Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I actually import a public key from a string ? #37

Closed
ta3pks opened this issue Feb 3, 2020 · 8 comments · Fixed by #38
Closed

How do I actually import a public key from a string ? #37

ta3pks opened this issue Feb 3, 2020 · 8 comments · Fixed by #38

Comments

@ta3pks
Copy link

ta3pks commented Feb 3, 2020

In go you simply pem.Decode and then x509.ParsePKIXPublicKey the given byte slice and you get a rsa.PublicKey. However, in the rust world none of those libraries are actually compatible with each other so how do I import an existing public key?

@tarcieri
Copy link
Member

tarcieri commented Feb 3, 2020

There are (at least) two possible formats an RSA public key could be in. Can you tell me if the PEM encoded key begins with BEGIN RSA PUBLIC KEY or BEGIN PUBLIC KEY?

The former is PKCS#1, and the latter is PKCS#8. In either case it's fairly easy to parse.

PKCS#1 RSA public keys are the (PEM encoding, starting with BEGIN RSA PUBLIC KEY of) the DER encoding of the following ASN.1 structure:

RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}

PKCS#8 RSA public keys are the (PEM encoding, starting with BEGIN PUBLIC KEY, of) the DER encoding of the following ASN.1 structure:

SubjectPublicKeyInfo  ::=  SEQUENCE  {
    algorithm  ::=  SEQUENCE  {
        algorithm               OBJECT IDENTIFIER, -- 1.2.840.113549.1.1.1 rsaEncryption (PKCS#1 1)
        parameters              ANY DEFINED BY algorithm OPTIONAL  },
    subjectPublicKey     BIT STRING {
        RSAPublicKey ::= SEQUENCE {
            modulus            INTEGER,    -- n
            publicExponent     INTEGER     -- e
        }
}

As you can see, PKCS#8 contains the PKCS#1 encoding, plus an additional header:

30 82 01 22          ;SEQUENCE (0x122 bytes = 290 bytes)
|  30 0D             ;SEQUENCE (0x0d bytes = 13 bytes) 
|  |  06 09          ;OBJECT IDENTIFIER (0x09 = 9 bytes)
|  |  2A 86 48 86   
|  |  F7 0D 01 01 01 ;hex encoding of 1.2.840.113549.1.1
|  |  05 00          ;NULL (0 bytes)
|  03 82 01 0F 00    ;BIT STRING  (0x10f = 271 bytes)

When Base64 encoded in a PEM wrapper, this header will be the following 32 Base64-encoded characters:

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A

With that treated as a special case (i.e. hardcoded), the code needed to parse the remaining RSAPublicKey as a SEQUENCE of two DER-encoded INTEGERs is not too far off from what's already in the ECDSA crate for parsing (and serializing) DER encoded ECDSA signatures, which are also a SEQUENCE of two DER-encoded INTEGERs (although that code doesn't quite handle INTEGERs as large as what's used by RSA, but fixing that should be simple):

https://github.com/RustCrypto/signatures/blob/master/ecdsa/src/convert.rs

I can also look into if BearSSL code for this already written, as that's where the above code was translated from anyway.

@ta3pks
Copy link
Author

ta3pks commented Feb 3, 2020

The theory is nice and simple but in practice for someone who just has a pubkey and wants to encrypt something for it without holding too much technical knowledge parsing the entire thing seems not a practical option.
Is there any crate you can suggest that handles parsing and gives me those 2 uints so I can make use of this crate?

@tarcieri
Copy link
Member

tarcieri commented Feb 3, 2020

@NikosEfthias I'm suggesting adding a feature to this crate to support parsing (and potentially serializing) PKCS#1 and/or PKCS#8 RSA public keys.

@ta3pks
Copy link
Author

ta3pks commented Feb 3, 2020

Do you mean the serde feature?
image

@tarcieri
Copy link
Member

tarcieri commented Feb 3, 2020

No, I mean as far as I can tell this crate doesn't support either PKCS#1 or PKCS#8-formatted public keys, but it wouldn't be too difficult to add and also seems important.

@ta3pks
Copy link
Author

ta3pks commented Feb 4, 2020

Oh, I see so I believe you can add a feature request flag to this ticket.
I couldn't use this crate so far and used OpenSSL instead btw seems the only option for people like myself who just want to use rsa encryption but not necesarily have a good understanding of the internals openssl seems a more viable option for now

@penumbra23
Copy link

Such a feature would be lovely, as for now I can't load any existing keys from a file and use them to enc/de-crypt.

@dignifiedquire
Copy link
Member

Yes, I would really like to see serialization and deserialization of the common formats as a feature

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants