簡體   English   中英

從內存導入密鑰時,Crypto++ BERDecode 異常?

[英]Crypto++ BERDecode exception when importing key from memory?

我正在嘗試從內存中導入公鑰,但它失敗並出現以下異常:“BER 解碼錯誤”。 一旦我使用FileSource從文件中導入它,它就會成功。

為什么我無法從內存中解碼它,但可以成功地從文件中解碼? 我嘗試了Load()BERDecode()函數。

namespace CryptoHelper
{
    byte key[292] =
    {
        0x30, 0x82, 0x01, 0x20, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
        0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0D, 0x00, 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01,
        0x00, 0xB6, 0x87, 0x31, 0x96, 0xE3, 0xAD, 0x61, 0x66, 0x30, 0x0D, 0xE6, 0x91, 0xED, 0x9D, 0x41,
        0x4E, 0xA2, 0x30, 0x10, 0xCD, 0x5C, 0x24, 0x90, 0xD2, 0x9A, 0xD9, 0xBD, 0xF9, 0x70, 0x14, 0xF9,
        0x57, 0x36, 0xE7, 0xE7, 0x9D, 0xCF, 0xFE, 0x85, 0x6F, 0x28, 0x81, 0x16, 0x10, 0x95, 0x80, 0x2B,
        0xCA, 0xA2, 0xB7, 0x88, 0x95, 0xF1, 0xCA, 0x5E, 0xEF, 0xCD, 0x3B, 0xEC, 0x30, 0xB9, 0xE3, 0xC6,
        0x88, 0xB3, 0xF4, 0xA2, 0x5D, 0xF3, 0xC7, 0x9C, 0x2A, 0xA7, 0x54, 0xAE, 0xBF, 0xEC, 0x7D, 0x14,
        0xE8, 0x63, 0xE7, 0x2C, 0x8E, 0xAE, 0x06, 0xFF, 0xA2, 0x21, 0x04, 0xF8, 0x1B, 0x3F, 0x94, 0x01,
        0xFC, 0xDE, 0x28, 0xA1, 0x6F, 0x05, 0x76, 0xBE, 0x81, 0x6B, 0xF0, 0x60, 0x19, 0xB3, 0x8E, 0x6A,
        0xBE, 0x39, 0x54, 0xC3, 0xF5, 0xA8, 0xC9, 0xC0, 0x3F, 0x30, 0x87, 0x48, 0x64, 0xBE, 0x8E, 0x8A,
        0xFF, 0x8D, 0xC8, 0x51, 0xCC, 0x5A, 0x99, 0xD5, 0xDF, 0x0B, 0x41, 0x8F, 0xFE, 0xAD, 0xBC, 0xD2,
        0x01, 0x79, 0x6F, 0x6E, 0xFC, 0x46, 0xEC, 0x73, 0xD4, 0xF7, 0xD4, 0xD4, 0x34, 0x1F, 0xCF, 0x1E,
        0xBE, 0xA9, 0xD5, 0xDF, 0x9B, 0x45, 0x15, 0xF4, 0xB5, 0x0F, 0xA1, 0x22, 0x06, 0xED, 0x5B, 0x21,
        0xC0, 0x8C, 0x1C, 0xC8, 0xF3, 0x47, 0x7A, 0x6D, 0x3D, 0x03, 0x87, 0xF7, 0x0D, 0xF9, 0x5C, 0xF0,
        0xA9, 0xD0, 0xD4, 0xAD, 0x89, 0x86, 0x08, 0xAE, 0xC2, 0x4B, 0x2B, 0x1C, 0xC1, 0xCA, 0xA7, 0xBD,
        0x37, 0x5D, 0x62, 0xD9, 0x0A, 0xF8, 0x1F, 0x12, 0x64, 0xBA, 0xD1, 0x43, 0x33, 0xA2, 0xFC, 0xAD,
        0xE0, 0x5A, 0x17, 0x7B, 0x86, 0xD1, 0x8F, 0xF8, 0x05, 0x5F, 0xB6, 0x32, 0x59, 0xAB, 0x70, 0x1C,
        0xD4, 0x30, 0x68, 0xA2, 0xC6, 0x68, 0xD7, 0x7B, 0x21, 0xE3, 0xE9, 0x4D, 0x4C, 0x54, 0x40, 0x95,
        0xEB, 0x02, 0x01, 0x11,
    };

    AutoSeededRandomPool rng;       // TODO: Check whether this is thread-safe
    ArraySink keySink(key, 292);    // TODO: Check whether this is thread-safe
    RSA::PublicKey rsaPublic;       // TODO: Check whether this is thread-safe

    void EncryptBuffer()
    {
        std::string plain = "RSA Encryption", cipher, recovered;

        FileSource input("rsapublic.dat", true);

        // This one works perfectly
        // rsaPublic.BERDecode(input);
        rsaPublic.Load(keySink);

        RSAES_OAEP_SHA_Encryptor e(rsaPublic);

        // Encrypt
        StringSource ss1(plain, true,
            new PK_EncryptorFilter(rng, e, new StringSink(cipher)
            ));

        return;
    }
}

為什么我無法從內存中解碼它,但可以成功地從文件中解碼? 我嘗試了Load()BERDecode()函數。

你很近。 使用ArraySource而不是ArraySink來加載密鑰。 數據從源流向接收器。 另請參閱 Crypto++ wiki 上的ArraySourceArraySink

您還需要Load因為密鑰具有SubjectPublicKeyInfo前導碼。 另請參閱 Crypto++ wiki 上的密鑰和格式

$ cat test.cxx
#include "cryptlib.h"
#include "filters.h"
#include "osrng.h"
#include "files.h"
#include "rsa.h"
#include "hex.h"

#include <iostream>
#include <string>

using CryptoPP::byte;
extern const byte key[292];

int main (int argc, char* argv[])
{
    using namespace CryptoPP;
    AutoSeededRandomPool rng;
    ArraySource keySource(key, 292, true);

    RSA::PublicKey rsaPublic;
    rsaPublic.Load(keySource);
    RSAES_OAEP_SHA_Encryptor enc(rsaPublic);

    std::string plain = "RSA Encryption", cipher, recovered;    
    StringSource ss1(plain, true,
        new PK_EncryptorFilter(rng, enc, new StringSink(cipher)
    ));

    std::cout << "Encrypted: ";
    StringSource(cipher, true, new HexEncoder(new FileSink(std::cout)));
    std::cout << std::endl;

    return 0;
}

const byte key[292] =
{
    0x30, 0x82, 0x01, 0x20, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
    0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0D, 0x00, 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01,
    0x00, 0xB6, 0x87, 0x31, 0x96, 0xE3, 0xAD, 0x61, 0x66, 0x30, 0x0D, 0xE6, 0x91, 0xED, 0x9D, 0x41,
    0x4E, 0xA2, 0x30, 0x10, 0xCD, 0x5C, 0x24, 0x90, 0xD2, 0x9A, 0xD9, 0xBD, 0xF9, 0x70, 0x14, 0xF9,
    0x57, 0x36, 0xE7, 0xE7, 0x9D, 0xCF, 0xFE, 0x85, 0x6F, 0x28, 0x81, 0x16, 0x10, 0x95, 0x80, 0x2B,
    0xCA, 0xA2, 0xB7, 0x88, 0x95, 0xF1, 0xCA, 0x5E, 0xEF, 0xCD, 0x3B, 0xEC, 0x30, 0xB9, 0xE3, 0xC6,
    0x88, 0xB3, 0xF4, 0xA2, 0x5D, 0xF3, 0xC7, 0x9C, 0x2A, 0xA7, 0x54, 0xAE, 0xBF, 0xEC, 0x7D, 0x14,
    0xE8, 0x63, 0xE7, 0x2C, 0x8E, 0xAE, 0x06, 0xFF, 0xA2, 0x21, 0x04, 0xF8, 0x1B, 0x3F, 0x94, 0x01,
    0xFC, 0xDE, 0x28, 0xA1, 0x6F, 0x05, 0x76, 0xBE, 0x81, 0x6B, 0xF0, 0x60, 0x19, 0xB3, 0x8E, 0x6A,
    0xBE, 0x39, 0x54, 0xC3, 0xF5, 0xA8, 0xC9, 0xC0, 0x3F, 0x30, 0x87, 0x48, 0x64, 0xBE, 0x8E, 0x8A,
    0xFF, 0x8D, 0xC8, 0x51, 0xCC, 0x5A, 0x99, 0xD5, 0xDF, 0x0B, 0x41, 0x8F, 0xFE, 0xAD, 0xBC, 0xD2,
    0x01, 0x79, 0x6F, 0x6E, 0xFC, 0x46, 0xEC, 0x73, 0xD4, 0xF7, 0xD4, 0xD4, 0x34, 0x1F, 0xCF, 0x1E,
    0xBE, 0xA9, 0xD5, 0xDF, 0x9B, 0x45, 0x15, 0xF4, 0xB5, 0x0F, 0xA1, 0x22, 0x06, 0xED, 0x5B, 0x21,
    0xC0, 0x8C, 0x1C, 0xC8, 0xF3, 0x47, 0x7A, 0x6D, 0x3D, 0x03, 0x87, 0xF7, 0x0D, 0xF9, 0x5C, 0xF0,
    0xA9, 0xD0, 0xD4, 0xAD, 0x89, 0x86, 0x08, 0xAE, 0xC2, 0x4B, 0x2B, 0x1C, 0xC1, 0xCA, 0xA7, 0xBD,
    0x37, 0x5D, 0x62, 0xD9, 0x0A, 0xF8, 0x1F, 0x12, 0x64, 0xBA, 0xD1, 0x43, 0x33, 0xA2, 0xFC, 0xAD,
    0xE0, 0x5A, 0x17, 0x7B, 0x86, 0xD1, 0x8F, 0xF8, 0x05, 0x5F, 0xB6, 0x32, 0x59, 0xAB, 0x70, 0x1C,
    0xD4, 0x30, 0x68, 0xA2, 0xC6, 0x68, 0xD7, 0x7B, 0x21, 0xE3, 0xE9, 0x4D, 0x4C, 0x54, 0x40, 0x95,
    0xEB, 0x02, 0x01, 0x11
};

該程序的結果是:

$ ./test.exe
Encrypted: 004EE30C8B91F07056FAB43D6DB17DA0A193B19856BB725898301B5717B929066BC37
37F587063ECC4EA81A3ED06219C24335B3997A612C2B0BFAE17F555D6B05D759A1BE3D812B3E6018
6E114E13B6CD7D145D4DBB125D7B56F7640875F16854C911F4552272FBD3E3437E6C3CD6F6059FB5
C2ED50E62B65EAC9B78645E86C2EFC606FCAD2F823CA19F846C6F1837DDA4AA81CAA73108B30F8DC
9107FF442708CD97BF1800BA4E7FE60D3F5B08376B0BD9A41021FC5812FA4B0F1B2A08F504C2B622
A8684D189AD2BCDD85E647AAE2023D923F2F3B2531F315F97E0135489B282DB6F3C05F78233AC810
E184028743B943B07FFFEA93CC6A69511BF113888F2

如果添加以下內容,則可以將密鑰寫入文件:

FileSink fs("rsa.der");
fs.Put(key, sizeof(key));
fs.MessageEnd();

或者:

ArraySource(key, sizeof(key), true, new FileSink("rsa.der"));

然后,您可以使用 Gutmann 的dumpasn1檢查密鑰。 請注意,您有一個 RSA SubjectPublicKeyInfo。 當您有 SubjectPublicKeyInfo 或 PrivateKeyInfo 時,您可以使用Load()Save() (並使用BERDecodeDEREncode加載和保存沒有*Info標頭的公鑰或私鑰)。

$ dumpasn1 rsa.der
  0 288: SEQUENCE {
  4  13:   SEQUENCE {
  6   9:     OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
 17   0:     NULL
       :     }
 19 269:   BIT STRING, encapsulates {
 24 264:     SEQUENCE {
 28 257:       INTEGER
       :         00 B6 87 31 96 E3 AD 61 66 30 0D E6 91 ED 9D 41
       :         4E A2 30 10 CD 5C 24 90 D2 9A D9 BD F9 70 14 F9
       :         57 36 E7 E7 9D CF FE 85 6F 28 81 16 10 95 80 2B
       :         CA A2 B7 88 95 F1 CA 5E EF CD 3B EC 30 B9 E3 C6
       :         88 B3 F4 A2 5D F3 C7 9C 2A A7 54 AE BF EC 7D 14
       :         E8 63 E7 2C 8E AE 06 FF A2 21 04 F8 1B 3F 94 01
       :         FC DE 28 A1 6F 05 76 BE 81 6B F0 60 19 B3 8E 6A
       :         BE 39 54 C3 F5 A8 C9 C0 3F 30 87 48 64 BE 8E 8A
       :                 [ Another 129 bytes skipped ]
289   1:       INTEGER 17
       :       }
       :     }
       :   }

0 warnings, 0 errors.


AutoSeededRandomPool prng;      // TODO: Check whether this is thread-safe
ArraySink keySink(key, 292);    // TODO: Check whether this is thread-safe
RSA::PublicKey rsaPublic;       // TODO: Check whether this is thread-safe

關於評論...所有 Crypto++ 對象在類級別都是線程安全的,這意味着它們不共享數據。 這在自述文件中說明

Crypto++ 在類級別是線程安全的。 這意味着您可以在多線程應用程序中安全地使用 Crypto++,但是當多個線程訪問一個公共 Crypto++ 對象時,您必須提供同步。

這意味着,如果您有兩個線程使用同一個對象,那么您需要提供鎖。 例如,使用prng意味着生成器的內部狀態將發生變化。 沒有內部鎖,您必須序列化對prng訪問。

關於隨機數生成器,戴維(庫的原作者)建議為每個線程使用單獨的生成器。 來自郵件列表上 AutoSeededRandomPool 的使用

我建議每個線程一個實例,這樣您就不必擔心同步訪問它。 如果這樣更方便的話,每次使用一個實例也可以。 在大多數情況下,額外的系統開銷可能並不明顯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM