【问题标题】:Can't DER encode and BER decode RSA public key无法对 RSA 公钥进行 DER 编码和 BER 解码
【发布时间】:2014-10-16 00:09:50
【问题描述】:

我在使用 Crypto++ 保存 RSA 公钥时遇到问题(我获得了以 PKCS#8 格式加载私钥文件)。在解码密钥时,我总是得到一个BERDecodeErr 异常。

这是我正在使用的代码:

CryptoPP::RSASSA_PKCS1v15_SHA_Signer   _signer;
CryptoPP::RSASSA_PKCS1v15_SHA_Verifier _verifier;
CryptoPP::ByteQueue                    bytes;

//_signer.AccessPublicKey().Save(bytes); // seem to save private key instead
_signer.AccessKey().DEREncodePublicKey(bytes);

//_verifier.AccessKey().Load(bytes);
//_verifier.AccessKey().BERDecodePublicKey(bytes, 0, 0);
_verifier.AccessPublicKey().Load(bytes);

我也尝试了上面评论的说明,但没有成功。

如何保存或打开公钥?

十六进制格式的公钥看起来像这样,是否有工具检查其格式/有效性(关于crypto++支持什么)?

3081890281810097e24f2e95504a397e90fbc56d1b330ab2ab97a0d326007b890e40013f9e1d9bd9
f54b0c0840782ddae19b5b4595d8f8b9ffe0d2120174fcbc39585c5867cd2dfba69f8e540caa2c52
de8f08278a34e9249120500117f0ba756c5bb2be660013160db9f82f75deb7ccf63742a9e945da6c
cf30c2b109b73342daaabd02b872e50203010001

【问题讨论】:

  • 你是怎么解决这个问题的?
  • 谢谢,您的解决方案解决了这个问题

标签: public-key crypto++ der ber


【解决方案1】:

我不确定我是否完全理解您的问题。但是您看起来使用Load/SaveBERDecodePublicKey/DEREncodePublicKey 是在正确的轨道上。

如果你有一个 PKCS#8 编码的私钥,我会这样处理它。

FileSource privateKey("<private key>", true);
RSASSA_PKCS1v15_SHA_Signer signer;    
signer.AccessKey().Load(privateKey);

AutoSeededRandomPool prng;
bool valid = signer.AccessKey().Validate(prng, 3);
...

RSASSA_PKCS1v15_SHA_Verifier verifier(signer);
FileSink publicKey("<public key>", true);

verifier.AccessKey().Save(publicKey);

然后,您可以使用Gutmann's dumpasn1 进行打印:

$ dumpasn1 <public key>
...

我相信您还可以使用以下方法将私钥/签名者转换为公钥/验证者:

RSASSA_PKCS1v15_SHA_Signer signer;
signer.AccessKey().Load(privateKey);

RSASSA_PKCS1v15_SHA_Verifier verifier;
signer.MakePublic(verifier);

Crypto++ wiki 上还有一个页面更详细地讨论了它:Keys and Formats。如果有兴趣,还有一个专门用于 PEM 编码的页面:PEM Pack。如果你想要 PEM 编码,你必须自己编译库。


这是我与您发布的公钥一起使用的代码。没有问题。

string key = "3081890281810097e24f2e95504a397e90fbc56d1b330ab2ab97a0d326007b890e40013f9e1d9bd9 \
    f54b0c0840782ddae19b5b4595d8f8b9ffe0d2120174fcbc39585c5867cd2dfba69f8e540caa2c52 \
    de8f08278a34e9249120500117f0ba756c5bb2be660013160db9f82f75deb7ccf63742a9e945da6c \
    cf30c2b109b73342daaabd02b872e50203010001";

ByteQueue queue;
StringSource ss(key, true, new HexDecoder(new Redirector(queue)));

RSASSA_PKCS1v15_SHA_Verifier verifier;
verifier.AccessKey().BERDecodePublicKey(queue, false, 0);

AutoSeededRandomPool prng;
bool result = verifier.AccessKey().Validate(prng, 3);
if(!result)
    throw Exception(Exception::OTHER_ERROR, "Failed to validate public key");

如果您安装了PEM Pack,那么您可以添加以下内容:

FileSink sink("public-key.pem", true);
PEM_Save(sink, verifier.GetKey());

这会让你得到:

$ cat public-key.pem 
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCX4k8ulVBKOX6Q+8VtGzMKsquX
oNMmAHuJDkABP54dm9n1SwwIQHgt2uGbW0WV2Pi5/+DSEgF0/Lw5WFxYZ80t+6af
jlQMqixS3o8IJ4o06SSRIFABF/C6dWxbsr5mABMWDbn4L3Xet8z2N0Kp6UXabM8w
wrEJtzNC2qq9Arhy5QIDAQAB
-----END PUBLIC KEY-----

还有:

$ openssl rsa -in public-key.pem -pubin -text -noout
Public-Key: (1024 bit)
Modulus:
    00:97:e2:4f:2e:95:50:4a:39:7e:90:fb:c5:6d:1b:
    33:0a:b2:ab:97:a0:d3:26:00:7b:89:0e:40:01:3f:
    9e:1d:9b:d9:f5:4b:0c:08:40:78:2d:da:e1:9b:5b:
    45:95:d8:f8:b9:ff:e0:d2:12:01:74:fc:bc:39:58:
    5c:58:67:cd:2d:fb:a6:9f:8e:54:0c:aa:2c:52:de:
    8f:08:27:8a:34:e9:24:91:20:50:01:17:f0:ba:75:
    6c:5b:b2:be:66:00:13:16:0d:b9:f8:2f:75:de:b7:
    cc:f6:37:42:a9:e9:45:da:6c:cf:30:c2:b1:09:b7:
    33:42:da:aa:bd:02:b8:72:e5
Exponent: 65537 (0x10001)

最后,两者的区别:

  • verifier.AccessKey():获取RSA::Public键,键是非常量
  • verifier.GetKey():获取RSA::Public键,键为const

【讨论】:

  • 解决方案是使用_verifier.AccessKey().BERDecodePublicKey(bytes, false, 0);。我之前没有看到这个方法可用(必须以某种神秘的方式继承),自动完成甚至不起作用。
  • @Mildred 您在原始帖子中使用BERDecodePublicKey 评论了代码:_verifier.AccessKey().BERDecodePublicKey(bytes, 0, 0);,那么这里出了什么问题..?
猜你喜欢
  • 2015-03-10
  • 1970-01-01
  • 2017-04-16
  • 2012-05-09
  • 2010-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多