public-keycrypto++derber

Can't DER encode and BER decode RSA public key


I have problems using Crypto++ to save a RSA public key (that I obtained loading a private key file in PKCS#8 format). When decoding the key, I always get a BERDecodeErr exception.

Here is the code I am using:

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);

I also tried with the instructions commented above, without success.

How do you do to save or open the public key?

The public key looks like this in hex format, is there a tool to check its format / validity (regarding what crypto++ supports) ?

3081890281810097e24f2e95504a397e90fbc56d1b330ab2ab97a0d326007b890e40013f9e1d9bd9
f54b0c0840782ddae19b5b4595d8f8b9ffe0d2120174fcbc39585c5867cd2dfba69f8e540caa2c52
de8f08278a34e9249120500117f0ba756c5bb2be660013160db9f82f75deb7ccf63742a9e945da6c
cf30c2b109b73342daaabd02b872e50203010001

Solution

  • I'm not sure I understand your problem completely. But you look like you are on the right track with using either Load/Save or BERDecodePublicKey/DEREncodePublicKey.

    Here's how I would approach it given you have a PKCS#8 encoded private key.

    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);
    

    Then, you can use Gutmann's dumpasn1 to print it:

    $ dumpasn1 <public key>
    ...
    

    I believe you can also convert a private key/signer to a public key/verifier with:

    RSASSA_PKCS1v15_SHA_Signer signer;
    signer.AccessKey().Load(privateKey);
    
    RSASSA_PKCS1v15_SHA_Verifier verifier;
    signer.MakePublic(verifier);
    

    There's also a page on the Crypto++ wiki that talks about it in greater detail: Keys and Formats. And there's a page dedicated to PEM encoding, if interested: PEM Pack. If you want the PEM encoding, you have to compile the library yourself, though.


    Here's the code I used with the public key you posted. It had no problems.

    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");
    

    If you install the PEM Pack then you can add the following:

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

    That will get you:

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

    And:

    $ 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)
    

    Finally, the difference between: