Pascal (Lazarus/Delphi)
Pascal (Lazarus/Delphi)
ECDSA Sign and Verify
See more ECC Examples
Demonstrates how to create an ECDSA signature on the SHA256 hash of some data, and then verify.Chilkat Pascal (Lazarus/Delphi) Downloads
program ChilkatDemo;
// Demonstrates using the Chilkat Pascal wrapper via the C bridge DLL.
// Builds as a console application under Lazarus (FPC) or Delphi.
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
SysUtils,
CkDllLoader,
Chilkat.Asn,
Chilkat.Prng,
Chilkat.BinData,
Chilkat.PrivateKey,
Chilkat.PublicKey,
Chilkat.Xml,
Chilkat.Crypt2,
Chilkat.Ecc;
// ---------------------------------------------------------------------------
procedure RunDemo;
var
success: Boolean;
privKey: TPrivateKey;
bd: TBinData;
crypt: TCrypt2;
hashStr: string;
ecdsa: TEcc;
prng: TPrng;
sig: string;
asn: TAsn;
xml: TXml;
r: string;
s: string;
pubKey: TPublicKey;
ecc2: TEcc;
result: Integer;
xml2: TXml;
asn2: TAsn;
encodedSig: string;
begin
success := False;
// This example assumes the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// First load an ECDSA private key to be used for signing.
privKey := TPrivateKey.Create;
success := privKey.LoadEncryptedPemFile('qa_data/ecc/secp256r1-key-pkcs8-secret.pem','secret');
if (success = False) then
begin
WriteLn(privKey.LastErrorText);
Exit;
end;
// Sign the SHA256 hash of some data.
bd := TBinData.Create;
success := bd.LoadFile('qa_data/hamlet.xml');
if (success = False) then
begin
WriteLn('Failed to load file to be hashed.');
Exit;
end;
crypt := TCrypt2.Create;
crypt.HashAlgorithm := 'sha256';
crypt.EncodingMode := 'base64';
hashStr := crypt.HashBdENC(bd);
ecdsa := TEcc.Create;
prng := TPrng.Create;
// Returns ASN.1 signature as a base64 string.
sig := ecdsa.SignHashENC(hashStr,'base64',privKey,prng);
WriteLn('sig = ' + sig);
// The signature is in ASN.1 format (which may be described as the "encoded DSS signature").
// SEQUENCE (2 elem)
// INTEGER (255 bit) 4849395540832462044300553275435608522154141569743642905628579547100940...
// INTEGER (255 bit) 3680701124244788134409868118208591399799457104230118295614152238560005...
// If you wish, you can get the r and s components of the signature like this:
asn := TAsn.Create;
asn.LoadEncoded(sig,'base64');
xml := TXml.Create;
xml.LoadXml(asn.AsnToXml());
WriteLn(xml.GetXml());
// We now have this:
// <?xml version="1.0" encoding="utf-8"?>
// <sequence>
// <int>6650D422D86BA4A228B5617604E59052591B9B2C32EF324C44D09EF67E5F0060</int>
// <int>0CFD9F6AC85042FC70F672C141BA6B2A4CAFBB906C3D907BCCC1BED62B28326F</int>
// </sequence>
// Get the "r" and "s" as hex strings
r := xml.GetChildContentByIndex(0);
s := xml.GetChildContentByIndex(1);
WriteLn('r = ' + r);
WriteLn('s = ' + s);
// --------------------------------------------------------------------
// Now verify against the hash of the original data.
// Get the corresponding public key.
pubKey := TPublicKey.Create;
success := pubKey.LoadFromFile('qa_data/ecc/secp256r1-pub.pem');
if (success = False) then
begin
WriteLn(pubKey.LastErrorText);
Exit;
end;
// We already have the SHA256 hash of the original data (hashStr) so no need to re-do it..
ecc2 := TEcc.Create;
result := ecc2.VerifyHashENC(hashStr,sig,'base64',pubKey);
if (result <> 1) then
begin
WriteLn(ecc2.LastErrorText);
Exit;
end;
WriteLn('Verified!');
// Note: If we have only r,s and wish to reconstruct the ASN.1 signature, we do it like this:
xml2 := TXml.Create;
xml2.Tag := 'sequence';
xml2.NewChild2('int',r);
xml2.NewChild2('int',s);
asn2 := TAsn.Create;
asn2.LoadAsnXml(xml2.GetXml());
encodedSig := asn2.GetEncodedDer('base64');
WriteLn('encoded DSS signature: ' + encodedSig);
// You can go to https://lapo.it/asn1js/ and copy/paste the base64 encodedSig into the online tool, then press the "decode" button.
// You will see the ASN.1 such as this:
// SEQUENCE (2 elem)
// INTEGER (255 bit) 4849395540832462044300553275435608522154141569743642905628579547100940...
// INTEGER (255 bit) 3680701124244788134409868118208591399799457104230118295614152238560005...
privKey.Free;
bd.Free;
crypt.Free;
ecdsa.Free;
prng.Free;
asn.Free;
xml.Free;
pubKey.Free;
ecc2.Free;
xml2.Free;
asn2.Free;
end;
// ---------------------------------------------------------------------------
begin
try
RunDemo;
except
on E: Exception do
WriteLn('Unhandled exception: ', E.ClassName, ': ', E.Message);
end;
WriteLn;
{$IFDEF MSWINDOWS}
WriteLn('Press Enter to exit...');
ReadLn;
{$ENDIF}
end.