hyperledger-archives / sawtooth-sdk-cxx

https://wiki.hyperledger.org/display/sawtooth
Apache License 2.0
4 stars 21 forks source link

Question about secp256k1 #15

Open akitl opened 5 years ago

akitl commented 5 years ago

hello, in this sawtooth sdk I do not see any use of secp256k1, by this fact, I do not understand how are signed messages .

can someone enlighten me about this ?

lucgerrits commented 5 years ago

Hi, I have this exact same issue. How are the message signed in c++ ? I used Crypto++ but still a mystery about how the signed messages with the SDKs are constant and with Crypto++ it changes on every execution. (This would be probably an other issue but still connected to this one). Posted a message about this on the Hyperledger chat. Hope here or there I'll get an answer. I'll put the answer here if I have it.

arsulegai commented 4 years ago

@akitl and @lucgerrits for some reason this was unnoticed by me. Apparently we need signing for building the client. I don't see those libraries for building a client in CXX SDK (here in the repo). There are SDK utilities for building a TP. It would be helpful to the community if by now you have a sample code.

lucgerrits commented 4 years ago

Note: BTW this is actually more of a cryptographic issue. I have seen and tried the CXX SDK but didn't managed to make it work easily, so I made my own C++ program using bitcoin secp256k1 & Protobuf.

Concerning the issue I had was that I wasn't following secp256k1 "standard" so ended up using the already existing bitcoin secp256k1. I discovered the issue reason after I read this RFC about Deterministic ECDSA (that secp256k1 follows in a way).

In cas you wonder what it looks like, here a piece of code I used :

//load some keys into TnxKeys & BatchKeys
CHECK(LoadKeys(ctx, TnxKeys.privateKey, TnxKeys.privKey, TnxKeys.publicKey, TnxKeys.publicKey_serilized, TnxKeys.pubKey, options.isverbose) == 1);
CHECK(LoadKeys(ctx, BatchKeys.privateKey, BatchKeys.privKey, BatchKeys.publicKey, BatchKeys.publicKey_serilized, BatchKeys.pubKey, options.isverbose) == 1);

//add some protobuf stuff...
BatchList myBatchList;                      //init batch list
Batch *myBatch = myBatchList.add_batches(); //init the one batch that will be sent
BatchHeader myBatchHeader;                  //init batch header
Transaction *myTransaction = myBatch->add_transactions(); //init the one transaction that will be sent
TransactionHeader myTransactionHeader;
//then manipulate the protobuf according the Sawtooth specs in the docs...

//then hash and sign the message:
message_hash_str = sha256Data(myTransactionHeader_string);
HexStrToUchar(message_hash_char, message_hash_str.c_str(), (size_t)HASH_SHA256_SIZE);
CHECK(SECP256K1_API::secp256k1_ecdsa_sign(ctx, &signature, message_hash_char, TnxKeys.privateKey, NULL, NULL) == 1); //make signature
CHECK(SECP256K1_API::secp256k1_ecdsa_signature_serialize_compact(ctx, signature_serilized, &signature) == 1);
signature_serilized_str = UcharToHexStr(signature_serilized, SIGNATURE_SERILIZED_SIZE);
myTransaction->set_header_signature(signature_serilized_str); //set header signature

//at the end serialize the protobuf to some bytes and send that to the Sawtooth REST API and voila :)

Quick edit: this issue could probably be closed.