| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925 |
- { *********************************************************************************** }
- { * CryptoLib Library * }
- { * Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe * }
- { * Github Repository <https://github.com/Xor-el> * }
- { * Distributed under the MIT software license, see the accompanying file LICENSE * }
- { * or visit http://www.opensource.org/licenses/mit-license.php. * }
- { * Acknowledgements: * }
- { * * }
- { * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * }
- { * development of this library * }
- { * ******************************************************************************* * }
- (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
- unit UsageExamples;
- {$IFDEF FPC}
- {$MODE DELPHI}
- {$HINTS OFF}
- {$WARNINGS OFF}
- {$ENDIF FPC}
- interface
- uses
- SysUtils,
- ClpIDigest,
- ClpIDigestMAC,
- ClpDigestUtilities,
- ClpBigInteger,
- ClpSecureRandom,
- ClpISecureRandom,
- ClpIX9ECParameters,
- ClpIECDomainParameters,
- ClpECDomainParameters,
- ClpIECKeyPairGenerator,
- ClpECKeyPairGenerator,
- ClpIECKeyGenerationParameters,
- ClpECKeyGenerationParameters,
- ClpIAsymmetricCipherKeyPair,
- ClpAsymmetricCipherKeyPair,
- ClpIECPrivateKeyParameters,
- ClpIECPublicKeyParameters,
- ClpECPublicKeyParameters,
- ClpECPrivateKeyParameters,
- ClpIAsymmetricKeyParameter,
- ClpECSchnorrSigner,
- ClpIECInterface,
- ClpECPoint,
- ClpISigner,
- ClpSignerUtilities,
- ClpParametersWithIV,
- ClpIParametersWithIV,
- ClpIBufferedCipher,
- ClpIBufferedBlockCipher,
- // ClpIIESEngine,
- // ClpIESEngine,
- ClpPascalCoinIESEngine,
- ClpIPascalCoinIESEngine,
- ClpIIESWithCipherParameters,
- ClpIESWithCipherParameters,
- ClpIAesEngine,
- ClpAesEngine,
- ClpICbcBlockCipher,
- ClpCbcBlockCipher,
- ClpIZeroBytePadding,
- ClpZeroBytePadding,
- ClpIIESCipher,
- ClpIESCipher,
- ClpIECDHBasicAgreement,
- ClpECDHBasicAgreement,
- ClpIPascalCoinECIESKdfBytesGenerator,
- ClpPascalCoinECIESKdfBytesGenerator,
- ClpPaddedBufferedBlockCipher,
- ClpParameterUtilities,
- ClpCipherUtilities,
- ClpGeneratorUtilities,
- ClpIAsymmetricCipherKeyPairGenerator,
- ClpArrayUtils,
- ClpHex,
- ClpSecNamedCurves;
- type
- TUsageExamples = class sealed(TObject)
- strict private
- const
- /// <summary>
- /// supported curves are secp256k1, sect283k1, secp384r1 and secp521r1
- /// </summary>
- CurveName = 'secp256k1';
- /// <summary>
- /// supported signing algorithms are NONEwithECDSA, SHA-1withECDSA, <br />
- /// SHA-224withECDSA, SHA-256withECDSA, SHA-384withECDSA,
- /// SHA-512withECDSA and RIPEMD160withECDSA
- /// </summary>
- SigningAlgorithmECDSA = 'SHA-1withECDSA';
- SigningAlgorithmECSCHNORR = 'SHA-256withECSCHNORRLIBSECP';
- PKCS5_SALT_LEN = Int32(8);
- SALT_MAGIC_LEN = Int32(8);
- SALT_SIZE = Int32(8);
- SALT_MAGIC: String = 'Salted__';
- class var
- FRandom: ISecureRandom;
- FCurve: IX9ECParameters;
- class function BytesToHexString(input: TBytes): String; static;
- class constructor UsageExamples();
- private
- class procedure DoSigningAndVerifying(const PublicKey
- : IECPublicKeyParameters; const PrivateKey: IECPrivateKeyParameters;
- const CallerMethod, TextToSign: String;
- const SigningAlgo: String = SigningAlgorithmECDSA); static;
- class function EVP_GetSalt(): TBytes; static; inline;
- class function EVP_GetKeyIV(PasswordBytes, SaltBytes: TBytes;
- out KeyBytes, IVBytes: TBytes): Boolean; static;
- class function AES256CBCPascalCoinEncrypt(PlainText, PasswordBytes: TBytes)
- : TBytes; static;
- class function AES256CBCPascalCoinDecrypt(CipherText, PasswordBytes: TBytes;
- out PlainText: TBytes): Boolean; static;
- class function GetECIESPascalCoinCompatibilityEngine
- : IPascalCoinIESEngine; static;
- class function GetECKeyPair: IAsymmetricCipherKeyPair; static;
- class function GetIESCipherParameters: IIESWithCipherParameters; static;
- class function ECIESPascalCoinEncrypt(const PublicKey
- : IAsymmetricKeyParameter; PlainText: TBytes): TBytes; static;
- class function ECIESPascalCoinDecrypt(const PrivateKey
- : IAsymmetricKeyParameter; CipherText: TBytes; out PlainText: TBytes)
- : Boolean; static;
- public
- class procedure GenerateKeyPairAndSignECDSA(); static;
- class procedure GenerateKeyPairAndSignECSchnorr(); static;
- class procedure GetPublicKeyFromPrivateKey(); static;
- class procedure RecreatePublicAndPrivateKeyPairsFromByteArray(); static;
- class procedure RecreatePublicKeyFromXAndYCoordByteArray; static;
- class procedure BinaryCompatiblePascalCoinAES256EncryptDecryptDemo
- (const inputmessage, password: string); static;
- class procedure BinaryCompatiblePascalCoinECIESEncryptDecryptDemo
- (const input: string); static;
- class procedure BinaryCompatiblePascalCoinECIESDecryptExistingPayloadDemo
- (const PrivateKeyInHex, EncryptedMessageInHex,
- ACurveName: string); static;
- end;
- implementation
- { TUsageExamples }
- class function TUsageExamples.ECIESPascalCoinDecrypt(const PrivateKey
- : IAsymmetricKeyParameter; CipherText: TBytes; out PlainText: TBytes)
- : Boolean;
- var
- CipherDecrypt: IIESCipher;
- begin
- // Decryption
- CipherDecrypt := TIESCipher.Create(GetECIESPascalCoinCompatibilityEngine);
- CipherDecrypt.Init(False, PrivateKey, GetIESCipherParameters, FRandom);
- PlainText := CipherDecrypt.DoFinal(CipherText);
- Result := True;
- end;
- class function TUsageExamples.ECIESPascalCoinEncrypt(const PublicKey
- : IAsymmetricKeyParameter; PlainText: TBytes): TBytes;
- var
- CipherEncrypt: IIESCipher;
- begin
- // Encryption
- CipherEncrypt := TIESCipher.Create(GetECIESPascalCoinCompatibilityEngine);
- CipherEncrypt.Init(True, PublicKey, GetIESCipherParameters, FRandom);
- Result := CipherEncrypt.DoFinal(PlainText);
- end;
- class function TUsageExamples.EVP_GetKeyIV(PasswordBytes, SaltBytes: TBytes;
- out KeyBytes, IVBytes: TBytes): Boolean;
- var
- LKey, LIV: integer;
- LDigest: IDigest;
- begin
- LKey := 32; // AES256 CBC Key Length
- LIV := 16; // AES256 CBC IV Length
- System.SetLength(KeyBytes, LKey);
- System.SetLength(IVBytes, LKey);
- // Max size to start then reduce it at the end
- LDigest := TDigestUtilities.GetDigest('SHA-256'); // SHA2_256
- System.Assert(LDigest.HashSize >= LKey);
- System.Assert(LDigest.HashSize >= LIV);
- // Derive Key First
- LDigest.TransformBytes(PasswordBytes);
- if SaltBytes <> Nil then
- begin
- LDigest.TransformBytes(SaltBytes);
- end;
- KeyBytes := System.Copy(LDigest.TransformFinal.GetBytes);
- // Derive IV Next
- LDigest.Initialize();
- LDigest.TransformBytes(KeyBytes);
- LDigest.TransformBytes(PasswordBytes);
- if SaltBytes <> Nil then
- begin
- LDigest.TransformBytes(SaltBytes);
- end;
- IVBytes := System.Copy(LDigest.TransformFinal.GetBytes);
- System.SetLength(IVBytes, LIV);
- Result := True;
- end;
- class function TUsageExamples.EVP_GetSalt: TBytes;
- begin
- System.SetLength(Result, PKCS5_SALT_LEN);
- FRandom.NextBytes(Result);
- end;
- class function TUsageExamples.AES256CBCPascalCoinDecrypt(CipherText,
- PasswordBytes: TBytes; out PlainText: TBytes): Boolean;
- var
- SaltBytes, KeyBytes, IVBytes, Buf, Chopped: TBytes;
- KeyParametersWithIV: IParametersWithIV;
- cipher: IBufferedCipher;
- LBufStart, LSrcStart, Count: Int32;
- begin
- Result := False;
- System.SetLength(SaltBytes, SALT_SIZE);
- // First read the magic text and the salt - if any
- Chopped := System.Copy(CipherText, 0, SALT_MAGIC_LEN);
- if (System.Length(CipherText) >= SALT_MAGIC_LEN) and
- (TArrayUtils.AreEqual(Chopped, TEncoding.UTF8.GetBytes(SALT_MAGIC))) then
- begin
- System.Move(CipherText[SALT_MAGIC_LEN], SaltBytes[0], SALT_SIZE);
- If not EVP_GetKeyIV(PasswordBytes, SaltBytes, KeyBytes, IVBytes) then
- begin
- Exit;
- end;
- LSrcStart := SALT_MAGIC_LEN + SALT_SIZE;
- end
- else
- begin
- If Not EVP_GetKeyIV(PasswordBytes, Nil, KeyBytes, IVBytes) then
- begin
- Exit;
- end;
- LSrcStart := 0;
- end;
- cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING');
- KeyParametersWithIV := TParametersWithIV.Create
- (TParameterUtilities.CreateKeyParameter('AES', KeyBytes), IVBytes);
- cipher.Init(False, KeyParametersWithIV); // init decryption cipher
- System.SetLength(Buf, System.Length(CipherText));
- LBufStart := 0;
- Count := cipher.ProcessBytes(CipherText, LSrcStart, System.Length(CipherText)
- - LSrcStart, Buf, LBufStart);
- System.Inc(LBufStart, Count);
- Count := cipher.DoFinal(Buf, LBufStart);
- System.Inc(LBufStart, Count);
- System.SetLength(Buf, LBufStart);
- PlainText := System.Copy(Buf);
- Result := True;
- end;
- class function TUsageExamples.AES256CBCPascalCoinEncrypt(PlainText,
- PasswordBytes: TBytes): TBytes;
- var
- SaltBytes, KeyBytes, IVBytes, Buf: TBytes;
- KeyParametersWithIV: IParametersWithIV;
- cipher: IBufferedCipher;
- LBlockSize, LBufStart, Count: Int32;
- begin
- SaltBytes := EVP_GetSalt;
- EVP_GetKeyIV(PasswordBytes, SaltBytes, KeyBytes, IVBytes);
- cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING');
- KeyParametersWithIV := TParametersWithIV.Create
- (TParameterUtilities.CreateKeyParameter('AES', KeyBytes), IVBytes);
- cipher.Init(True, KeyParametersWithIV); // init encryption cipher
- LBlockSize := cipher.GetBlockSize;
- System.SetLength(Buf, System.Length(PlainText) + LBlockSize + SALT_MAGIC_LEN +
- PKCS5_SALT_LEN);
- LBufStart := 0;
- System.Move(TEncoding.UTF8.GetBytes(SALT_MAGIC)[0], Buf[LBufStart],
- SALT_MAGIC_LEN * System.SizeOf(Byte));
- System.Inc(LBufStart, SALT_MAGIC_LEN);
- System.Move(SaltBytes[0], Buf[LBufStart],
- PKCS5_SALT_LEN * System.SizeOf(Byte));
- System.Inc(LBufStart, PKCS5_SALT_LEN);
- Count := cipher.ProcessBytes(PlainText, 0, System.Length(PlainText), Buf,
- LBufStart);
- System.Inc(LBufStart, Count);
- Count := cipher.DoFinal(Buf, LBufStart);
- System.Inc(LBufStart, Count);
- System.SetLength(Buf, LBufStart);
- Result := Buf;
- end;
- class procedure TUsageExamples.
- BinaryCompatiblePascalCoinAES256EncryptDecryptDemo(const inputmessage,
- password: string);
- var
- PlainText, PasswordBytes, CipherText, DecryptedCipherText: TBytes;
- begin
- PlainText := TEncoding.UTF8.GetBytes(inputmessage);
- PasswordBytes := TEncoding.UTF8.GetBytes(password);
- CipherText := TUsageExamples.AES256CBCPascalCoinEncrypt(PlainText,
- PasswordBytes);
- if TUsageExamples.AES256CBCPascalCoinDecrypt(CipherText, PasswordBytes,
- DecryptedCipherText) then
- begin
- if TArrayUtils.AreEqual(PlainText, DecryptedCipherText) then
- begin
- Writeln('AES_256_CBC PascalCoin Compatability Encrypt, Decrypt Was Successful '
- + sLineBreak);
- Exit;
- end;
- end;
- Writeln('AES_256_CBC PascalCoin Compatability Encrypt, Decrypt Failed ' +
- sLineBreak);
- end;
- class procedure TUsageExamples.
- BinaryCompatiblePascalCoinECIESDecryptExistingPayloadDemo
- (const PrivateKeyInHex, EncryptedMessageInHex, ACurveName: string);
- const
- MethodName = 'BinaryCompatiblePascalCoinECIESDecryptExistingPayloadDemo';
- var
- PrivateKeyBytes, PayloadToDecodeBytes, DecryptedCipherText: TBytes;
- Lcurve: IX9ECParameters;
- domain: IECDomainParameters;
- RegeneratedPublicKey: IECPublicKeyParameters;
- RegeneratedPrivateKey: IECPrivateKeyParameters;
- KeyPair: IAsymmetricCipherKeyPair;
- PrivD: TBigInteger;
- begin
- // Create From Existing Parameter Method
- System.Assert(PrivateKeyInHex <> '', 'PrivateKeyInHex Cannot be Empty');
- System.Assert(EncryptedMessageInHex <> '',
- 'EncryptedMessageInHex Cannot be Empty');
- System.Assert(ACurveName <> '', 'ACurveName Cannot be Empty');
- PrivateKeyBytes := THex.Decode(PrivateKeyInHex);
- System.Assert(PrivateKeyBytes <> Nil, 'PrivateKeyBytes Cannot be Nil');
- PayloadToDecodeBytes := THex.Decode(EncryptedMessageInHex);
- System.Assert(PayloadToDecodeBytes <> Nil,
- 'PayloadToDecodeBytes Cannot be Nil');
- Lcurve := TSecNamedCurves.GetByName(ACurveName);
- System.Assert(Lcurve <> Nil, 'Lcurve Cannot be Nil');
- // Set Up Asymmetric Key Pair from known private key ByteArray
- domain := TECDomainParameters.Create(Lcurve.Curve, Lcurve.G, Lcurve.N,
- Lcurve.H, Lcurve.GetSeed);
- PrivD := TBigInteger.Create(1, PrivateKeyBytes);
- RegeneratedPrivateKey := TECPrivateKeyParameters.Create('ECDSA',
- PrivD, domain);
- RegeneratedPublicKey := TECKeyPairGenerator.GetCorrespondingPublicKey
- (RegeneratedPrivateKey);
- KeyPair := TAsymmetricCipherKeyPair.Create(RegeneratedPublicKey,
- RegeneratedPrivateKey);
- // Do Signing and Verifying to Assert Proper Recreation Of Public and Private Key
- DoSigningAndVerifying(KeyPair.Public as IECPublicKeyParameters,
- KeyPair.Private as IECPrivateKeyParameters, MethodName, 'PascalECDSA');
- // Do Decryption Of Payload
- if TUsageExamples.ECIESPascalCoinDecrypt(RegeneratedPrivateKey,
- PayloadToDecodeBytes, DecryptedCipherText) then
- begin
- Writeln('ECIES PascalCoin Existing Payload Compatability Decrypt Was Successful '
- + sLineBreak);
- Writeln('Payload Message Is "' + TEncoding.UTF8.GetString
- (DecryptedCipherText) + '"');
- Exit;
- end;
- Writeln('ECIES PascalCoin Existing Payload Compatability Decrypt Failed ' +
- sLineBreak);
- end;
- class procedure TUsageExamples.BinaryCompatiblePascalCoinECIESEncryptDecryptDemo
- (const input: string);
- var
- PlainText, CipherText, DecryptedCipherText: TBytes;
- KeyPair: IAsymmetricCipherKeyPair;
- begin
- KeyPair := GetECKeyPair;
- PlainText := TEncoding.UTF8.GetBytes(input);
- CipherText := TUsageExamples.ECIESPascalCoinEncrypt(KeyPair.Public,
- PlainText);
- if TUsageExamples.ECIESPascalCoinDecrypt(KeyPair.Private, CipherText,
- DecryptedCipherText) then
- begin
- if TArrayUtils.AreEqual(PlainText, DecryptedCipherText) then
- begin
- Writeln('ECIES PascalCoin Compatability Encrypt, Decrypt Was Successful '
- + sLineBreak);
- Exit;
- end;
- end;
- Writeln('ECIES PascalCoin Compatability Encrypt, Decrypt Failed ' +
- sLineBreak);
- end;
- class function TUsageExamples.BytesToHexString(input: TBytes): String;
- var
- index: Int32;
- begin
- Result := '';
- for index := System.Low(input) to System.High(input) do
- begin
- if index = 0 then
- begin
- Result := Result + IntToHex(input[index], 2);
- end
- else
- begin
- Result := Result + ',' + IntToHex(input[index], 2);
- end;
- end;
- Result := '[' + Result + ']';
- end;
- class procedure TUsageExamples.DoSigningAndVerifying(const PublicKey
- : IECPublicKeyParameters; const PrivateKey: IECPrivateKeyParameters;
- const CallerMethod, TextToSign: String;
- const SigningAlgo: String = SigningAlgorithmECDSA);
- var
- Signer: ISigner;
- &message, sigBytes: TBytes;
- begin
- Writeln('Caller Method Is ' + CallerMethod + sLineBreak);
- Signer := TSignerUtilities.GetSigner(SigningAlgo);
- Writeln('Signer Name is: ' + Signer.AlgorithmName + sLineBreak);
- &message := TEncoding.UTF8.GetBytes(TextToSign);
- // Sign
- Signer.Init(True, PrivateKey);
- Signer.BlockUpdate(&message, 0, System.Length(&message));
- sigBytes := Signer.GenerateSignature();
- Writeln('Generated Signature is: ' + BytesToHexString(sigBytes) + sLineBreak);
- // Verify
- Signer.Init(False, PublicKey);
- Signer.BlockUpdate(&message, 0, System.Length(&message));
- if (not Signer.VerifySignature(sigBytes)) then
- begin
- Writeln(PublicKey.AlgorithmName + ' verification failed' + sLineBreak);
- end
- else
- begin
- Writeln(PublicKey.AlgorithmName + ' verification passed' + sLineBreak);
- end;
- end;
- class procedure TUsageExamples.GenerateKeyPairAndSignECDSA;
- var
- domain: IECDomainParameters;
- generator: IECKeyPairGenerator;
- keygenParams: IECKeyGenerationParameters;
- KeyPair: IAsymmetricCipherKeyPair;
- privParams: IECPrivateKeyParameters;
- pubParams: IECPublicKeyParameters;
- const
- MethodName = 'GenerateKeyPairAndSignECDSA';
- begin
- Writeln('MethodName is: ' + MethodName + sLineBreak);
- domain := TECDomainParameters.Create(FCurve.Curve, FCurve.G, FCurve.N,
- FCurve.H, FCurve.GetSeed);
- generator := TECKeyPairGenerator.Create('ECDSA');
- keygenParams := TECKeyGenerationParameters.Create(domain, FRandom);
- generator.Init(keygenParams);
- KeyPair := generator.GenerateKeyPair();
- privParams := KeyPair.Private as IECPrivateKeyParameters; // for signing
- pubParams := KeyPair.Public as IECPublicKeyParameters; // for verifying
- Writeln('Algorithm Name is: ' + pubParams.AlgorithmName + sLineBreak);
- Writeln('Public Key Normalized XCoord is: ' +
- pubParams.Q.Normalize.AffineXCoord.ToBigInteger.ToString(16) + sLineBreak);
- Writeln('Public Key Normalized YCoord is: ' +
- pubParams.Q.Normalize.AffineYCoord.ToBigInteger.ToString(16) + sLineBreak);
- Writeln('Private Key D Parameter is: ' + privParams.D.ToString(16) +
- sLineBreak);
- DoSigningAndVerifying(pubParams, privParams, MethodName, 'PascalECDSA');
- end;
- class procedure TUsageExamples.GenerateKeyPairAndSignECSchnorr;
- var
- domain: IECDomainParameters;
- generator: IECKeyPairGenerator;
- keygenParams: IECKeyGenerationParameters;
- KeyPair: IAsymmetricCipherKeyPair;
- privParams: IECPrivateKeyParameters;
- pubParams: IECPublicKeyParameters;
- const
- MethodName = 'GenerateKeyPairAndSignECSchnorr';
- begin
- Writeln('MethodName is: ' + MethodName + sLineBreak);
- domain := TECDomainParameters.Create(FCurve.Curve, FCurve.G, FCurve.N,
- FCurve.H, FCurve.GetSeed);
- generator := TECKeyPairGenerator.Create('ECSCHNORR');
- keygenParams := TECKeyGenerationParameters.Create(domain, FRandom);
- generator.Init(keygenParams);
- KeyPair := generator.GenerateKeyPair();
- privParams := KeyPair.Private as IECPrivateKeyParameters; // for signing
- pubParams := KeyPair.Public as IECPublicKeyParameters; // for verifying
- Writeln('Algorithm Name is: ' + pubParams.AlgorithmName + sLineBreak);
- Writeln('Public Key Normalized XCoord is: ' +
- pubParams.Q.Normalize.AffineXCoord.ToBigInteger.ToString(16) + sLineBreak);
- Writeln('Public Key Normalized YCoord is: ' +
- pubParams.Q.Normalize.AffineYCoord.ToBigInteger.ToString(16) + sLineBreak);
- Writeln('Private Key D Parameter is: ' + privParams.D.ToString(16) +
- sLineBreak);
- DoSigningAndVerifying(pubParams, privParams, MethodName, 'PascalECSCHNORR',
- SigningAlgorithmECSCHNORR);
- end;
- class function TUsageExamples.GetECIESPascalCoinCompatibilityEngine
- : IPascalCoinIESEngine;
- var
- cipher: IBufferedBlockCipher;
- AesEngine: IAesEngine;
- blockCipher: ICbcBlockCipher;
- ECDHBasicAgreementInstance: IECDHBasicAgreement;
- KDFInstance: IPascalCoinECIESKdfBytesGenerator;
- DigestMACInstance: IDigestMAC;
- begin
- // Set up IES Cipher Engine For Compatibility With PascalCoin
- ECDHBasicAgreementInstance := TECDHBasicAgreement.Create();
- KDFInstance := TPascalCoinECIESKdfBytesGenerator.Create
- (TDigestUtilities.GetDigest('SHA-512'));
- DigestMACInstance := TDigestUtilities.GetDigestMAC
- (TDigestUtilities.GetDigest('MD5'));
- // Set Up Block Cipher
- AesEngine := TAesEngine.Create(); // AES Engine
- blockCipher := TCbcBlockCipher.Create(AesEngine); // CBC
- cipher := TPaddedBufferedBlockCipher.Create(blockCipher,
- TZeroBytePadding.Create() as IZeroBytePadding); // ZeroBytePadding
- Result := TPascalCoinIESEngine.Create(ECDHBasicAgreementInstance, KDFInstance,
- DigestMACInstance, cipher);
- end;
- class function TUsageExamples.GetECKeyPair: IAsymmetricCipherKeyPair;
- var
- Lcurve: IX9ECParameters;
- domain: IECDomainParameters;
- KeyPairGeneratorInstance: IAsymmetricCipherKeyPairGenerator;
- const
- MethodName = 'GetECKeyPair';
- begin
- // Full Generation Method
- Lcurve := TSecNamedCurves.GetByName(CurveName);
- KeyPairGeneratorInstance := TGeneratorUtilities.GetKeyPairGenerator('ECDSA');
- domain := TECDomainParameters.Create(Lcurve.Curve, Lcurve.G, Lcurve.N,
- Lcurve.H, Lcurve.GetSeed);
- KeyPairGeneratorInstance.Init(TECKeyGenerationParameters.Create(domain,
- FRandom));
- Result := KeyPairGeneratorInstance.GenerateKeyPair();
- DoSigningAndVerifying(Result.Public as IECPublicKeyParameters,
- Result.Private as IECPrivateKeyParameters, MethodName, 'PascalECDSA');
- end;
- class function TUsageExamples.GetIESCipherParameters: IIESWithCipherParameters;
- var
- Derivation, Encoding, IVBytes: TBytes;
- MacKeySizeInBits, CipherKeySizeInBits: Int32;
- UsePointCompression: Boolean;
- begin
- // Set up IES Cipher Parameters For Compatibility With PascalCoin Current Implementation
- // The derivation and encoding vectors are used when initialising the KDF and MAC.
- // They're optional but if used then they need to be known by the other user so that
- // they can decrypt the ciphertext and verify the MAC correctly. The security is based
- // on the shared secret coming from the (static-ephemeral) ECDH key agreement.
- Derivation := Nil;
- Encoding := Nil;
- System.SetLength(IVBytes, 16); // using Zero Initialized IV for compatibility
- MacKeySizeInBits := 32 * 8;
- // Since we are using AES256_CBC for compatibility
- CipherKeySizeInBits := 32 * 8;
- // whether to use point compression when deriving the octets string
- // from a point or not in the EphemeralKeyPairGenerator
- UsePointCompression := True; // for compatibility
- Result := TIESWithCipherParameters.Create(Derivation, Encoding, IVBytes,
- MacKeySizeInBits, CipherKeySizeInBits, UsePointCompression);
- end;
- class procedure TUsageExamples.GetPublicKeyFromPrivateKey;
- var
- domain: IECDomainParameters;
- generator: IECKeyPairGenerator;
- keygenParams: IECKeyGenerationParameters;
- KeyPair: IAsymmetricCipherKeyPair;
- privParams: IECPrivateKeyParameters;
- pubParams, recreatedPubKeyParameters: IECPublicKeyParameters;
- EncodedPublicKey, RecreatedEncodedPublicKey: TBytes;
- qPoint: IECPoint;
- const
- MethodName = 'GetPublicKeyFromPrivateKey';
- begin
- Writeln('MethodName is: ' + MethodName + sLineBreak);
- domain := TECDomainParameters.Create(FCurve.Curve, FCurve.G, FCurve.N,
- FCurve.H, FCurve.GetSeed);
- generator := TECKeyPairGenerator.Create('ECDSA');
- keygenParams := TECKeyGenerationParameters.Create(domain, FRandom);
- generator.Init(keygenParams);
- KeyPair := generator.GenerateKeyPair();
- privParams := KeyPair.Private as IECPrivateKeyParameters; // for signing
- pubParams := KeyPair.Public as IECPublicKeyParameters; // for verifying
- Writeln('Algorithm Name is: ' + pubParams.AlgorithmName + sLineBreak);
- Writeln('Public Key Normalized XCoord is: ' +
- pubParams.Q.Normalize.AffineXCoord.ToBigInteger.ToString(16) + sLineBreak);
- Writeln('Public Key Normalized YCoord is: ' +
- pubParams.Q.Normalize.AffineYCoord.ToBigInteger.ToString(16) + sLineBreak);
- EncodedPublicKey := pubParams.Q.Normalize.GetEncoded;
- Writeln('Encoded Public Key is: ' + BytesToHexString(EncodedPublicKey) +
- sLineBreak);
- Writeln('Private Key D Parameter is: ' + privParams.D.ToString(16) +
- sLineBreak);
- // get public key from private key
- // Method One
- qPoint := domain.G.Multiply(privParams.D);
- RecreatedEncodedPublicKey := qPoint.GetEncoded();
- if CompareMem(PByte(EncodedPublicKey), PByte(RecreatedEncodedPublicKey),
- System.Length(EncodedPublicKey) * System.SizeOf(Byte)) then
- begin
- Writeln('Public Key Recreation From Private Key Was Successful' +
- sLineBreak);
- end
- else
- begin
- Writeln('Public Key Recreation From Private Key Failed' + sLineBreak);
- end;
- recreatedPubKeyParameters := TECPublicKeyParameters.Create(qPoint, domain);
- if pubParams.Equals(recreatedPubKeyParameters) then
- begin
- Writeln('Public Key Recreation Match With Original Public Key' +
- sLineBreak);
- end
- else
- begin
- Writeln('Public Key Recreation DOES NOT Match With Original Public Key' +
- sLineBreak);
- end;
- // Do Signing and Verifying to Assert Proper Recreation Of Public Key
- DoSigningAndVerifying(recreatedPubKeyParameters, privParams, MethodName,
- 'PascalECDSA');
- // or the easier method
- // Method Two (** Preferred **)
- recreatedPubKeyParameters := TECKeyPairGenerator.GetCorrespondingPublicKey
- (privParams);
- if pubParams.Equals(recreatedPubKeyParameters) then
- begin
- Writeln('Public Key Recreation Match With Original Public Key' +
- sLineBreak);
- end
- else
- begin
- Writeln('Public Key Recreation DOES NOT Match With Original Public Key' +
- sLineBreak);
- end;
- // Do Signing and Verifying to Assert Proper Recreation Of Public Key
- DoSigningAndVerifying(recreatedPubKeyParameters, privParams, MethodName,
- 'PascalECDSA');
- end;
- class procedure TUsageExamples.RecreatePublicAndPrivateKeyPairsFromByteArray;
- var
- domain: IECDomainParameters;
- generator: IECKeyPairGenerator;
- keygenParams: IECKeyGenerationParameters;
- KeyPair: IAsymmetricCipherKeyPair;
- privParams, RegeneratedPrivateKey: IECPrivateKeyParameters;
- pubParams, RegeneratedPublicKey: IECPublicKeyParameters;
- PublicKeyByteArray, PrivateKeyByteArray: TBytes;
- PrivD: TBigInteger;
- const
- MethodName = 'RecreatePublicAndPrivateKeyPairsFromByteArray';
- begin
- Writeln('MethodName is: ' + MethodName + sLineBreak);
- domain := TECDomainParameters.Create(FCurve.Curve, FCurve.G, FCurve.N,
- FCurve.H, FCurve.GetSeed);
- generator := TECKeyPairGenerator.Create('ECDSA');
- keygenParams := TECKeyGenerationParameters.Create(domain, FRandom);
- generator.Init(keygenParams);
- KeyPair := generator.GenerateKeyPair();
- privParams := KeyPair.Private as IECPrivateKeyParameters; // for signing
- pubParams := KeyPair.Public as IECPublicKeyParameters; // for verifying
- Writeln('Algorithm Name is: ' + pubParams.AlgorithmName + sLineBreak);
- Writeln('Public Key Normalized XCoord is: ' +
- pubParams.Q.Normalize.AffineXCoord.ToBigInteger.ToString(16) + sLineBreak);
- Writeln('Public Key Normalized YCoord is: ' +
- pubParams.Q.Normalize.AffineYCoord.ToBigInteger.ToString(16) + sLineBreak);
- Writeln('Private Key D Parameter is: ' + privParams.D.ToString(16) +
- sLineBreak);
- PublicKeyByteArray := pubParams.Q.GetEncoded;
- // using ToByteArray here because bytes are unsigned in Pascal
- PrivateKeyByteArray := privParams.D.ToByteArray;
- RegeneratedPublicKey := TECPublicKeyParameters.Create('ECDSA',
- FCurve.Curve.DecodePoint(PublicKeyByteArray), domain);
- if pubParams.Equals(RegeneratedPublicKey) then
- begin
- Writeln('Public Key Recreation Match With Original Public Key' +
- sLineBreak);
- end
- else
- begin
- Writeln('Public Key Recreation DOES NOT Match With Original Public Key' +
- sLineBreak);
- end;
- PrivD := TBigInteger.Create(PrivateKeyByteArray);
- RegeneratedPrivateKey := TECPrivateKeyParameters.Create('ECDSA',
- PrivD, domain);
- if privParams.Equals(RegeneratedPrivateKey) then
- begin
- Writeln('Private Key Recreation Match With Original Private Key' +
- sLineBreak);
- end
- else
- begin
- Writeln('Private Key Recreation DOES NOT Match With Original Private Key' +
- sLineBreak);
- end;
- // Do Signing and Verifying to Assert Proper Recreation Of Public Key
- DoSigningAndVerifying(RegeneratedPublicKey, privParams, MethodName,
- 'PascalECDSA');
- // Do Signing and Verifying to Assert Proper Recreation Of Private Key
- DoSigningAndVerifying(pubParams, RegeneratedPrivateKey, MethodName,
- 'PascalECDSA');
- end;
- class procedure TUsageExamples.RecreatePublicKeyFromXAndYCoordByteArray;
- var
- domain: IECDomainParameters;
- generator: IECKeyPairGenerator;
- keygenParams: IECKeyGenerationParameters;
- KeyPair: IAsymmetricCipherKeyPair;
- pubParams, RegeneratedPublicKey: IECPublicKeyParameters;
- privParams: IECPrivateKeyParameters;
- XCoordByteArray, YCoordByteArray: TBytes;
- BigXCoord, BigYCoord, BigXCoordRecreated, BigYCoordRecreated: TBigInteger;
- point: IECPoint;
- const
- MethodName = 'RecreatePublicKeyFromXAndYCoordByteArray';
- begin
- Writeln('MethodName is: ' + MethodName + sLineBreak);
- domain := TECDomainParameters.Create(FCurve.Curve, FCurve.G, FCurve.N,
- FCurve.H, FCurve.GetSeed);
- generator := TECKeyPairGenerator.Create('ECDSA');
- keygenParams := TECKeyGenerationParameters.Create(domain, FRandom);
- generator.Init(keygenParams);
- KeyPair := generator.GenerateKeyPair();
- privParams := KeyPair.Private as IECPrivateKeyParameters; // for signing
- pubParams := KeyPair.Public as IECPublicKeyParameters; // for verifying
- Writeln('Algorithm Name is: ' + pubParams.AlgorithmName + sLineBreak);
- BigXCoord := pubParams.Q.Normalize.AffineXCoord.ToBigInteger;
- BigYCoord := pubParams.Q.Normalize.AffineYCoord.ToBigInteger;
- Writeln('Public Key Normalized XCoord is: ' + BigXCoord.ToString(16) +
- sLineBreak);
- Writeln('Public Key Normalized YCoord is: ' + BigYCoord.ToString(16) +
- sLineBreak);
- XCoordByteArray := BigXCoord.ToByteArray;
- YCoordByteArray := BigYCoord.ToByteArray;
- BigXCoordRecreated := TBigInteger.Create(1, XCoordByteArray);
- BigYCoordRecreated := TBigInteger.Create(1, YCoordByteArray);
- point := FCurve.Curve.CreatePoint(BigXCoordRecreated, BigYCoordRecreated);
- RegeneratedPublicKey := TECPublicKeyParameters.Create(point, domain);
- if pubParams.Equals(RegeneratedPublicKey) then
- begin
- Writeln('Public Key Recreation Match With Original Public Key' +
- sLineBreak);
- end
- else
- begin
- Writeln('Public Key Recreation DOES NOT Match With Original Public Key' +
- sLineBreak);
- end;
- // Do Signing and Verifying to Assert Proper Recreation Of Public Key
- DoSigningAndVerifying(RegeneratedPublicKey, privParams, MethodName,
- 'PascalECDSA');
- end;
- class constructor TUsageExamples.UsageExamples;
- begin
- FRandom := TSecureRandom.Create();
- FCurve := TSecNamedCurves.GetByName(CurveName);
- end;
- end.
|