11import { secp256k1 } from "ethereum-cryptography/secp256k1" ;
22import { sha256 } from "ethereum-cryptography/sha256" ;
33import { ripemd160 } from "ethereum-cryptography/ripemd160" ;
4- import { toHex , utf8ToBytes } from "ethereum-cryptography/utils" ;
4+ import { toHex } from "ethereum-cryptography/utils" ;
55
6+ // Custom imports
7+ const elliptic = require ( 'elliptic' ) ;
8+ const ec = new elliptic . ec ( 'secp256k1' ) ;
9+ const crypto = require ( 'crypto-browserify' ) ;
10+
11+ // PRNG
12+ function * block_generator ( seed ) {
13+ let counter = 0 ;
14+ while ( true ) {
15+ for ( const byte of crypto . createHash ( 'sha256' ) . update ( "prng-" + counter . toString ( ) + "-" + seed ) . digest ( ) ) {
16+ yield byte ;
17+ }
18+ counter ++ ;
19+ }
20+ }
21+
22+ class PRNG {
23+ generator ;
24+ constructor ( seed ) {
25+ this . generator = block_generator ( seed ) ;
26+ }
27+
28+ get_bytes ( n ) {
29+ let a = new Uint8Array ( n ) ;
30+ for ( let i = 0 ; i < n ; i ++ ) {
31+ a [ i ] = this . generator . next ( ) . value ;
32+ }
33+ return a ;
34+ }
35+ }
36+
37+ // workaround
38+ function uint8_to_byte_literal ( uint8 ) {
39+ const bytes = [ "\\x00" , "\\x01" , "\\x02" , "\\x03" , "\\x04" , "\\x05" , "\\x06" ,
40+ "\\x07" , "\\x08" , "\\t" , "\\n" , "\\x0b" , "\\x0c" , "\\r" , "\\x0e" , "\\x0f" , "\\x10" ,
41+ "\\x11" , "\\x12" , "\\x13" , "\\x14" , "\\x15" , "\\x16" , "\\x17" , "\\x18" , "\\x19" ,
42+ "\\x1a" , "\\x1b" , "\\x1c" , "\\x1d" , "\\x1e" , "\\x1f" , " " , "!" , "\"" , "#" , "$" ,
43+ "%" , "&" , "'" , "(" , ")" , "*" , "+" , "," , "-" , "." , "/" , "0" , "1" , "2" , "3" ,
44+ "4" , "5" , "6" , "7" , "8" , "9" , ":" , ";" , "<" , "=" , ">" , "?" , "@" , "A" , "B" ,
45+ "C" , "D" , "E" , "F" , "G" , "H" , "I" , "J" , "K" , "L" , "M" , "N" , "O" , "P" , "Q" ,
46+ "R" , "S" , "T" , "U" , "V" , "W" , "X" , "Y" , "Z" , "[" , "\\\\" , "]" , "^" , "_" , "`" ,
47+ "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" , "i" , "j" , "k" , "l" , "m" , "n" , "o" ,
48+ "p" , "q" , "r" , "s" , "t" , "u" , "v" , "w" , "x" , "y" , "z" , "{" , "|" , "}" , "~" ,
49+ "\\x7f" , "\\x80" , "\\x81" , "\\x82" , "\\x83" , "\\x84" , "\\x85" , "\\x86" , "\\x87" ,
50+ "\\x88" , "\\x89" , "\\x8a" , "\\x8b" , "\\x8c" , "\\x8d" , "\\x8e" , "\\x8f" , "\\x90" ,
51+ "\\x91" , "\\x92" , "\\x93" , "\\x94" , "\\x95" , "\\x96" , "\\x97" , "\\x98" , "\\x99" ,
52+ "\\x9a" , "\\x9b" , "\\x9c" , "\\x9d" , "\\x9e" , "\\x9f" , "\\xa0" , "\\xa1" , "\\xa2" ,
53+ "\\xa3" , "\\xa4" , "\\xa5" , "\\xa6" , "\\xa7" , "\\xa8" , "\\xa9" , "\\xaa" , "\\xab" ,
54+ "\\xac" , "\\xad" , "\\xae" , "\\xaf" , "\\xb0" , "\\xb1" , "\\xb2" , "\\xb3" , "\\xb4" ,
55+ "\\xb5" , "\\xb6" , "\\xb7" , "\\xb8" , "\\xb9" , "\\xba" , "\\xbb" , "\\xbc" , "\\xbd" ,
56+ "\\xbe" , "\\xbf" , "\\xc0" , "\\xc1" , "\\xc2" , "\\xc3" , "\\xc4" , "\\xc5" , "\\xc6" ,
57+ "\\xc7" , "\\xc8" , "\\xc9" , "\\xca" , "\\xcb" , "\\xcc" , "\\xcd" , "\\xce" , "\\xcf" ,
58+ "\\xd0" , "\\xd1" , "\\xd2" , "\\xd3" , "\\xd4" , "\\xd5" , "\\xd6" , "\\xd7" , "\\xd8" ,
59+ "\\xd9" , "\\xda" , "\\xdb" , "\\xdc" , "\\xdd" , "\\xde" , "\\xdf" , "\\xe0" , "\\xe1" ,
60+ "\\xe2" , "\\xe3" , "\\xe4" , "\\xe5" , "\\xe6" , "\\xe7" , "\\xe8" , "\\xe9" , "\\xea" ,
61+ "\\xeb" , "\\xec" , "\\xed" , "\\xee" , "\\xef" , "\\xf0" , "\\xf1" , "\\xf2" , "\\xf3" ,
62+ "\\xf4" , "\\xf5" , "\\xf6" , "\\xf7" , "\\xf8" , "\\xf9" , "\\xfa" , "\\xfb" , "\\xfc" ,
63+ "\\xfd" , "\\xfe" , "\\xff" ]
64+ return bytes [ uint8 ] ;
65+ }
66+
67+ // expects mnemonic phrase as string in format: "word1 word2 word3 word4 word5..."
68+ // returns private key as integer (point on curve)
69+ function warthog_mnemo_to_pk ( mnemo ) {
70+ let order = BigInt ( 115792089237316195423570985008687907852837564279074904382605163141518161494337 ) ;
71+ let bytes = 32 ;
72+
73+ let mnemo_hash = crypto . pbkdf2Sync ( mnemo , 'mnemonic' , 2048 , 64 , 'sha512' ) ;
74+
75+ let seed = "" ;
76+ for ( const byte of mnemo_hash ) {
77+ seed += uint8_to_byte_literal ( byte ) ;
78+ }
79+ if ( seed . includes ( "'" ) ) {
80+ seed = "b\"" + seed + "\"" ;
81+ } else {
82+ seed = "b'" + seed + "'" ;
83+ }
84+
85+ let prng = new PRNG ( seed ) ;
86+ while ( true ) {
87+ let extrabyte = new Uint8Array ( 1 ) ;
88+ extrabyte [ 0 ] = prng . get_bytes ( 1 ) [ 0 ] & 1 ;
89+
90+ let guess = new Uint8Array ( 33 ) ;
91+ guess . set ( extrabyte ) ;
92+ guess . set ( prng . get_bytes ( bytes ) , 1 ) ;
93+ let guess_int = BigInt ( "0x" + Buffer . from ( guess ) . toString ( 'hex' ) ) ;
94+
95+ // Compare to both variables to fix the type comparision issue
96+ if ( BigInt ( 1 ) <= guess_int && guess_int < order ) {
97+ return guess_int + BigInt ( 1 ) ;
98+ }
99+ }
100+ }
101+
102+
103+ // Wartlock implementations
6104export async function walletFromSeed ( seed : string ) : Promise < { address : string ; privateKey : string } > {
7- const seedBytes = utf8ToBytes ( seed ) ;
8- const privateKey = derivePrivateKey ( seedBytes ) ;
105+ const privateKeyHex = ec . keyFromPrivate ( warthog_mnemo_to_pk ( seed ) , 10 ) . getPrivate ( ) . toString ( "hex" ) ;
106+ const privateKey = new Uint8Array ( Buffer . from ( privateKeyHex , "hex" ) ) ;
9107 const publicKey = secp256k1 . getPublicKey ( privateKey , true ) ;
10108 const address = addressFromPublicKey ( publicKey ) ;
11109
@@ -21,15 +119,11 @@ export async function walletFromPkHex(pkHex) {
21119 } ;
22120}
23121
24- function derivePrivateKey ( seed ) {
25- const hash = sha256 ( seed ) ;
26- return hash . slice ( 0 , 32 ) ;
27- }
28-
29122function addressFromPublicKey ( publicKey ) {
30123 const sha256Hash = sha256 ( publicKey ) ;
31124 const ripemd160Hash = ripemd160 ( sha256Hash ) ;
32125 const checksum = sha256 ( ripemd160Hash ) . slice ( 0 , 4 ) ;
33126 const addressBytes = new Uint8Array ( [ ...ripemd160Hash , ...checksum ] ) ;
34127 return toHex ( addressBytes ) ;
35128}
129+
0 commit comments