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

Add parsing for pkcs1 and pkcs8 encoded rsa keys #38

Merged
merged 4 commits into from
Feb 26, 2020

Conversation

aloucks
Copy link
Contributor

@aloucks aloucks commented Feb 13, 2020

Adds simple functions for parsing pkcs1 and pkcs8 encoded keys and a pem feature that re-exports the pem crate with TryFrom implementations.

The TryFrom implementations will auto-detect pkcs1 or pkcs8 via the header tags.

let pem = rsa::pem::parse(private_key_pem)?;
let private_key = RSAPrivateKey::try_from(pem)?;

let pem = rsa::pem::parse(public_key_pem)?;
let public_key= RSAPublicKey::try_from(pem)?;

Or, manually:

// -----BEGIN RSA PRIVATE KEY-----
let private_key = rsa::parse_private_key_pkcs1(pkcs1_private_key_base64_decoded)?;
// -----BEGIN RSA PUBLIC KEY-----
let public_key = rsa::parse_public_key_pkcs1(pkcs1_public_key_base64_decoded)?;

// -----BEGIN PRIVATE KEY-----
let private_key = rsa::parse_private_key_pkcs8(pkcs8_private_key_base64_decoded)?;
// -----BEGIN PUBLIC KEY-----
let public_key = rsa::parse_public_key_pkcs8(pkcs8_public_key_base64_decoded)?;

Fixes #37

EDIT:

Bikeshed: Should the rsa::parse_[public|private]_key_pkcs[1|8] functions be prefixed with decode_ instead?

@aloucks
Copy link
Contributor Author

aloucks commented Feb 13, 2020

The build is failing on the hex crate with rust 1.36. I believe this is unrelated to the pull request:

error: enum variants on type aliases are experimental
  --> /home/travis/.cargo/registry/src/jackfan.us.kg-1ecc6299db9ec823/hex-0.4.1/src/error.rs:30:13
   |
30 |             Self::InvalidStringLength => write!(f, "Invalid string length"),
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
error: Could not compile `hex`.

@tarcieri
Copy link
Member

Thanks for this, and looks like some unrelated fixes are needed for the hex crate.

This implementation looks okay to me. I'm not super wild about the rsa::parse_[public|private]_key_pkcs functions.

I think those should probably be methods on the individual key types. See the FromPkcs8 trait in the signatory crate as a potential example of an API.

The TryFrom impls look good to me.

src/lib.rs Outdated

pub use self::key::{PublicKey, RSAPrivateKey, RSAPublicKey};
pub use self::padding::PaddingScheme;
use self::parse::{parse_private_key_pkcs1, parse_private_key_pkcs8, parse_public_key_pkcs1, parse_public_key_pkcs8};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this is unnecessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed it and used the full crate path where referenced.

@tarcieri
Copy link
Member

Cool, well other than the unrelated errors from hex this looks good to me.

@dignifiedquire @str4d thoughts?

I think we can probably simplify the implementation and eliminate the simple_asn1 dependency by vendoring just the ASN.1 DER support we need and looking for a hardcoded PKCS#8 header ala BearSSL and the corresponding translation in the ecdsa crate, but I think that's a debatable tradeoff and not worth blocking this PR over.

Copy link
Member

@dignifiedquire dignifiedquire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm overall, some notes, thank you!

/// following a `-----BEGIN RSA PUBLIC KEY-----` header.
///
/// <https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem>
pub fn from_pkcs1(der: &[u8]) -> Result<RSAPublicKey> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you add a doctesz for this?

/// Expects one of the following `pem` headers:
/// - `-----BEGIN PRIVATE KEY-----`
/// - `-----BEGIN RSA PRIVATE KEY-----`
fn try_from(pem: pem::Pem) -> Result<RSAPrivateKey> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you add a doctest for this, so it is easy to see in the docs how it works?

/// Expects one of the following `pem` headers:
/// - `-----BEGIN PUBLIC KEY-----`
/// - `-----BEGIN RSA PUBLIC KEY-----`
fn try_from(pem: pem::Pem) -> Result<RSAPublicKey> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dignifiedquire I've added examples for all of the new functions.

@aloucks aloucks force-pushed the parse branch 3 times, most recently from e37075c to dcdb757 Compare February 16, 2020 17:49
@aloucks
Copy link
Contributor Author

aloucks commented Feb 21, 2020

@dignifiedquire @tarcieri Anything else needed before merging?

@dignifiedquire
Copy link
Member

@aloucks sorry for the delay, I want to fix CI before merging, but it looks good thank you 👌

@aloucks
Copy link
Contributor Author

aloucks commented Feb 26, 2020

@dignifiedquire A new version of hex was published and the build is passing now.

@tarcieri
Copy link
Member

:shipit:

@tarcieri tarcieri merged commit 54ecc60 into RustCrypto:master Feb 26, 2020
@penumbra23 penumbra23 mentioned this pull request Feb 27, 2020
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 this pull request may close these issues.

How do I actually import a public key from a string ?
3 participants