提问者:小点点

WinCrypt RSA vs Java Org.Bouncycastle


所以这里有一个问题。 我在一个Windows系统上有一个旧代码,它只接受一个短字符串,然后用一个公共RSA密钥对它进行CryptEncrypt。 这里是最小的工作示例(避免任何检查以使其更短。也避免释放)

std::string testData = "12345678";
HCRYPTPROV context;
CryptAcquireContext(&context, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);

auto pubK = FromBase64(PublicKey);
CERT_PUBLIC_KEY_INFO *pubKeyInfo = nullptr;
DWORD keyLength = 0;
CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, 
    pubK.data(), pubK.size(), 
    CRYPT_ENCODE_ALLOC_FLAG, nullptr, 
    &pubKeyInfo, &keyLength);

HCRYPTKEY key;
CryptImportPublicKeyInfo(context, X509_ASN_ENCODING, pubKeyInfo, &key);

std::vector<std::uint8_t> result(testData.begin(), testData.end());
DWORD size = testData.size();

CryptEncrypt(key, NULL, true, 0, result.data(), &size, result.size());
result.resize(size);
size = testData.size();
CryptEncrypt(key, NULL, true, 0, result.data(), &size, result.size());

std::cout << ToBase64(result) << "\n";

代码工作并返回一个base64编码的字符串。 类似<代码

然后我必须用运行Java的另一边的私钥来解密这个字符串。 我使用Bouncycastle:

    try {
        Security.addProvider(new BouncyCastleProvider()); 
        String value = "";
        AsymmetricKeyParameter privateKey = 
            (AsymmetricKeyParameter) PrivateKeyFactory.createKey(Base64.getDecoder().decode(privateKeyValue));
        AsymmetricBlockCipher e = new RSAEngine();
        e = new org.bouncycastle.crypto.encodings.PKCS1Encoding(e);
        e.init(false, privateKey);

        byte[] messageBytes = Base64.getDecoder().decode(inputdata);
        byte[] hexEncodedCipher = e.processBlock(messageBytes, 0, messageBytes.length);
        value = new String(hexEncodedCipher);
        System.out.println(value);
        return value;
    }
    catch (Exception e) {
        System.out.println(e);
    }

这段代码显示了下一个错误:

org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.

而且我相信我在windows端漏掉了一些东西,因为如果我在Java端使用相同的密钥,并且用相同的公钥加密相同的数据,解密就会像预期的那样工作。

这里是我用openssl为这个问题(RSA 2048)生成的密钥:
private:

MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCeL7K++3+vl52Q
WFC6ThgvNPlhHLlP5ylIMi/7Gy60wcCHtx8R5Hzi2j7Kx/uBXyr7SCbePS7NtqHx
meVK3VhEvYHz2uYaUNf6GqJgNNjfRymnL5ll8K8lq1wym6A7KZ+L3qLHH1oI6GfW
+uf32nUfy1PQvsatPN7aiJ4ymiaJj2LcI6Bp78CINsu56Cx9QBN9uoXqKO/7NjOz
y2GRdYdckiqCkcmGDzA4/5tJROxj21gUbxwoUR+yz2sVFGlcJycsDDJiIXiPjbVN
XgM/YfmRjdAPQQwXXj9AK5w/dp9TPq621WqYES74rIY05cba4v1kihmFbs0DHLrV
fQZB0Pu9AgMBAAECggEAGuD//nO9vpiErYJUNVQPx/W4akf3NRySZzIf9QspZI2H
qYf0P5YTonhzMwHIOrNxGkGoWRsMWOgvnF4KGC6EUSniaw1HDDGwgU8FSFOyhj4R
VddAuZGsMTps8CyBjYwFED9EaZFqOxlCi8UWpYb5X+2s0EuadtVhCMEuIGsRIU53
mfW11182YtbAI7Zqi7wg/w0yRz5rVj4ph8nbSFPgi6qtVWA9bxVxNeRTXyQDWjUU
NFQzGcRG6D/SYTnRzTndVM5TmTwEVt0hvJNA2/pMWF5XMu6B2exOpJIVVVdQ40l/
XHh33SU8+gQYY56rHzFebCa0Nuxwdk0paluv+x3CAQKBgQDKwe8QXfNlMDqrM06n
iq/NwKE7tB+1gs1nKr4qZdbI71IzgQJgIJcxbJwbuE6z6Yk8PoancEELH9mSY7EN
YGeSO3QsO1LF1vyJWgWQU1G3pfC9sh8sY6f9WYg8+JogIeJsgjwf7PXrGaBq8++Q
GBMUATzPAh/ERIqUip0nEQ2IJwKBgQDHuYgPvv77qhLc+ZNOdhaZtibeVsFx50V+
a+qR+INSTJ/CChNkoVtMg803ZQWckJBOYL/TS2Mw+ctNomUg+ImjULGT9GzqMeme
HkPpAj5pNyNVpRfVNZfmS2cwwuRyE1QbFGs3C4p7D5MKKCfl4/8MBQXtJGWrQZFr
owh2NNyHewKBgHsMmSYorlcBnwlZOOnK7AiFWBRgq0G/4SI0OXaHmYMWYp+pMqTe
AoPXMyJLh0/+ce/izlt9b6vtp2AFKmVA1XpUpJtXYVN5tocw3+GH/zbh+SlWmT6a
OFAz7s953CeWCNDrdMu3RkNoqQdfhUrAoYtpeNr0ogy9wBCH0vnrinfPAoGBALNy
U/hpz+lH1qjqKFsPqKC001ljM21msL60sU4zrbHNHKEXsnLwsvodVc3Wm2MfVDjH
nrJ2gomnde2r4hbsl6W/w70+mHkXHWKuqK97D54zJzE1IyOygmctCmr6QIzqJuAp
yWbsnKCSzrcKe0aHQkmHXdrCoAJt5/2AvwKN3jJvAoGAIaLts1F7shIZ365FXyWD
poOFtXsNRXESkcYpJ2Pn+K0fUNtdH4BtR/5Z5bsEWXBf2LbL7s15UZFZbck0KH3K
22BRgPQze7wEhMVFlIMNhF17WrOh2NTGUAVz2CYSthbYh0QSI+5XJk0AEfiQcqYk
+E4bZw/RUTY94V+ITEK6F8g=

公共

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAni+yvvt/r5edkFhQuk4Y
LzT5YRy5T+cpSDIv+xsutMHAh7cfEeR84to+ysf7gV8q+0gm3j0uzbah8ZnlSt1Y
RL2B89rmGlDX+hqiYDTY30cppy+ZZfCvJatcMpugOymfi96ixx9aCOhn1vrn99p1
H8tT0L7GrTze2oieMpomiY9i3COgae/AiDbLuegsfUATfbqF6ijv+zYzs8thkXWH
XJIqgpHJhg8wOP+bSUTsY9tYFG8cKFEfss9rFRRpXCcnLAwyYiF4j421TV4DP2H5
kY3QD0EMF14/QCucP3afUz6uttVqmBEu+KyGNOXG2uL9ZIoZhW7NAxy61X0GQdD7
vQIDAQAB

我哪里错了?


共1个答案

匿名用户

cryptencrypt以little-endian格式返回密文,请参见cryptencrypt(最后一节的备注)。 因此,对于Java中的解密,字节数组messagebytes必须反转,例如这里。