Keats / jsonwebtoken

JWT lib in rust
MIT License
1.67k stars 266 forks source link

Possibility of a `from_pem` constructor for Decoding and Encoding keys #292

Open krishna-kashyap opened 1 year ago

krishna-kashyap commented 1 year ago

I was looking at using the from PEM options for the Decoding key and seems like despite of having all the information from the parsing at the time of creating PemEncodingKey, the methods exposed need the user to explicitly specify the type of the key which is then checked on a match and and error emitted.

So could we have a from_pem constructor which in turn does a match and creates the encoding and decoding keys?

If it makes sense, I'd be interested in adding it

Keats commented 1 year ago

I think the current situation is fine, can you write some pseudo-code on how it would look with what you're proposing?

krishna-kashyap commented 1 year ago

Something like this? However this needed changing a few permissions from the other module. This is possibly not the best approach, better one would actually be to possibly expose the type and content of the key for the decoding/encoding keys in the decoder. More like as_private_key and as_public_key which provides the information about the Family and the Content

+    /// If you are loading a public key in a PEM format, use this.
+    #[cfg(feature = "use_pem")]
+    pub fn from_pem(key: &[u8]) -> Result<Self> {
+        let pem_key = PemEncodedKey::new(key)?;
+        match pem_key.pem_type {
+            PemType::EcPublic => {
+                Ok(DecodingKey {
+                    family: AlgorithmFamily::Ec,
+                    kind: DecodingKeyKind::SecretOrDer(pem_key.as_ec_public_key().unwrap().to_vec()),
+                })
+            },
+            PemType::EdPublic => {
+                Ok(DecodingKey {
+                        family: AlgorithmFamily::Ed,
+                        kind: DecodingKeyKind::SecretOrDer(pem_key.as_ed_public_key().unwrap().to_vec()),
+                    })
+                },
+            PemType::RsaPublic => {
+                Ok(DecodingKey {
+                        family: AlgorithmFamily::Rsa,
+                        kind: DecodingKeyKind::SecretOrDer(pem_key.as_rsa_key().unwrap().to_vec()),
+                    })

...skipping 1 line
+
+            _ => Err(ErrorKind::InvalidKeyFormat.into()),
+        }
+    }
+
Keats commented 1 year ago

I think I prefer seeing the expected alg type in the user code.

krishna-kashyap commented 1 year ago

However I see this more like from_jwt instead of expecting user to instead call the from components themselves by actually parsing the key component from the token when they have a PEM key instead of the standard components.