【问题标题】:Can't BER decode an RSA public key无法对 RSA 公钥进行 BER 解码
【发布时间】:2015-03-10 08:57:48
【问题描述】:

我遇到了与asked here 类似的问题。我有一个我认为是 DER 编码的 RSA PKCS#1 公钥,我想用它来验证我拥有的其他一些数据/签名,但我什至无法让解码工作。

我使用的代码与该问题的解决方案中提出的代码相同。

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

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

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

当我使用该问题中发布的密钥时,代码可以工作,但是当我尝试使用我的密钥时,它会失败。我是不是格式不对?还有什么?我对加密还很陌生,所以这可能是一些愚蠢/显而易见的事情......

这是我要使用的密钥。

30819D300D06092A864886F70D010101050003818B0030818702818100B126088
1BDFE84463D88C6AB8DB914A2E593893C10508B8A5ABDF692E9A5419A3EDBAE86
A052849983B75E3B425C18178B260003D857DF0B6505C6CF9C84F5859FCE3B63F
1FB2D4818501F6C5FA4AD1430EEB081A74ABD74CD1F4AA1FCCA3B88DD0548AED3
4443CEB52444EAE9099AA4FE66B2E6224D02381C248025C7044079020111

编辑:

忘了说,这是我得到的错误:

Error!
Dynamic exception type: class CryptoPP::BERDecodeErr
std::exception::what: BER decode error

【问题讨论】:

  • 对我来说,它看起来不像 PKCS#1 RSA 公钥的 BER 编码。也许是 X.509 SubjectPublicKeyInfo?
  • 这是一些与密钥用法相关的代码,让我相信它是 PKCS#1(基本上它是对象的 VTable 类型,似乎是从我转储的密钥构造的) :pastie.org/pastes/9827716/text
  • 这当然可能是一个红鲱鱼......

标签: c++ cryptography public-key-encryption public-key crypto++


【解决方案1】:

它是SubjectPublicKeyInfo (SPKI)。你需要在HexDecoding之后调用Load

首先,将其保存到ASN.1/DER中的一个文件中,看看它是什么:

string dek("30819D300D06092A864886F70D010101050003818B0030818702818100B126088"
       "1BDFE84463D88C6AB8DB914A2E593893C10508B8A5ABDF692E9A5419A3EDBAE86"
       "A052849983B75E3B425C18178B260003D857DF0B6505C6CF9C84F5859FCE3B63F"
       "1FB2D4818501F6C5FA4AD1430EEB081A74ABD74CD1F4AA1FCCA3B88DD0548AED3"
       "4443CEB52444EAE9099AA4FE66B2E6224D02381C248025C7044079020111");

HexDecoder decoder(new FileSink("key.der", true));
decoder.Put((const byte*)dek.data(), dek.size());
decoder.MessageEnd();

那么,看看 Gutmann 的 dumpasn1 是什么:

$ dumpasn1 key.der 
  0 157: SEQUENCE {
  3  13:   SEQUENCE {
  5   9:     OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
 16   0:     NULL
       :     }
 18 139:   BIT STRING, encapsulates {
 22 135:     SEQUENCE {
 25 129:       INTEGER
       :         00 B1 26 08 81 BD FE 84 46 3D 88 C6 AB 8D B9 14
       :         A2 E5 93 89 3C 10 50 8B 8A 5A BD F6 92 E9 A5 41
       :         9A 3E DB AE 86 A0 52 84 99 83 B7 5E 3B 42 5C 18
       :         17 8B 26 00 03 D8 57 DF 0B 65 05 C6 CF 9C 84 F5
       :         85 9F CE 3B 63 F1 FB 2D 48 18 50 1F 6C 5F A4 AD
       :         14 30 EE B0 81 A7 4A BD 74 CD 1F 4A A1 FC CA 3B
       :         88 DD 05 48 AE D3 44 43 CE B5 24 44 EA E9 09 9A
       :         A4 FE 66 B2 E6 22 4D 02 38 1C 24 80 25 C7 04 40
       :         79
157   1:       INTEGER 17
       :       }
       :     }
       :   }

rsaEncryption (1 2 840 113549 1 1 1) 告诉你它是一个 RSA 密钥和 SPKI。


所以我可以这样做:

AutoSeededRandomPool prng;
string dek("30819D300D06092A864886F70D010101050003818B0030818702818100B126088"
           "1BDFE84463D88C6AB8DB914A2E593893C10508B8A5ABDF692E9A5419A3EDBAE86"
           "A052849983B75E3B425C18178B260003D857DF0B6505C6CF9C84F5859FCE3B63F"
           "1FB2D4818501F6C5FA4AD1430EEB081A74ABD74CD1F4AA1FCCA3B88DD0548AED3"
           "4443CEB52444EAE9099AA4FE66B2E6224D02381C248025C7044079020111");

try {

    ByteQueue queue;
    HexDecoder decoder(new Redirector(queue));

    decoder.Put((const byte*)dek.data(), dek.size());
    decoder.MessageEnd();

    RSASSA_PKCS1v15_SHA_Verifier verifier;
    verifier.AccessKey().Load(queue);

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

    cout << "Verified key" << endl;
}
catch(CryptoPP::Exception& ex)
{
    cerr << ex.what() << endl;
}

程序结果(如预期):

$ ./cryptopp-test.exe
Verified key

基于您的 Pastebin 并带有以下内容(我添加了一些相当糟糕的格式):

text:1002712F                 
mov
     [ebp+a1], offset ??_7?$TF_VerifierImpl@U?$TF_SignatureSchemeOptions@V?
     $TF_SS@UPKCS1v15@CryptoPP@@VSHA1@2@URSA@2@H@CryptoPP@@URSA@2@
     VPKCS1v15_SignatureMessageEncodingMethod@2@VSHA1@2@@CryptoPP@@@CryptoPP@@6B?
     $TF_VerifierImpl@U?$TF_SignatureSchemeOptions@V?
     $TF_SS@UPKCS1v15@CryptoPP@@VSHA1@2@URSA@2@H@CryptoPP@@URSA@2@
     VPKCS1v15_SignatureMessageEncodingMethod@
     2@VSHA1@2@@CryptoPP@@@CryptoPP@@@ ; const
     CryptoPP::TF_VerifierImpl<CryptoPP::TF_SignatureSchemeOptions<CryptoPP::TF_SS<
     CryptoPP::PKCS1v15,CryptoPP::SHA1,CryptoPP::RSA,int>,
     CryptoPP::RSA,CryptoPP::PKCS1v15_SignatureMessageEncodingMethod,
     CryptoPP::SHA1>>::`vftable'{for `CryptoPP::TF_VerifierImpl<
     CryptoPP::TF_SignatureSchemeOptions<CryptoPP::TF_SS<
     CryptoPP::PKCS1v15,CryptoPP::SHA1,CryptoPP::RSA,int>,
     CryptoPP::RSA,CryptoPP::PKCS1v15_SignatureMessageEncodingMethod,CryptoPP::SHA1>>'

我猜RSASSA_PKCS1v15_SHA_Verifier 会没事的。但是直到您尝试使用编码签名后您才会知道。

如果RSASSA_PKCS1v15_SHA_Verifier 不起作用,请尝试添加使用SHA256typedef

typedef RSASS<PKCS1v15, SHA256>::Signer RSASSA_PKCS1v15_SHA256_Signer;
typedef RSASS<PKCS1v15, SHA256>::Verifier RSASSA_PKCS1v15_SHA256_Verifier;

这是来自rsa.h 库的原始typedefs

00161 typedef RSASS<PKCS1v15, SHA>::Signer RSASSA_PKCS1v15_SHA_Signer;
00162 typedef RSASS<PKCS1v15, SHA>::Verifier RSASSA_PKCS1v15_SHA_Verifier;

Crypto++ wiki 在Keys and Formats 上有一个页面。在您看到具体案例之前,这似乎很杂乱无章:) 它甚至向您展示了如何使用其他库(如 OpenSSL 和 GnuTLS)创建密钥。

【讨论】:

  • A++ 当然,我一直喜欢this ASN.1 encoder,尽管如果它是答案的基础,也建议从该站点复制解码。
  • 这非常有帮助,谢谢!现在无法让签名验证拖曳玩得很好,但这可能是我解释数据错误的另一种情况......
  • @RaptorFactor - 如果您可以发布公钥、示例消息和消息上的签名,那么我们可能会提供帮助。不过,请在一个新问题中这样做。
  • @Owlstead - 我完全忘记了那个工具。这是我偶尔会记得的那些链接之一。
  • @jww 我搞定了!签名和其他一些易失性数据嵌入到我要验证的消息中,因此需要在验证签名之前将其剥离。我正在这样做,但我的代码中有一个错误,这意味着我没有做到 100% 正确。一旦我比较了使用我的工具制作的十六进制转储与使用我试图与之交互操作的工具制作的十六进制转储,很明显这就是问题所在。再次感谢您的帮助,您太棒了。
猜你喜欢
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 1970-01-01
相关资源
最近更新 更多