2

I have to send some encrypted data throught the network (websocket)

I generated a key pair with the the following node.js module :

https://github.com/juliangruber/keypair

My public key looks like this:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAlUiMDQsBgj5P/T86w/eg9MXUj8M4WMVihP8YzmDxMqCFb7D+w4N/1XcxWxQT
....
Wo+SRCsr6npfp1ctDhMtkXIeNT4lKf3qUGhP5tbx/TreaNF/d8zCeinGR/KeBGadMwIDAQAB
-----END RSA PUBLIC KEY-----

In the C++ code, I generated a RSA class with read the public key via a char*

const char rsaKey1[] = "-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAlUiMDQsBgj5P/T86w/eg9MXUj8M4WMVihP8YzmDxMqCFb7D+w4N/1XcxWxQT\n"
....
"Wo+SRCsr6npfp1ctDhMtkXIeNT4lKf3qUGhP5tbx/TreaNF/d8zCeinGR/KeBGadMwIDAQAB\n"
"-----END RSA PUBLIC KEY-----\n";


BIO* bio = BIO_new_mem_buf( rsaKey1, strlen(rsaKey1)); 

m_rsaPubKey = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL);

usigned the m_rsaPubKey , I have able to generate a std::vector of unsigned char with encrypted data

 std::vector<u8> Rsa::encrypt(std::string & msg)
 {

    std::vector<u8> encryptedData;

    char *encrypt = new char[RSA_size(m_rsaPubKey)];

    int encryptLen;

    if (encryptLen = RSA_public_encrypt(msg.size() + 1, (unsigned 
    char*)msg.c_str(), (unsigned char*)encrypt, m_rsaPubKey, 
    RSA_PKCS1_OAEP_PADDING) == -1)
    {
        LogOutSys("error encoding string");
    }

    for (u32 i = 0; i < strlen(encrypt); i++)
    {
        encryptedData.push_back(encrypt[i]);
    }

    delete encrypt;

    return encryptedData;
}

I don't get any errors while reading the public key or encrypting my data so I assume the encryption went ok.

then the data went throught a websocket and is received with node.js

the private key is read like this:

var rsa = new RSA(fs.readFileSync("./rsa-keys/sj_private_1.pem"),
{encryptionScheme :'pkcs8'})

and decoding

 var decrypted = rsa.decrypt(data)

where data is a buffer of same length and content (no corruption while sending via the websocket)

c++ side:

encrypted len 256, first bytes 117 125 58 109

node size :

Buffer(256) [117, 125, 58, 109, 38, 229, 7, 189, …]

the rsa.decrypt generated an exception :

TypeError: Cannot read property 'length' of null

I tried several encryptionScheme option (including the default , but always getting the same error or Incorrect key or data

3
  • Which RSA libraries are you using in C and in node? Commented Aug 11, 2017 at 11:16
  • node-rsa for decrypting , keypair for key generating. openSSL in the C++ part ( OpenSSL 1.0.2l 25 May 2017 ) Commented Aug 11, 2017 at 12:00
  • Which node-rsa? The one at github.com/rzcoder/node-rsa? Also, have you considered using WebSocket over TLS to achieve security? Lastly, note that in your code you use strlen(encrypt) which is not safe given that encrypt may contain embedded NULLs. What is RSA_size(m_rsaPubKey)? Commented Aug 11, 2017 at 13:13

1 Answer 1

1

Because of the random padding in OAEP, troubleshooting encryption issues with it can sometimes be a bit tricky.

For further troubleshooting use the following checklist to shoot down potential issues:

  • Make sure you use the same crypto mechanism on both ends. In your C++ code you are using RSA_PKCS1_OAEP_PADDING but the JavaScript lines in your question does not tell what mechanism you use there.
  • Make sure that the mechanisms are implemented the same ways in both C++ and Node libraries. It is crucial you have the same hashing method and MGF1 (mask generation function) in both implementations. This is one of the most typical failing points that I've seen in my career.
  • Since you are working with byte arrays, make sure you are not having any issues in the byte order. In other words, make sure both ends talks the same language in regard of endianness (For self-study: https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html).
Sign up to request clarification or add additional context in comments.

8 Comments

I noticed it works using RSA_PKCS1_PADDING on C++ side and {encryptionScheme :'pkcs1'} on node.js side. BUT : not always (probably because of some randomness... I dont think there s an issue with byte order as I dumped on both side the first bytes of the buffer and content is the same.
RSA_PKCS1_PADDING sounds so generic it probably means PKCS#1 v1.5. There is no random padding similar to OAEP so if it only works sometimes, you may want to take a look at potential memory leaks. Print out the hex value of the output of the encryption to verify it is always the same (with PKCS#1 v1.5). Also, when it is not working, what do you see/get?
when it's not working, the buffer size is not 256 bytes (eg : 63) , on node.js side I get the following : Error: Incorrect data or key
Wrong buffer size could be caused by a wrong key size. I'd recommend to check from debugger / debug prints what is the length of public key modulus on every run and see if it correlates with the buffer length.
@quniz: 'v1.5' encryption -- formally RSAES-PKCS1-v1_5, previously 'block type 2' in PKCS1v1 -- does use random padding, though separably which allows Bleichenbacher's (famous) adaptive-ciphertext oracle attack which OAEP fixes.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.