如何从字符串/字节数组或任何其他容器加载私钥/公钥

deW*_*eW1 7 c++ cryptography rsa public-key-encryption crypto++

是否有可能存储在一个源例如RSA公钥/私钥byte[]string或任何其他container与使用该密钥用于加密/解密?

文件中的解码函数如下所示:

void Decode(const string& filename, BufferedTransformation& bt)
{
    // http://www.cryptopp.com/docs/ref/class_file_source.html
    FileSource file(filename.c_str(), true /*pumpAll*/);

    file.TransferTo(bt);
    bt.MessageEnd();
}
Run Code Online (Sandbox Code Playgroud)

从文件加载密钥不是我想要的.

我知道它必须是可能的,因为我可以创建密钥AutoSeededRandomPool.

我只是不知道如何使用现有的.

也许我在文档中忽略了这一部分.

sof*_*ess 15

加密+按键和格式加密+ RSA加密的页面可能会感兴趣.

如果您正在生成这样的RSA参数:

AutoSeededRandomPool rng;

InvertibleRSAFunction params;
params.GenerateRandomWithKeySize(rng, 2048);
Run Code Online (Sandbox Code Playgroud)

您可以使用DEREncodeBERDecode方法InvertibleRSAFunction分别对所有参数进行编码和解码:

{
    FileSink output("rsaparams.dat");
    params.DEREncode(output);
}

InvertibleRSAFunction params2;
{
    FileSource input("rsaparams.dat", true);
    params2.BERDecode(input);
}
Run Code Online (Sandbox Code Playgroud)

编码/解码独立的私人和公共的材料,使用DEREncode以及BERDecode对方法RSA::PrivateKeyRSA::PublicKey对象本身:

// Initialize keys from generated params
RSA::PrivateKey rsaPrivate(params);
RSA::PublicKey rsaPublic(params);

// Write keys to file
{
    FileSink output("rsaprivate.dat");
    rsaPrivate.DEREncode(output);
}
{
    FileSink output("rsapublic.dat");
    rsaPublic.DEREncode(output);
}

// Read keys from file into new objects
RSA::PrivateKey rsaPrivate2;
RSA::PublicKey rsaPublic2;
{
    FileSource input("rsaprivate.dat", true);
    rsaPrivate2.BERDecode(input);
}
{
    FileSource input("rsapublic.dat", true);
    rsaPublic2.BERDecode(input);
}
Run Code Online (Sandbox Code Playgroud)

FileSource并且FileSink只是您可以使用的示例源和接收对象.编码/解码例程将BufferedTransformation对象作为参数,因此您可以使用该接口的任何其他合适的实现.

例如,ArraySink可用于将数据写入您提供的内存缓冲区,并且StringSource(也称为别名ArraySource)可用于从缓冲区读取.

这里有一些代码显示使用ArraySinkArraySource通过以下方式往返私钥材料std::vector<byte>:

RSA::PrivateKey rsaPrivate(params);
std::vector<byte> buffer(8192 /* buffer size */);

ArraySink arraySink(&buffer[0], buffer.size());
rsaPrivate.DEREncode(arraySink);

// Initialize variable with the encoded key material
// (excluding unwritten bytes at the end of our buffer object)
std::vector<byte> rsaPrivateMaterial(
    &buffer[0],
    &buffer[0] + arraySink.TotalPutLength());

RSA::PrivateKey rsaPrivate2;
ArraySource arraySource(
    &rsaPrivateMaterial[0],
    rsaPrivateMaterial.size(),
    true);
rsaPrivate2.BERDecode(arraySource);
Run Code Online (Sandbox Code Playgroud)

(另请参阅@ jww的答案,以获取使用a避免固定大小缓冲区的示例ByteQueue).

另一个例子是使用a std::string来存储密钥材料并使用StringSink类来写入,这避免了一些缓冲区管理(字符串将自动调整大小以匹配编码的数据量).请注意,即使它位于std::string对象中,它仍然是二进制数据.

RSA::PrivateKey rsaPrivate(params);

std::string rsaPrivateMaterial;
StringSink stringSink(rsaPrivateMaterial);
rsaPrivate.DEREncode(stringSink);

RSA::PrivateKey rsaPrivate2;
StringSource stringSource(rsaPrivateMaterial, true);
rsaPrivate2.BERDecode(stringSource);
Run Code Online (Sandbox Code Playgroud)

或者,如果您想自己控制格式,可以使用InvertibleRSAFunction对象或关键对象的方法来提取各个参数(如上面的"Crypto ++ RSA Cryptography"链接所示)并使用它来提取存储值以您自己的格式:

const Integer& n = params.GetModulus();
const Integer& p = params.GetPrime1();
const Integer& q = params.GetPrime2();
const Integer& d = params.GetPrivateExponent();
const Integer& e = params.GetPublicExponent();
Run Code Online (Sandbox Code Playgroud)

这些然后可以恢复到新的InvertibleRSAFunctionRSA::*Key从文件或容器阅读时,通过使用相应的设置方法(例如SetModulus(),SetPrime1()等).