在 Java 和 Crypto++ 代码之间传递 RSA 密钥
Passing RSA keys between Java and Crypto++ code
我有一个用 java 编写的服务器,它生成 RSA 密钥对。我想在C++客户端使用私钥解密
这是我用来创建私钥的代码:
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(4096);
KeyPair keyPair = keyGen.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
byte[] encoded = privateKey.getEncoded();
String b64Encoded = Base64.getEncoder().encodeToString(encoded);
然后我保存 base64 编码的字符串并尝试将其作为私钥加载到我的 cpp 代码中。
我把base64字符串解码成二进制数组,然后用下面的代码尝试加载私钥(encodedString应该是base64解码后的DER编码数据):
ByteQueue queue;
StringSource ss(encodedString,true);
ss.TransferTo(queue);
queue.MessageEnd();
key.BERDecodePrivateKey(queue, false , queue.MaxRetrievable());
但是此代码总是崩溃并出现异常:CryptoPP::BERDecodeErr
.
我相信这两个库都使用 PKCS#8 对关键参数进行编码。
注意: 当我使用 crypto++ 创建密钥对然后对其进行编码 (DER + base64) 时,我在 java 中得到一个 3172/3176 字符的字符串代码我得到一个 3168 个字符的字符串。我不确定此信息是否有帮助。
看来您需要调用 Load
而不是 BERDecodePrivateKey
。当你有一个密钥+信息(如版本和算法 ID)时,你调用 Load
;当你只有一把钥匙时,你打电话给 BERDecodePrivateKey
。以下对我有用。
如果私钥受密码保护,那么您将需要PEM Pack。 PEM 包是一个社区贡献,但它像适当的库一样得到维护。
$ cat rsa_java.java
import java.io.*;
import java.util.*;
import java.security.*;
public class rsa_java {
public static void main (String[] args) throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(4096);
KeyPair keyPair = keyGen.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
byte[] encodedPrivateKey = privateKey.getEncoded();
String b64Encoded = Base64.getEncoder().encodeToString(encodedPrivateKey);
try (PrintStream out = new PrintStream(new FileOutputStream("rsa_key.txt")))
{
out.print(b64Encoded);
}
}
并且:
$ cat rsa_cryptopp.cxx
#include <iostream>
using namespace std;
#include "cryptopp/rsa.h"
#include "cryptopp/files.h"
#include "cryptopp/osrng.h"
#include "cryptopp/base64.h"
using namespace CryptoPP;
int main(int argc, char* argv[])
{
try
{
RSA::PrivateKey key;
FileSource fs("rsa_key.txt", true, new Base64Decoder);
key.Load(fs);
cout << "Loaded RSA key" << endl;
AutoSeededRandomPool prng;
key.Validate(prng, 3);
cout << "Validated RSA key" << endl;
}
catch(const Exception& ex)
{
cout << "Exception: " << ex.what() << endl;
}
return 0;
}
结果是:
$ javac rsa_java.java && java rsa_java
$ g++ -I. rsa_cryptopp.cxx cryptopp/libcryptopp.a -o rsa_cryptopp.exe
$ ./rsa_cryptopp.exe
Loaded RSA key
Validated RSA key
为了完整起见,这里是使用 Base64 编码的密钥。它的 3168 字节:
$ fold -w 80 -s rsa_key.txt
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
我有一个用 java 编写的服务器,它生成 RSA 密钥对。我想在C++客户端使用私钥解密
这是我用来创建私钥的代码:
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(4096);
KeyPair keyPair = keyGen.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
byte[] encoded = privateKey.getEncoded();
String b64Encoded = Base64.getEncoder().encodeToString(encoded);
然后我保存 base64 编码的字符串并尝试将其作为私钥加载到我的 cpp 代码中。
我把base64字符串解码成二进制数组,然后用下面的代码尝试加载私钥(encodedString应该是base64解码后的DER编码数据):
ByteQueue queue;
StringSource ss(encodedString,true);
ss.TransferTo(queue);
queue.MessageEnd();
key.BERDecodePrivateKey(queue, false , queue.MaxRetrievable());
但是此代码总是崩溃并出现异常:CryptoPP::BERDecodeErr
.
我相信这两个库都使用 PKCS#8 对关键参数进行编码。
注意: 当我使用 crypto++ 创建密钥对然后对其进行编码 (DER + base64) 时,我在 java 中得到一个 3172/3176 字符的字符串代码我得到一个 3168 个字符的字符串。我不确定此信息是否有帮助。
看来您需要调用 Load
而不是 BERDecodePrivateKey
。当你有一个密钥+信息(如版本和算法 ID)时,你调用 Load
;当你只有一把钥匙时,你打电话给 BERDecodePrivateKey
。以下对我有用。
如果私钥受密码保护,那么您将需要PEM Pack。 PEM 包是一个社区贡献,但它像适当的库一样得到维护。
$ cat rsa_java.java
import java.io.*;
import java.util.*;
import java.security.*;
public class rsa_java {
public static void main (String[] args) throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(4096);
KeyPair keyPair = keyGen.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
byte[] encodedPrivateKey = privateKey.getEncoded();
String b64Encoded = Base64.getEncoder().encodeToString(encodedPrivateKey);
try (PrintStream out = new PrintStream(new FileOutputStream("rsa_key.txt")))
{
out.print(b64Encoded);
}
}
并且:
$ cat rsa_cryptopp.cxx
#include <iostream>
using namespace std;
#include "cryptopp/rsa.h"
#include "cryptopp/files.h"
#include "cryptopp/osrng.h"
#include "cryptopp/base64.h"
using namespace CryptoPP;
int main(int argc, char* argv[])
{
try
{
RSA::PrivateKey key;
FileSource fs("rsa_key.txt", true, new Base64Decoder);
key.Load(fs);
cout << "Loaded RSA key" << endl;
AutoSeededRandomPool prng;
key.Validate(prng, 3);
cout << "Validated RSA key" << endl;
}
catch(const Exception& ex)
{
cout << "Exception: " << ex.what() << endl;
}
return 0;
}
结果是:
$ javac rsa_java.java && java rsa_java
$ g++ -I. rsa_cryptopp.cxx cryptopp/libcryptopp.a -o rsa_cryptopp.exe
$ ./rsa_cryptopp.exe
Loaded RSA key
Validated RSA key
为了完整起见,这里是使用 Base64 编码的密钥。它的 3168 字节:
$ fold -w 80 -s rsa_key.txt
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