加载在JSBN中创建的RSA公钥,然后加密消息

Load RSA public key created in JSBN, then encrypt a message

本文关键字:公钥 然后 加密 消息 RSA JSBN 创建 加载      更新时间:2023-09-26

我正试图使用JSBN在JavaScript中创建一个RSA密钥对,并将公钥传输到Crypto++。然后,我试图用Crypto++加密一条消息,并将其发送回JavaScript并解密。

但我在这方面相对较新,所以我认为我做错了什么(数据没有被解密)

任何帮助都将不胜感激:D

这是我的cpp代码

Integer n(nStr->c_str()),
e("0x10001");
RSA::PublicKey pubKey;
pubKey.Initialize(n, e);
AutoSeededRandomPool rng;
if (!pubKey.Validate(rng, 3))
    throw std::exception("Rsa private key validation failed");
////////////////////////////////////////////////
// Encryption
RSAES_PKCS1v15_Encryptor enc(pubKey);
StringSource ss1(data, true,
        new PK_EncryptorFilter(rng, enc,
            new StringSink(retStr)
        ));
std::string retData2 = "";
StringSource ss2((const byte*)retStr.data(), retStr.size(), true,
        new Base64Encoder(
            new StringSink(retData2)
        ));
retStr = retData2;

我的javascript代码

// nStr in CPP is "0x" + localStorage.getItem("rsa_public")  from javascript
// data in CPP is "secret"
var rsa = new RSAKey();
var publickey = localStorage.getItem("rsa_public");
var privatekey = localStorage.getItem("rsa_private");
rsa.setPrivate(publickey, "10001", privatekey);
alert(b64tohex(dec) + "'n" + rsa.encrypt("secret")); <-- these don't match at all .. and ofc rsa.decrypt returns null

javascript中的dec是来自CPP 的retStr

JSBN和您的Crypto++代码使用的PKCS#1 v1.5填充是随机填充,因此如果您使用相同的密钥加密数据,它看起来会有所不同。您必须通过双向加密和解密来检查您的实现是否有效。

RSAES_PKCS1v15_Encryptor enc(pubKey);
StringSource ss1(data, true,
        new PK_EncryptorFilter(rng, enc,
            new StringSink(retStr)
        ));
...
StringSource ss2((const byte*)retStr.data(), retStr.size(), true,
        new Base64Encoder(
            new StringSink(retData2)
        ));

对于使用Javascript和JSBN进行互操作,我不确定这是否正确。单独使用它是正确的,而且对于与OpenSSL的互操作也是正确的。

Crypto++使用早期的Base64编码方案。它出现在当时的电子邮件和其他标准中(当时大约是20世纪90年代)。字母表使用加号(+)和正斜杠(/)字符。

Javascript和JSON技术,如JSON Web密钥(JWK),倾向于使用URL或Web安全字母表进行Base64编码。字母表使用减号(-)和下划线(_)字符。

旧的和新的Base64编码方案都在RFC 4648、Base16、Base32和Base64数据编码中指定。

您应该获取Base64URLEncoder的补丁,并将其应用于Crypto++源之上。修补后,您将拥有现有的Base6Encoder和新的Base64URLEncoder。最后,重新编译并重新安装库。您必须对其进行修补,因为它不是Wei Dai编写和提供的Crypto++库的一部分。

然后,执行以下操作:

RSAES_PKCS1v15_Encryptor enc(pubKey);
string encoded;
StringSource ss(data, true,
        new PK_EncryptorFilter(prng, enc,
            new Base64URLEncoder(
                new StringSink(encoded)
        )));
// Print encoded cipher text
cout << encoded << endl;
return encoded;

至于";这些根本不匹配"-我想这是意料之中的事。RSA加密使用随机填充,因此当您对m1m2消息进行加密时,密文是不同的。它被称为";语义安全";这是一种强烈的(更强的?)安全概念。这样,坏人就无法判断同一条信息何时被发送了两次。