【问题标题】:RSA encryption between c++ and node.jsc++ 和 node.js 之间的 RSA 加密
【发布时间】:2018-01-19 17:54:31
【问题描述】:

我必须通过网络(websocket)发送一些加密数据

我使用以下 node.js 模块生成了一个密钥对:

https://github.com/juliangruber/keypair

我的公钥如下所示:

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

在 C++ 代码中,我生成了一个通过 char* 读取公钥的 RSA 类

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);

使用 m_rsaPubKey 签名,我能够生成带有加密数据的无符号字符的 std::vector

 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;
}

我在读取公钥或加密我的数据时没有收到任何错误,因此我认为加密正常。

然后数据通过 websocket 并通过 node.js 接收

私钥是这样读取的:

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

和解码

 var decrypted = rsa.decrypt(data)

其中数据是长度和内容相同的缓冲区(通过 websocket 发送时不会损坏)

c++端:

encrypted len 256, first bytes 117 125 58 109

节点大小:

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

rsa.decrypt 产生了一个异常:

TypeError: Cannot read property 'length' of null

我尝试了几个加密方案选项(包括默认的,但总是得到相同的错误或不正确的密钥或数据

【问题讨论】:

  • 您在 C 和节点中使用了哪些 RSA 库?
  • node-rsa 用于解密,keypair 用于生成密钥。 C++ 部分中的 openSSL(OpenSSL 1.0.2l 2017 年 5 月 25 日)
  • 哪个节点-rsa? github.com/rzcoder/node-rsa 的那个?另外,您是否考虑过使用基于 TLS 的 WebSocket 来实现安全性?最后,请注意在您的代码中使用strlen(encrypt),这是不安全的,因为encrypt 可能包含嵌入的NULL。 RSA_size(m_rsaPubKey) 是什么?

标签: c++ node.js encryption cryptography rsa


【解决方案1】:

由于 OAEP 中的随机填充,使用它解决加密问题有时会有点棘手。

如需进一步故障排除,请使用以下清单解决潜在问题:

  • 确保在两端使用相同的加密机制。在您的 C++ 代码中,您使用的是 RSA_PKCS1_OAEP_PADDING,但您问题中的 JavaScript 行并没有说明您在那里使用的机制。
  • 确保这些机制在 C++ 和 Node 库中的实现方式相同。在两种实现中使用相同的散列方法和 MGF1(掩码生成函数)至关重要。这是我职业生涯中见过的最典型的失败点之一。
  • 由于您使用的是字节数组,请确保您在字节顺序上没有任何问题。换句话说,确保两端在字节序方面使用相同的语言(自学:https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html)。

【讨论】:

  • 我注意到它在 C++ 端使用 RSA_PKCS1_PADDING 并在 node.js 端使用 {encryptionScheme :'pkcs1'}。但是:并非总是如此(可能是因为一些随机性......我认为字节顺序没有问题,因为我在两边都转储了缓冲区的第一个字节并且内容是相同的。
  • RSA_PKCS1_PADDING 听起来很笼统,可能意味着 PKCS#1 v1.5。没有类似于 OAEP 的随机填充,因此如果它仅在某些时候有效,您可能需要查看潜在的内存泄漏。打印出加密输出的十六进制值以验证它始终相同(使用 PKCS#1 v1.5)。此外,当它不工作时,你会看到/得到什么?
  • 当它不工作时,缓冲区大小不是 256 字节(例如:63),在 node.js 端我得到以下信息:错误:不正确的数据或密钥
  • 错误的缓冲区大小可能是由错误的密钥大小引起的。我建议检查调试器/调试打印每次运行时公钥模数的长度是多少,看看它是否与缓冲区长度相关。
  • @quniz: 'v1.5' 加密——正式的 RSAES-PKCS1-v1_5,以前在 PKCS1v1 中的“块类型 2”——确实使用随机填充,尽管可分离地允许 Bleichenbacher(著名)自适应-OAEP 修复的密文预言机攻击。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
  • 2015-02-27
  • 1970-01-01
  • 2018-07-06
  • 2014-04-13
  • 1970-01-01
  • 2012-06-02
相关资源
最近更新 更多