├── .gitignore ├── Faketoshi.cabal ├── LICENSE ├── README.md ├── Setup.hs ├── app └── Main.hs ├── package.yaml ├── src └── Faketoshi.hs └── stack.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .stack-work 2 | -------------------------------------------------------------------------------- /Faketoshi.cabal: -------------------------------------------------------------------------------- 1 | -- This file has been generated from package.yaml by hpack version 0.28.2. 2 | -- 3 | -- see: https://github.com/sol/hpack 4 | -- 5 | -- hash: 87763b2d0a1912e38b1c2c2fe373d729591ac21ffbc602c80769b6fc36d96f4c 6 | 7 | name: Faketoshi 8 | version: 0.1.0.0 9 | description: Please see the README on GitHub at 10 | homepage: https://github.com/albacorelabs/Faketoshi#readme 11 | bug-reports: https://github.com/albacorelabs/Faketoshi/issues 12 | author: Albacore 13 | maintainer: albacore.io 14 | copyright: 2018 Albacore 15 | license: MIT 16 | license-file: LICENSE 17 | build-type: Simple 18 | cabal-version: >= 1.10 19 | extra-source-files: 20 | README.md 21 | 22 | source-repository head 23 | type: git 24 | location: https://github.com/albacorelabs/Faketoshi 25 | 26 | library 27 | exposed-modules: 28 | Faketoshi 29 | other-modules: 30 | Paths_Faketoshi 31 | hs-source-dirs: 32 | src 33 | build-depends: 34 | base >=4.7 && <5 35 | , cryptonite 36 | default-language: Haskell2010 37 | 38 | executable Faketoshi-exe 39 | main-is: Main.hs 40 | other-modules: 41 | Paths_Faketoshi 42 | hs-source-dirs: 43 | app 44 | ghc-options: -threaded -rtsopts -with-rtsopts=-N -dynamic -Wall -Werror 45 | build-depends: 46 | Faketoshi 47 | , base >=4.7 && <5 48 | , cryptonite 49 | default-language: Haskell2010 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Albacore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Faketoshi 2 | 3 | 4 | With everyone seemingly trying to prove they are Satoshi (looking at you [Craig Wright](https://en.bitcoin.it/wiki/Craig_Wright) and the recent["faketoshi twitter"](https://archive.fo/Br5Tl)), we've decided to make it easier for other people to make similar claims. 5 | 6 | Credit to Greg Maxwell and Pieter Wuille whose various posts ( 7 | [here](https://www.reddit.com/r/btc/comments/9xpivk/satoshi_i_do_not_want_to_be_public_but_there_is/e9uo87m/), 8 | [here](https://twitter.com/pwuille/status/1063582706288586752), and 9 | [here](https://bitcoin.stackexchange.com/questions/81115/if-someone-wanted-to-pretend-to-be-satoshi-by-posting-a-fake-signature-to-defrau) 10 | ) gave us enough of an understanding to implement our own Faketoshi-forger. We encourage you to check these resources out to understand why these continued Satoshi claims are nothing more than frauds. 11 | 12 | The following implementation creates a signature (s) from a message hash (H(m)) that will validate against the public key from the genesis block. (Although it can easily be extended for **any Satoshi public key**). The trick is that the message (m), the pre-image of the message hash, itself cannot be known or derived. Thus this, and the other claims using the construction, is an existensial forgery. 13 | 14 | You can browse to https://albacore.io/faketoshi for an generator in js that uses a similar construction. 15 | 16 | ### How to use 17 | ``` 18 | git clone git@github.com:albacorelabs/Libra.git 19 | stack build 20 | stack exec Faketoshi-exe 21 | 22 | /* Optional */ 23 | Post output on twitter claiming to be Satoshi 24 | ``` -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /app/Main.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Faketoshi 4 | import Control.Monad.IO.Class (liftIO) 5 | 6 | main :: IO () 7 | main = do 8 | let xCoord = "678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb6" -- xCoord from Genesis Block Pubkey 9 | let yCoord = "49f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f" -- yCoord from Genesis Block Pubkey 10 | Just forgery <- liftIO $ generate_forgery xCoord yCoord 11 | if valid_forgery forgery then 12 | putStrLn $ show forgery 13 | else 14 | putStrLn "Couldn't make you Satoshi - sorry" 15 | 16 | 17 | -------------------------------------------------------------------------------- /package.yaml: -------------------------------------------------------------------------------- 1 | name: Faketoshi 2 | version: 0.1.0.0 3 | github: "albacorelabs/Faketoshi" 4 | license: MIT 5 | author: "Albacore" 6 | maintainer: "albacore.io" 7 | copyright: "2018 Albacore" 8 | 9 | extra-source-files: 10 | - README.md 11 | 12 | description: Please see the README on GitHub at 13 | 14 | dependencies: 15 | - base >= 4.7 && < 5 16 | - cryptonite 17 | 18 | library: 19 | source-dirs: src 20 | 21 | executables: 22 | Faketoshi-exe: 23 | main: Main.hs 24 | source-dirs: app 25 | ghc-options: 26 | - -threaded 27 | - -rtsopts 28 | - -with-rtsopts=-N 29 | - -dynamic 30 | - -Wall 31 | - -Werror 32 | dependencies: 33 | - Faketoshi -------------------------------------------------------------------------------- /src/Faketoshi.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RecordWildCards #-} 2 | 3 | module Faketoshi (valid_forgery,generate_forgery,Faketoshi_Credentials) where 4 | 5 | import Numeric 6 | import Crypto.PubKey.ECC.Prim 7 | import Crypto.PubKey.ECC.Types 8 | import Crypto.PubKey.ECC.ECDSA 9 | import Crypto.Number.ModArithmetic 10 | import Crypto.Number.Generate 11 | import Crypto.Random.Types 12 | 13 | 14 | data Faketoshi_Credentials = Faketoshi_Credentials { 15 | sig :: Signature, 16 | msg :: Integer, 17 | pubKey :: PublicKey 18 | } 19 | 20 | instance Show Faketoshi_Credentials where 21 | show (Faketoshi_Credentials s m p) = "Sigs: " ++ show s ++ "\nMsg Hash: " ++ show m ++ "\nPublic Key: " ++ show (public_q p) 22 | 23 | valid_forgery :: Faketoshi_Credentials -> Bool 24 | valid_forgery Faketoshi_Credentials{..} = hashless_verify pubKey sig msg 25 | 26 | -- Copied from Cryptonite ECDSA (https://hackage.haskell.org/package/cryptonite) just removing the hashing of the message 27 | hashless_verify :: PublicKey -> Signature -> Integer -> Bool 28 | hashless_verify (PublicKey _ PointO) _ _ = False 29 | hashless_verify pk@(PublicKey curve q) (Signature r s) msg 30 | | r < 1 || r >= n || s < 1 || s >= n = False 31 | | otherwise = maybe False (r ==) $ do 32 | w <- inverse s n 33 | let z = msg -- removed hash here or we ACTUALLY have to know the preimage of the forged hash 34 | u1 = z * w `mod` n 35 | u2 = r * w `mod` n 36 | x = pointAddTwoMuls curve u1 g u2 q 37 | case x of 38 | PointO -> Nothing 39 | Point x1 _ -> return $ x1 `mod` n 40 | where 41 | n = ecc_n cc 42 | g = ecc_g cc 43 | cc = common_curve $ public_curve pk 44 | 45 | generate_forgery :: MonadRandom m => String -> String -> m (Maybe Faketoshi_Credentials) 46 | generate_forgery x_coord y_coord = do 47 | let crv = getCurveByName SEC_p256k1 48 | let ((x_int,_):_) = readHex x_coord 49 | let ((y_int,_):_) = readHex y_coord 50 | let public_point = Point (x_int :: Integer) (y_int :: Integer) 51 | let curve_order = ((ecc_n . common_curve) crv) 52 | a <- generateMax ((ecc_n . common_curve) crv) 53 | b <- generateMax ((ecc_n . common_curve) crv) 54 | case inverse b curve_order of 55 | Just invB -> do 56 | let (Point rx _) = pointAdd crv (pointBaseMul crv a) (pointMul crv b public_point) 57 | 58 | let sig = Signature rx ((rx * invB) `mod` curve_order) 59 | let msg = (rx * a * invB) `mod` curve_order 60 | return $ Just $ Faketoshi_Credentials sig msg (PublicKey crv public_point) 61 | Nothing -> return Nothing 62 | 63 | 64 | -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by 'stack init' 2 | # 3 | # Some commonly used options have been documented as comments in this file. 4 | # For advanced use and comprehensive documentation of the format, please see: 5 | # https://docs.haskellstack.org/en/stable/yaml_configuration/ 6 | 7 | # Resolver to choose a 'specific' stackage snapshot or a compiler version. 8 | # A snapshot resolver dictates the compiler version and the set of packages 9 | # to be used for project dependencies. For example: 10 | # 11 | # The location of a snapshot can be provided as a file or url. Stack assumes 12 | # a snapshot provided as a file might change, whereas a url resource does not. 13 | # 14 | # resolver: ./custom-snapshot.yaml 15 | # resolver: https://example.com/snapshots/2018-01-01.yaml 16 | resolver: lts-12.19 17 | 18 | # User packages to be built. 19 | # Various formats can be used as shown in the example below. 20 | # 21 | # packages: 22 | # - some-directory 23 | # - https://example.com/foo/bar/baz-0.0.2.tar.gz 24 | # - location: 25 | # git: https://github.com/commercialhaskell/stack.git 26 | # commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a 27 | # - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a 28 | # subdirs: 29 | # - auto-update 30 | # - wai 31 | packages: 32 | - . 33 | # Dependency packages to be pulled from upstream that are not in the resolver 34 | # using the same syntax as the packages field. 35 | # (e.g., acme-missiles-0.3) 36 | # extra-deps: [] 37 | 38 | # Override default flag values for local packages and extra-deps 39 | # flags: {} 40 | 41 | # Extra package databases containing global packages 42 | # extra-package-dbs: [] 43 | 44 | # Control whether we use the GHC we find on the path 45 | # system-ghc: true 46 | # 47 | # Require a specific version of stack, using version ranges 48 | # require-stack-version: -any # Default 49 | # require-stack-version: ">=1.7" 50 | # 51 | # Override the architecture used by stack, especially useful on Windows 52 | # arch: i386 53 | # arch: x86_64 54 | # 55 | # Extra directories used by stack for building 56 | # extra-include-dirs: [/path/to/dir] 57 | # extra-lib-dirs: [/path/to/dir] 58 | # 59 | # Allow a newer minor version of GHC than the snapshot specifies 60 | # compiler-check: newer-minor --------------------------------------------------------------------------------