ripple / ripple-keypairs

Moved to: https://github.com/XRPLF/xrpl.js/tree/develop/packages/ripple-keypairs

Home Page:https://github.com/XRPLF/xrpl.js/tree/develop/packages/ripple-keypairs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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!

@hanwencheng

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