Always same signature and same random k
hanwencheng opened this issue · comments
Hi, I use the library to sign the same message with same seed, it always get the same signature, I check the code, every time it create the same K, as I understand for the ECDSA, the k should be variant, right?
Hi, Sublimator,
Thanks, I am glad that you answered the question. In RFC6979 it says Produced signatures remain fully compatible with plain DSA and ECDSA. Entities that verify the signatures need not be changed or even be aware of the process used to generate k.
But with the repository ripple-lib-java
as java signer, ripple-keypair
as js verifier, seems that it does not work, ripple-lib-java
produced the same hash, public key, but different signature. Furthermore this signature is unfortunately UNCOMPATIBLE with ripple-keypairs
's verify function.
In signer side:
Security.addProvider(new BouncyCastleProvider());
String messageString = "hello,world";
//get private key
String passPhrase = "sp5fghtJtpUorTwvof1NpDXAzNwf5";
IKeyPair keyPair = Seed.getKeyPair(passPhrase);
String privateKey = Utils.bigToHex(keyPair.priv());
String newPriv = "00" + privateKey;
//get hash
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(messageString.getBytes());
//get signature
assert keyPair.priv().compareTo(new BigInteger(newPriv, 16)) == 0;
byte[] signature = KeyPair.sign(digest , new BigInteger(newPriv, 16));
//transmit hex parameters
String messageHex = Utils.bytesToHex(digest);
String signatureHex = Utils.bytesToHex(signature);
String publicKeyHex = Utils.bigToHex(keyPair.pub());
In verifier side
var keypairs = require('ripple-keypairs')
var isCorrect = keypairs.verify(messageHex, signatureHex, publicKeyHex) //which is always false
They should be compatible. I see that your first parameter to verify
is hashHex
whereas the documentation says messageHex
. Is that the issue?
Hi, Clark,
Thanks! That is my typo, the result is still false yet.
I update the code snippet with the real use case, hope that make sense.
Hanwen
A further Js test case could be seen here
//====further test case====
var wallet = { address: 'rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1',
secret: 'sp5fghtJtpUorTwvof1NpDXAzNwf5' }
//hash
var message = "hello, world";
var hash = sjcl.hash.sha256.hash(message);
var hashHexJS = sjcl.codec.hex.fromBits(hash)
//publicKey
var keypair = keypairs.deriveKeypair(wallet.secret);
var publicKeyJS = keypair.publicKey;
//signature
var signatureJS = keypairs.sign(hashHexJS, keypair.privateKey )
var publicKey = "030D58EB48B4420B1F7B9DF55087E0E29FEF0E8468F9A6825B01CA2C361042D435" //derive from java code
var hashHex = "09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b" //derive from java code
var signature = "3045022100e5a0063e360be13a5f5c568ffe5137c5d0abe893075112d14ffc0db566eded5c0220045e5443938fee9af97c4a23aed4055a824d3b844c0a540ea716a758b0cf143f" //derive from java code
console.log('derived pubicKey is same', publicKey === publicKeyJS)//true!
console.log('derived hash is same', hashHex === hashHexJS)//true!
console.log('derived signature is same', signature === signatureJS)//false!
//check if the request is from the certain user
var isTrue = keypairs.verify(hashHex, signature, publicKey)//false!
var isTrueJS = keypairs.verify(hashHexJS, signatureJS, publicKeyJS)//true!
You are still signing the hash instead of signing the message. The sign
and verify
functions already hash the message internally, so you are double hashing: https://github.com/ripple/ripple-keypairs/blob/master/src/index.js#L37
I don't know how you are generating the ripple-lib-java
signature, but if you are signing the message then that would explain the difference.
Thanks! That's exactly where the problem is!
The ripple-lib-java
does not implement the hash for the massage, whereas ripple-keypair
use hash-512 as default!
I have a branch of ripple-lib-java with ed25519 support which has yet to be merged to master, which takes care of the hashing itself, with the sign/verify api methods taking the full message
rather than a digest.
What do you use ripple-lib-java for?
@sublimator Which branch? I am building another java client app to connect REST API , so I use ripple-lib-java to do the public key generation and ECDSA signature.
Thanks for your information! One question, after closing REST server, how could we build and use our own applications?
There is a pull request for an experimental JSON-RPC HTTP interface for RippleAPI: XRPLF/xrpl.js#663