1 /** 2 * Wallet records to store the wallet information 3 */ 4 module tagion.wallet.WalletRecords; 5 6 import tagion.basic.Types : Buffer; 7 import tagion.crypto.SecureInterfaceNet : HashNet; 8 import tagion.crypto.Types : Pubkey; 9 import tagion.dart.DARTBasic; 10 import tagion.hibon.Document : Document; 11 import tagion.hibon.HiBONRecord; 12 import tagion.wallet.Basic : saltHash; 13 import tagion.wallet.KeyRecover : KeyRecover; 14 15 /// Contains the quiz question 16 @safe 17 @recordType("Quiz") 18 struct Quiz { 19 @label("$Q") string[] questions; /// List of questions 20 mixin HiBONRecord; 21 } 22 23 /// Devices recovery for the pincode 24 @safe 25 @recordType("PIN") 26 struct DevicePIN { 27 Buffer D; /// Device number 28 Buffer U; /// Device random 29 Buffer S; /// Check sum value 30 bool recover( 31 const HashNet net, 32 ref scope ubyte[] R, 33 scope const(ubyte[]) P) const { 34 import tagion.utils.Miscellaneous : xor; 35 36 const pinhash = net.saltHash(P, U); 37 xor(R, D, pinhash); 38 return S == net.saltHash(R); 39 } 40 41 void setPin( 42 scope const HashNet net, 43 scope const(ubyte[]) R, 44 scope const(ubyte[]) P, 45 Buffer salt) scope { 46 import tagion.utils.Miscellaneous : xor; 47 48 U = salt; 49 const pinhash = net.saltHash(P, U); 50 D = xor(R, pinhash); 51 S = net.saltHash(R); 52 53 } 54 55 mixin HiBONRecord; 56 } 57 58 @safe 59 unittest { 60 import std.array; 61 import std.random; 62 import std.range; 63 import std.string : representation; 64 import tagion.crypto.SecureNet : StdHashNet; 65 import tagion.hibon.HiBONJSON; 66 import tagion.utils.Miscellaneous; 67 68 auto rnd = Random(unpredictableSeed); 69 auto rnd_range = generate!(() => uniform!ubyte(rnd)); 70 const net = new StdHashNet; 71 //auto R=new ubyte[net.hashSize]; 72 { 73 auto salt = iota(ubyte(0), ubyte(net.hashSize & ubyte.max)).array.idup; 74 const R = rnd_range.take(net.hashSize).array; 75 DevicePIN pin; 76 const pin_code = "1234".representation; 77 pin.setPin(net, R, pin_code, salt); 78 79 ubyte[] recovered_R = new ubyte[net.hashSize]; 80 { /// Recover the seed R with the correct pin-code 81 const recovered = pin.recover(net, recovered_R, pin_code); 82 assert(recovered); 83 assert(R == recovered_R); 84 } 85 86 { /// Try to recover the seed R with the wrong pin-code 87 const recovered = pin.recover(net, recovered_R, "wrong pin code".representation); 88 assert(!recovered); 89 assert(R != recovered_R); 90 } 91 92 } 93 } 94 /// Key-pair recovery generator 95 @safe 96 @recordType("Wallet") 97 struct RecoverGenerator { 98 Buffer[] Y; /// Recorvery seed 99 Buffer S; /// Check value S=H(H(R)) 100 @label("N") uint confidence; /// Confidence of the correct answers 101 mixin HiBONRecord; 102 }