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

Implement decode_rsa, verify_rsa for using public key components instead of DER key. #69

Closed

Conversation

AaronFriel
Copy link

This addresses #68 and enables supporting JWTs from JSON Web Key sets where the JWK set exposes the (n, e) tuple.

Copy link
Owner

@Keats Keats left a comment

Choose a reason for hiding this comment

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

Thanks for the PR!
Is it possible to get the modulus/exponent from a .pem file? I am guessing most people will have a .pem file so it would be nice to have it work automagically.

I am a bit busy with Tera and Zola currently but am planning to work on this crate afterwards (along with #66) so it will be merged at that time.

src/crypto.rs Outdated Show resolved Hide resolved
src/crypto.rs Outdated Show resolved Hide resolved
@AaronFriel
Copy link
Author

AaronFriel commented Jan 5, 2019

@Keats, the use case is not wider file format support than .DER. This is about handling RFC 7517 - JSON Web Key (JWK). Here is Google's JWKS document, served from https://www.googleapis.com/oauth2/v3/certs:

{
  "keys": [
    {
      "kid": "7978a91347261a291bd71dcab4a464be7d279666",
      "e": "AQAB",
      "kty": "RSA",
      "alg": "RS256",
      "n": "sFlU5LpHUtYIm7B27iiu7c4ZPZk7ULUNmFdMVsTmYJxJqQBKUIKU9ozwF6TlUsECmYUMLpQhX_iHuaZRcpG2YiG7jbmi9HMlonIXX7uUe7PIf8rNHhveX_VI7ZpwPTnab3_7ciy_o8ZFde6KNltkx_DLRO6hXf6z6ow1APFIIriaNlF8niz5cy0fPIv0e_Z2p13Sz3mnAACjBKZGPw2X9GWh5XpRoDEQBcibXpeLuA7ti8zLZuH-9ybXOoou699fr4QHFxUkcd_8fFqmzO5PKnlOnJZ0gtuXCCYYc9XPX-WSqlqbGNMZy0Giu2wHbNbeWdepkgVlGuJonTnMx4gLuQ",
      "use": "sig"
    },
    {
      "kid": "8aad66bdefc1b43d8db27e65e2e2ef301879d3e8",
      "e": "AQAB",
      "kty": "RSA",
      "alg": "RS256",
      "n": "vvAaaSpfr934Qx0ioFiWsopq7UCfLNn0zjYVbq4bvUcGSXU9kowYmQArR7WlIkjk1moffla0UV75QRaQPATva1oD5xQnnW-20haeMWTSsMgUHoN0Np9AD8ffPz-DfMJBOHIo4REL1BFFS33HSZgPl0hxJ-5UScqr4lW1JMy5XGeRho30dnmKTpakU1Oc35hFYKSea_O2SXfmbqiAkWlWkilEzgHq4pzVWiDZe4ZgfMdD4vqkSNrO_PkBFBT1mnBJztQ1h4v1jvUW-zeYYwIcPTaOX-xOTiGH9uQkcNPpe5pBrIZJqR5VNrDl_bJOmvVlhhXZSn4fkxA8kyQcZXGaTw",
      "use": "sig"
    }
  ]
}

We only have access to a base64url encoded modulus and exponent. In order for me to use this library with JWKS, I need to be able to decode tokens using the modulus and exponent tuple.

…ead of DER key.

Signed-off-by: Aaron Friel <aaron@twochairs.com>
@jamwaffles
Copy link

jamwaffles commented Jan 12, 2019

Another use case that I'm after is taking an RSA private key file from a Google Cloud service account JSON definition. It would be great to see RSA support added instead of having to extract the key using jq and converting it to a DER file. Does this PR address using PEM keys with the encode() method?

@AaronFriel
Copy link
Author

@Keats I addressed your requested changes.

@Keats
Copy link
Owner

Keats commented Feb 4, 2019

To be sure I don't forget anything, RSA keys can be set:

@jamwaffles I believe #74 fixes your issue no? Looks like it's for Google Cloud services as well

@Keats Keats mentioned this pull request Feb 4, 2019
@AaronFriel
Copy link
Author

No, PKCS #8 is typically base64 encoded in the standard .pem format:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIBrzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQImQO8S8BJYNACAggA
MB0GCWCGSAFlAwQBKgQQ398SY1Y6moXTJCO0PSahKgSCAWDeobyqIkAb9XmxjMmi
hABtlIJBsybBymdIrtPjtRBTmz+ga40KFNfKgTrtHO/3qf0wSHpWmKlQotRh6Ufk
0VBh4QjbcNFQLzqJqblW4E3v853PK1G4OpQNpFLDLaPZLIyzxWOom9c9GXNm+ddG
LbdeQRsPoolIdL61lYB505K/SXJCpemb1RCHO/dzsp/kRyLMQNsWiaJABkSyskcr
eDJBZWOGQ/WJKl1CMHC8XgjqvmpXXas47G5sMSgFs+NUqVSkMSrsWMa+XkH/oT/x
P8ze1v0RDu0AIqaxdZhZ389h09BKFvCAFnLKK0tadIRkZHtNahVWnFUks5EP3C1k
2cQQtWBkaZnRrEkB3H0/ty++WB0owHe7Pd9GKSnTMIo8gmQzT2dfZP3+flUFHTBs
RZ9L8UWp2zt5hNDtc82hyNs70SETaSsaiygYNbBGlVAWVR9Mp8SMNYr1kdeGRgc3
7r5E
-----END ENCRYPTED PRIVATE KEY-----

That's RFC 5208.

This is to handle RFC 7517.

@AaronFriel
Copy link
Author

@Keats Is there a blocker in this? This library isn't usable in a JWKS environment (like those configured by Istio, or Google's JWKS infrastructure, etc.) without the ability to decode based solely on the exponent and modulus.

@Keats
Copy link
Owner

Keats commented Feb 19, 2019

Not anything blocking this PR in particular, but the next version is blocked on #76 to avoid having to publish multiple major versions

@Terkwood
Copy link

Terkwood commented Feb 19, 2019 via email

@AaronFriel
Copy link
Author

@Keats this should be semver compatible as a "minor" bump, barring API changes right?

@Keats
Copy link
Owner

Keats commented Feb 26, 2019

It would work as a minor bump but then if the plan in #76 goes ahead would be removed very soon after.
Hopefully I can find some time this weekend to work on #76 to have a clearer idea

@manifest
Copy link

manifest commented Mar 5, 2019

@Keats We don't want to pass a PEM encoded or JWK encoded text representation of a binary key as an argument of jsonwebtoken::decode function and decode the key each time the function is called, right?

@manifest
Copy link

manifest commented Mar 5, 2019

I'm trying to understand if this feature somehow relates or blocks the feature with ES256 support.

@Keats
Copy link
Owner

Keats commented Mar 8, 2019

We don't want to pass a PEM encoded or JWK encoded text representation of a binary key as an argument of jsonwebtoken::decode function and decode the key each time the function is called, right?

Have a look at the first post of #76, I think providing a function for each usecase is going to be easier in the end as we can see it's going to be too messy trying to make everything fit in a single function as we can already see.

@manifest
Copy link

manifest commented Mar 9, 2019

Have a look at the first post of #76

Ok, I see. Having decoder types seems as a good idea.

@Keats Keats changed the base branch from master to next March 22, 2019 08:27
@Keats
Copy link
Owner

Keats commented Mar 22, 2019

Can someone look at the conflicts with after the ES support has been merged in next?

@mann-ed
Copy link

mann-ed commented Mar 30, 2019

@AaronFriel and @Keats I am using Aaron's branch as i'm working on a keycloak adaptor for a project i'm on. I am able to get things to work, and would like to see this merged. If needed i can look at resolving the merge conflicts.

@AaronFriel
Copy link
Author

@mann-ed do you want to take a look first?

@mann-ed
Copy link

mann-ed commented Apr 3, 2019

@AaronFriel Yes, i'll take a look at it tomorrow. I'll get back to you by Friday April 5th as i have other obligations i need to attend to in the next few days.

@mann-ed
Copy link

mann-ed commented Apr 6, 2019

@AaronFriel Ok, i have it updated, and i created a pull request to your branch. I don't know if that is what you wanted me to do.
AaronFriel#1

Let me know if you have time to review, or if there is something else i should do.

@Keats
Copy link
Owner

Keats commented Apr 12, 2019

@mann-ed @AaronFriel I'll pull your changes directly next week unless there is an issue

Close button is too close...

@Keats Keats closed this Apr 12, 2019
@Keats Keats reopened this Apr 12, 2019
@Keats Keats mentioned this pull request May 15, 2019
@AaronFriel
Copy link
Author

AaronFriel commented May 19, 2019

@mann-ed @Keats Sorry, I haven't been doing the best at watching my GitHub notifications. I merged the PR from @mann-ed into my branch, which updated this pull request.

@Keats
Copy link
Owner

Keats commented May 20, 2019

No worries @AaronFriel
Have you seen #89? It looks like a very sane approach to all the various key formats without duplicating all the functions

@AaronFriel
Copy link
Author

@Keats would it be acceptable to add a key format for "KeyFormat::RSAModulusExponentPair"? Or what would you call it?

@Keats
Copy link
Owner

Keats commented May 31, 2019

The name seems good to me. What do you think of this approach of using a KeyFormat enum?

@AaronFriel
Copy link
Author

AaronFriel commented May 31, 2019

I'm not sure, to be honest, because it looks like it's assumed that the Key k must be a [u8], but that's not the case here. I'd have to create an (arbitrary) binary encoding of the modulus and exponent just to unwrap those later on, which seems silly.

I think the trait structure needs reworking, but I haven't dug into it enough to make a specific comment on how. verify taking a &[u8] is still not correct for my use case. I have an exponent and a modulus, which are already correctly encoded byte vectors. Concatenating them is not correct, and it seems very silly to serialize them to a byte array to pass to verify, then deserialize inside the method to recover the key pair.

It seems like instead maybe verify should be generic in a type K that is an instance of Key, and maybe Key has an associated type Data as well as a method that uses it. For PKCS8 and DER, Key::Data = &[u8], for my use case, Key::Data = (&[u8], &[u8])?

@Keats
Copy link
Owner

Keats commented Jun 3, 2019

It seems like instead maybe verify should be generic in a type K that is an instance of Key, and maybe Key has an associated type Data as well as a method that uses it. For PKCS8 and DER, Key::Data = &[u8], for my use case, Key::Data = (&[u8], &[u8])?

Sounds like a good idea.

@Keats
Copy link
Owner

Keats commented Jun 6, 2019

I'm thinking an enum would be better than a trait in the end, any reason to prefer a trait other than adding one being a breaking change?

cc @Jake-Shadle

@Keats
Copy link
Owner

Keats commented Jun 16, 2019

@AaronFriel I pushed an enum version to #91
This way we can have a Key::ModulusExponent { n, e } enum member. I've made a temporary verify_ring_rsa in crypto.rs to extract the bytes from the enum which you can change/remove depending on what's easier.

Another thing I'm thinking is to maybe keep your sign_rsa/verify_rsa since that allows restricting the Key type at the type level rather than having an error at runtime.
Eg you can't verify a token HS512 with a modulus/exponent so it would be nice to error at compilation.

@Keats Keats mentioned this pull request Jun 22, 2019
@Keats
Copy link
Owner

Keats commented Jul 13, 2019

I've integrated that PR in 10105af

Can anyone try the next branch to see if that works for them?

@Keats
Copy link
Owner

Keats commented Aug 12, 2019

Closing in favour of #91

@Keats Keats closed this Aug 12, 2019
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.

7 participants