5 type tEccKey
=ed25519
.tKey32
;
6 type tPoWRec
=packed record
8 stamp
:LongWord
; {NetOrder}
11 var SecretKey
:ed25519
.tKey64
;
12 var PublicKey
:tEccKey
;
13 var PublicPoW
:tPoWRec
;
14 var ZeroDigest
:tSha1Digest
;
15 const cDig3PowMask
=%0010;
16 const cPoWValidDays
=5;
18 procedure CreateChallenge(out Challenge
: tEccKey
);
19 procedure CreateResponse(const Challenge
: tEccKey
; out Response
: tSha1Digest
; const srce
:tEccKey
);
20 function VerifyPoW(const proof
:tPoWRec
; const RemotePub
:tEccKey
):boolean;
22 operator
:=(k
:tEccKey
) s
:string;
25 uses SysUtils
,StrUtils
,DateUtils
;
27 procedure CreateChallenge(out Challenge
: tEccKey
);
30 for i
:=0 to 31 do challenge
[i
]:=Random(256);
33 procedure CreateResponse(const Challenge
: tEccKey
; out Response
: tSha1Digest
; const srce
:tEccKey
);
35 var shactx
:tSha1Context
;
37 ed25519
.SharedSecret(shared
,srce
,secretkey
);
39 Sha1Update(shactx
,challenge
,sizeof(challenge
));
40 Sha1Update(shactx
,shared
,sizeof(shared
));
41 Sha1Final(shactx
,Response
);
46 function VerifyPoW(const proof
:tPoWRec
; const RemotePub
:tEccKey
):boolean;
47 var shactx
:tSha1Context
;
48 var digest
:tSha1Digest
;
51 delta
:=TSNow
-BEtoN(proof
.stamp
);
52 if (delta
<=cPoWValidDays
) and (delta
>=-1) then begin
54 Sha1Update(shactx
,proof
,sizeof(proof
));
55 Sha1Update(shactx
,RemotePub
,sizeof(RemotePub
));
56 Sha1Final(shactx
,digest
);
57 result
:=(CompareByte(digest
,ZeroDigest
,3)=0)and((digest
[3]and cDig3PoWMask
)=0);
58 end else result
:=false;
61 const cPoWFN
='proof.dat';
62 procedure PoWLoadFromFile
;
63 var f
:file of tPoWRec
;
70 procedure PoWGenerate
;
71 var f
:file of tPoWRec
;
78 write('ECC: Generating PoW, this may take a while...');
79 PublicPow
.stamp
:=NtoBE(TSNow
);
80 Start
:=Now
; counter
:=0;
82 for i
:=0 to 31 do PublicPoW
.data
[i
]:=Random(256);
84 until VerifyPoW(PublicPoW
,PublicKey
);
85 writeln(' PoW found in ',(Now
-start
)*SecsPerDay
:1:0,'s speed=',counter
/((Now
-start
)*SecsPerDay
):1:0,'h/s');
90 const cSeckeyFN
='secret.dat';
91 procedure LoadFromFile
;
92 var f
:file of ed25519
.tPrivKey
;
100 procedure SaveGenerated
;
101 var f
:file of ed25519
.tPrivKey
;
112 var f
:file of ed25519
.tPrivKey
;
114 assign(f
,'/dev/urandom');
120 {$WARNING Not enough Random in windows license key}
121 {$ERROR This unit requires UNIX-compatile operating system}
125 procedure DerivePublic
;
127 CreatekeyPair(PublicKey
,SecretKey
);
130 operator
:=(k
:tEccKey
) s
:string;
133 BinToHex(@k
,@s
[1],32);
137 FillChar(ZeroDigest
,sizeof(ZeroDigest
),0);
138 TSNow
:=trunc(Now
-cTSEpoch
);
139 //writeln('ECC: Today is W',TSNow);
141 except on e
:Exception
do begin
142 writeln('ECC: '+cSecKeyFN
+' '+e
.message+' while loading secret key, generating new keypair');
144 (*until (PublicKey[31]=0)and(PublicKey[30]=0);*)
148 writeln('ECC: pubkey is ',string(PublicKey
));
151 if not VerifyPoW(PublicPoW
,PublicKey
)
152 then raise eXception
.Create('invalid or expired proof');
153 if (TSNow
-BEtoN(PublicPow
.Stamp
))>=cPoWValidDays
154 then raise eXception
.Create('proof about to expire');
155 except on e
:Exception
do begin
156 writeln('ECC: '+cPOWFN
+' '+e
.message+' while loading proof');
159 //writeln('ECC: ProofOfWork valid for W',BEtoN(PublicPow.Stamp));