Xor-el / CryptoLib4Pascal

Crypto for Modern Object Pascal
MIT License
211 stars 64 forks source link

Usage Question: Create private/public key pair with Ed25519 using SHA3-512 instead of SHA512 (standard) #9

Closed GamSui closed 4 years ago

GamSui commented 5 years ago

I'm struggling with finding a sample to do the following: I would like to create a private/public key pair with the Ed25519 public-key signature system. But unlike the standard Ed25519 implementation which uses SHA512 hash function, I would like to use the SHA3-512 hash function. Some help would be very much appreciated. Thanks a lot!

Xor-el commented 4 years ago

First of all, I must apologize for replying late as I am just seeing this issue now. GitHub unfortunately didn't notify me that an issue was created.

I have done something similar to what you want but for Blake2B.

Links can be found below

KeyPair Generator

Other relevant links

https://github.com/Xor-el/CryptoLib4Pascal/blob/master/CryptoLib/src/Math/EC/Rfc8032/ClpEd25519Blake2B.pas

https://github.com/Xor-el/CryptoLib4Pascal/blob/master/CryptoLib/src/Crypto/Signers/ClpEd25519Blake2BSigner.pas

using the above links as guidelines, you can create your own variant which uses SHA3-512.

do feel free to reach out if you encounter any other issues along the way. Regards.

GamSui commented 4 years ago

Hello

Thank you very much for your answer!

Hhm, unfortunately I did not succeed :-(

For some quick tests I'm save to "misuse" your Blake2B-512
implementation, and just replace the digest in ClpEd25519Blake2B.pas,
right? Replace result := TDigestUtilities.GetDigest('BLAKE2B-512'); with result := TDigestUtilities.GetDigest('SHA3-512');

In my test code I'm assigning a private key, and want to generate the
public key: LSk :=
DecodeHex('4ba47b6ace2abe73ef593c3cf32a999fb57349a6038bc334d3b50edff8bd33f6'); PrivateKey := TEd25519Blake2BPrivateKeyParameters.Create(LSk, 0); PublicKey := PrivateKey.GeneratePublicKey;

Private Key: 4ba47b6ace2abe73ef593c3cf32a999fb57349a6038bc334d3b50edff8bd33f6 Expected Public Key:
576192500b07f5c78482d05cb17bfcde61fcd819e447447ada0f7ad149928bf2 Generated Public Key:
498a4762482840fa5cb1e6614a9ff3624625dac26df7b5250a2d3d9f9e10fc9b

So something went wrong.

When doing the same with SHA-512 it works: Private Key: 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60 Expected Public Key:
d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a Generated Public Key:
d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a

When doing the same with Blake2B-512 it works as well: Private Key: 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60 Expected Public Key:
78e65bf30f893d32fc57ef051c341bdede242544fc2a2112f0fa2c7afdebc02f Generated Public Key:
78e65bf30f893d32fc57ef051c341bdede242544fc2a2112f0fa2c7afdebc02f

The reason I want to do this: I would like to create a NEM address
from scratch. NEM is a cryptocurrency platform like Ethereum with its
native currency, XEM (like Ether is to Ethereum). I'm pretty sure that
the expected public key is correct. Becasue when importing the
corresponding private key into the NEM Nano Wallet I get the correct
address, and the public key is part of the address calculation.

Thank you very much for any help, hints etc.

Best regards

Guido

Xor-el commented 4 years ago

Hello, strangely again, GitHub didn't notify me of your update. Got to see it by chance. To answer your question, Nem used SHA3-512 before it was standardized as SHA-3 by NIST which essentially means that Nem uses KECCAK-512.

So the hash you need is

result := TDigestUtilities.GetDigest('KECCAK-512');

GamSui commented 4 years ago

Hello again. No worries! And thanks a lot for checking from time to time.

I forgot to mention that I also tested with KECCAK-512. But unfortunately this didn't work out either :-(

Private Key: 4ba47b6ace2abe73ef593c3cf32a999fb57349a6038bc334d3b50edff8bd33f6 Expected Public Key: 576192500b07f5c78482d05cb17bfcde61fcd819e447447ada0f7ad149928bf2 Generated Public Key: 473c6df8dbbbde579b700323cd4f3d0df868573868bf1d9a53c30a2056d0ff5a

Hhmmm... I was pretty sure that with NEM the only difference to the standard Ed25519 implementation is the hash function. But maybe there is more...

Again, thank you very much for your support so far.

Best regards

Guido

Xor-el commented 4 years ago

Hello again. No worries! And thanks a lot for checking from time to time.

I forgot to mention that I also tested with KECCAK-512. But unfortunately this didn't work out either :-(

Private Key: 4ba47b6ace2abe73ef593c3cf32a999fb57349a6038bc334d3b50edff8bd33f6 Expected Public Key: 576192500b07f5c78482d05cb17bfcde61fcd819e447447ada0f7ad149928bf2 Generated Public Key: 473c6df8dbbbde579b700323cd4f3d0df868573868bf1d9a53c30a2056d0ff5a

Hhmmm... I was pretty sure that with NEM the only difference to the standard Ed25519 implementation is the hash function. But maybe there is more...

Again, thank you very much for your support so far.

Best regards

Guido

Hi, so I did some research about Nem and discovered that the private key is first reversed (as a byte array) before passed to the ED25519 method. The code below gives me 576192500b07f5c78482d05cb17bfcde61fcd819e447447ada0f7ad149928bf2 as my public key.

var
  sk, skreversed: TBytes;
  privateKey: IEd25519Blake2BPrivateKeyParameters;
  publicKey: IEd25519Blake2BPublicKeyParameters;
  pk: string;
  i: Int32;
begin
  sk := DecodeHex
    (('4ba47b6ace2abe73ef593c3cf32a999fb57349a6038bc334d3b50edff8bd33f6'));
  System.SetLength(skreversed, length(sk));
  for i := Low(sk) to High(sk) do
  begin
    skreversed[High(sk) - i] := sk[i];
  end;

  privateKey := TEd25519Blake2BPrivateKeyParameters.Create(skreversed, 0);
  publicKey := privateKey.GeneratePublicKey;
  pk := EncodeHex(publicKey.GetEncoded);
end;

** Note, I used Keccak-512 as the digest.

GamSui commented 4 years ago

Hello again

Wow! Thanks a lot! Works like a charm!

Donation is on the way...

Best regards

Guido