我正在努力保护我从node.js服务器发送到C应用程序的消息 .
从node.js开始,我创建了一个密钥对 .
我正在使用node-rsa读取node.js端的公钥(https://github.com/rzcoder/node-rsa)
var rsa = new nodeRSA(publicKeyBuffer ,{encryptionScheme :'pkcs1'})
由于我的消息可能很长,我在调用加密之前计算了消息的salted sha256 .
const hash = crypto.createHash('sha256').update(message + config.signSalt).digest('hex')
这部分工作正常,因为我能够在C端生成完全相同的哈希 .
然后,我正在调用node-rsa的encrypt函数来生成缓冲区
const signature = rsa.encrypt(hash)
我尝试了各种编码,但由于数据是通过websocket(MsgPack打包)发送的,因此二进制格式是一个不错的选择
在C方面,我第一次读取char []的键
const char keyStr[] = "-----BEGIN RSA PRIVATE KEY-----\n" ..........
BIO* bio = BIO_new_mem_buf(keyStr, (int)strlen(keyStr)); // -1: assume string is null terminated
m_rsaPrivKey = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
if (!m_rsaPrivKey)
LogOutSys("ERROR: Could not load PRIVATE KEY! PEM_write_bio_RSAPrivateKey FAILED: %s\n", ERR_error_string(ERR_get_error(), NULL));
读取密钥没有错误,之后,我正在计算消息中的散列,从unsigned char缓冲区生成一个std :: string
std::string hash = sha256(msg.c_str());
std::string signatureStr(signature.begin(), signature.end());
char *decrypt;
int decryptLen;
decrypt = new char[RSA_size(m_rsaPrivKey)];
decryptLen = RSA_private_decrypt((int)msg.size() + 1, (unsigned char*)msg.c_str(), (unsigned char*)decrypt, m_rsaPrivKey, RSA_NO_PADDING /* RSA_PKCS1_OAEP_PADDING */ );
if (decryptLen == -1)
{
char errStr[130];
ERR_error_string(ERR_get_error(), errStr);
LogOutSys("Rsa::decrypt - Error decrypting string ssl error %s", errStr);
}
for (int i = 0; i < decryptLen; i++)
{
decryptData.push_back(decrypt[i]);
}
delete decrypt;
解密失败,出现以下错误
Rsa :: decrypt - 解密字符串ssl错误错误:0406506C:lib(4):func(101):reason(108)
我尝试了各种编码和填充模式但总是出错 .
1 回答
(假设您想使用nodejs端的私钥进行签名,并使用openssl端的公钥进行验证)
要使用示例私钥对字符串
Test
进行签名,请使用例如:给出十六进制编码签名:
要使用openssl验证此签名,请使用例如:
一些(随机)笔记:
以上代码只是nodejs和openssl之间RSA签名/验证的工作概念验证 . 请不要指望它是一个安全的实现,具有正确的错误处理,安全密钥长度,防止定时/侧通道攻击等 .
signed string / buffer可以任意长,因为node-rsa执行散列
可以使用例如在nodejs中获得
编码的公钥/私钥 .
key.exportKey('pkcs8-public')
/key.exportKey('pkcs8')
选择适合您的编码(我使用字符串和十六进制字符串,因为它们清晰可读) . 您可能想要使用缓冲区
祝好运!
免责声明:我不是加密专家,所以请确认我的想法 .
使用私钥:
使用相应的公钥: