Protobuf 构建
根据 RCJava 的 dev_sdk_preview 分支 src/main/resources 目录下的 peer.proto 文件, 利用 protobuf-c 生成针对 peer.proto 的 peer.pb-c.c 文件。
由于在 peer.proto 文件中:
/*
* 交易
*/
message Transaction {
string id = 1;
enum Type {
UNDEFINED = 0;
// deploy a chaincode to the network and call `Init` function
CHAINCODE_DEPLOY = 1;
// call a chaincode `Invoke` function as a transaction
CHAINCODE_INVOKE = 2;
CHAINCODE_SET_STATE = 3;
}
Type type = 2;
//store ChaincodeID as bytes so its encrypted value can be stored
ChaincodeId cid = 3;
oneof para {
ChaincodeDeploy spec = 4;
ChaincodeInput ipt = 5;
bool state = 6;
}
Signature signature = 7;
}
其中的:
oneof para {
ChaincodeDeploy spec = 4;
ChaincodeInput ipt = 5;
bool state = 6;
}
Signature signatrue = 7;
在 protobuf-c 中,会生成一个 Uion 的 c 语言联合体,考虑到运行的环境是嵌入式实时操作系统,将此处的代码改为:
message Transaction
{
string id = 1;
enum Type
{
UNDEFINED = 0;
CHAINCODE_DEPLOY = 1;
CHAINCODE_INVOKE = 2;
CHAINCODE_SET_STATE = 3;
}
Type type = 2;
ChaincodeId cid = 3;
ChaincodeInput ipt = 5;
Signature signature = 7;
}
PS: 此处的 cid, ipt, signature 的数值应该与 peer.proto 中定义的消息类型一致。否则在 protobuf 解析是会出现错误,导致服务器无法对上传的 Transaction 的 protobuf 消息解码。
签名算法错误问题
RCJava 中对数据签名使用的默认算法是 SHA1withECDSA ,使用的秘钥是由 keystore.exe 使用 SHA256withECDSA 算法生成,注意在对数据签名时使用正确的算法。
在使用 SHA1withECDSA 与 SHA256withECDSA 时需要注意, SHA1withECDSA 算法是先采用 SHA1 对加密的消息进行 Hash 一共是 160 bits(20 bytes), SHA256withECDSA 对消息进行 hash 是 256 bits(32 bytes)。
调试过程中,一开始采用的是 SHA256withECDSA 算法对消息进行签名:
if (0 == mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), pBuffer, pBufferSize, digest))
{
LOG_I("get the hash of the protobuf succeed!");
rt_kprintf("\r\n");
for (size_t i = 0; i < sizeof digest; i++)
{
rt_kprintf("%s%02X%s", i % 16 == 0 ? "\n\t":" ", digest[i], i == sizeof(digest) - 1 ? "\n":"");
}
rt_kprintf("\r\n");
}
else
{
LOG_E("get the hash of the protobuf failed!");
}
if (0 == mbedtls_pk_sign(&pk_ctx, MBEDTLS_MD_SHA256, digest, sizeof digest, sig, &sigCnt, mbedtls_entropy_func, NULL))
{
LOG_I("sign the data succeed!");
}
else
{
LOG_E("sign the data failed!");
}
经过确认,更改签名算法为 SHA256withECDSA :
if (0 == mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), pBuffer, pBufferSize, digest))
{
LOG_I("get the hash of the protobuf succeed!");
rt_kprintf("\r\n");
for (size_t i = 0; i < sizeof digest; i++)
{
rt_kprintf("%s%02X%s", i % 16 == 0 ? "\n\t":" ", digest[i], i == sizeof(digest) - 1 ? "\n":"");
}
rt_kprintf("\r\n");
}
else
{
LOG_E("get the hash of the protobuf failed!");
}
if (0 == mbedtls_pk_sign(&pk_ctx, MBEDTLS_MD_SHA1, digest, sizeof digest, sig, &sigCnt, mbedtls_entropy_func, NULL))
{
LOG_I("sign the data succeed!");
}
else
{
LOG_E("sign the data failed!");
}
注意:在更改签名算法后,需要更改 mbedlts_pk_sign 中 digest 数组的上界,由于 sizeof digest 是默认数组上界的,不更改数组上界会导致数据签名是的 digest 消息错误,最后导致数据签名校验失败。