I'm working on a way to secure the message I sent from a node.js server to a C++ application.
From node.js , I created a key pair.
I'm using node-rsa to read the public key on node.js side ( https://github.com/rzcoder/node-rsa )
var rsa = new nodeRSA(publicKeyBuffer ,{encryptionScheme :'pkcs1'})
As my message can be long, I calculate a salted sha256 of the message before calling encrypt.
const hash = crypto.createHash('sha256').update(message + config.signSalt).digest('hex')
this part is working fine because I am able to generate the exact same hash on C++ side.
then, I'm calling the encrypt function of node-rsa to generate a buffer
const signature = rsa.encrypt(hash)
I tried various encoding , but as the data is sent through a websocket (+ MsgPack packing) the binary format is a good option
On C++ side , I am first reading the key for a 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));
the key is read without errors, after that, I'm calculating the hash from the message, making a std::string from the unsigned char buffer
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;
the decrypt failed with the following error
Rsa::decrypt - Error decrypting string ssl error error:0406506C:lib(4):func(101):reason(108)
I tried various encoding and padding mode but always getting an error.
(Assuming you want to sign using the private key on the nodejs side and verify using the public key on the openssl side)
To sign string
Testwith sample private key, use e.g.:Giving a hex encoded signature:
To verify this signature with openssl, use e.g.:
Some (random) notes:
above code is just a working proof-of-concept for RSA sign/verify between nodejs and openssl. Please do not expect it to be a secure implementation with correct error handling, secure key lengths, secure against timing/side-channel attacks etc.
signed string/buffer can be arbitrarily long as hashing is performed by node-rsa
encoded public/private key can be obtained in nodejs using e.g.
key.exportKey('pkcs8-public')/key.exportKey('pkcs8')select encoding that fits you (I used strings and hex-strings as they are clearly readable). You probably want to use buffers
Good luck!
Disclaimer: I am no crypto expert, so please do validate my thoughts.
Used private key:
With corresponding public key: