paulmillr / noble-ed25519

Fastest 4KB JS implementation of ed25519 signatures
https://paulmillr.com/noble
MIT License
421 stars 52 forks source link

Differing outputs between languages #42

Closed joshbenaron closed 2 years ago

joshbenaron commented 2 years ago

Hey,

I'm signing an identical message with the same key between this package and Rust's ed25519-dalek. The first 32ish bytes of both signatures are identical but the last bytes are not the same. Do you know why this could be?

paulmillr commented 2 years ago

No. Does it differ between different private keys?

joshbenaron commented 2 years ago

It differs with identical priv/pub keys, message

paulmillr commented 2 years ago

If you could provide a key/message pair, I will investigate this.

joshbenaron commented 2 years ago

Key = [ 232, 153, 76, 227, 11, 132, 39, 134, 89, 190, 9, 20, 251, 142, 65, 240, 252, 233, 70, 28, 233, 56, 14, 173, 81, 44, 139, 150, 139, 39, 200, 79, 88, 142, 42, 150, 88, 187, 51, 210, 155, 30, 26, 116, 229, 17, 165, 115, 112, 160, 123, 184, 142, 69, 194, 128, 197, 8, 92, 208, 49, 92, 178, 25, ]

Message = [ 110, 123, 209, 66, 178, 255, 153, 11, 45, 235, 189, 244, 42, 9, 152, 192, 181, 183, 40, 140, 216, 194, 141, 222, 128, 251, 237, 133, 207, 198, 131, 71, 242, 117, 246, 186, 189, 138, 117, 253, 31, 141, 117, 17, 179, 138, 224, 131 ]

paulmillr commented 2 years ago

your key is 64 bytes. ed25519 private keys are 32 bytes.

let sc = SecretKey::from_bytes(&Key[0..32]).unwrap();
let pubkey = PublicKey::from(&sc);
println!("SC {:?}", sc);
println!("SC/pub {:?}", hex::encode(pubkey.to_bytes()));
let kp = Keypair { public: pubkey, secret: sc };
    // Returns
    // 98FC99FD2869EFC7AA0743801620B8BD40DAA6DD798A8985BD43AE151E4C7C1A2937808FC199A76708FA046E06206F82B776EB4E05A426CB8F8B4ED4FB4AEC0F
    // Same as noble code:
    //   const privateKey = new Uint8Array(Key).slice(0, 32);
    //   const pub = await ed.getPublicKey(privateKey);
    //   console.log('PUB', Buffer.from(pub).toString('hex'));
    //   const signature = await ed.sign(new Uint8Array(Message), privateKey);
    //   console.log('SIG', signature, Buffer.from(signature).toString('hex'));
    println!("SIG {:?}", kp.sign(&Message));
joshbenaron commented 2 years ago

your key is 64 bytes

The first 32 bytes is the secret key and the second 32 is the public key. Very standard in crypto (as in cryptocurrency)

paulmillr commented 2 years ago

See my code -- the outputs match