jsonwebtoken icon indicating copy to clipboard operation
jsonwebtoken copied to clipboard

Support ED25519

Open rgarrigue opened this issue 2 years ago • 8 comments

Hello

This is a feature request to support ed25519. The reason is explained there https://github.com/mike-engel/jwt-cli/issues/173. Sadly I'm not able to make the related PR, because I know nothing about rust.

Best regards,

rgarrigue avatar Mar 08 '22 15:03 rgarrigue

I wouldn't be against it but someone would have to submit the PR.

Keats avatar Mar 08 '22 17:03 Keats

Is this feature supported? It seems to be in the library (e.g., from_ed_der), but attempts to use it don't seem to round-trip. (Verification always fails.)

roy-work avatar Jun 21 '22 22:06 roy-work

It's not supported

Keats avatar Jun 22 '22 07:06 Keats

Would be nice to see support for Ed25519 as the other curves may have some weaknesses

Cubxity avatar Jul 11 '22 12:07 Cubxity

What exactly isn't supported? It seems to be working fine for me. I'm not sure what I'm missing.

use jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation};
use ring::signature::KeyPair;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    sub: String,
    company: String,
    exp: usize,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let rng = ring::rand::SystemRandom::new();
    let pkcs8_bytes = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng)?;
    let key_pair = ring::signature::Ed25519KeyPair::from_pkcs8(pkcs8_bytes.as_ref())?;

    let enc_key = EncodingKey::from_ed_der(pkcs8_bytes.as_ref());
    let dec_key = DecodingKey::from_ed_der(key_pair.public_key().as_ref());

    let validation = Validation::new(jsonwebtoken::Algorithm::EdDSA);
    let header = Header::new(jsonwebtoken::Algorithm::EdDSA);

    let my_claims = Claims {
        sub: "[email protected]".to_owned(),
        company: "ACME".to_owned(),
        exp: std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_secs() as usize
            + 60,
    };

    let token = jsonwebtoken::encode(&header, &my_claims, &enc_key)?;
    let claims = jsonwebtoken::decode::<Claims>(&token, &dec_key, &validation)?;

    println!("{token}");
    println!("{claims:?}");
    Ok(())
}

Output:

eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjE2NzQ2NzUyMzl9.vUKPAbuzbwmfGZjg5NmcJO10o-nr2LT6FwZIC__GXnH__jGMEQbN3KqNkpiCNoAInYFQN4A2uDFUvyQLBurXCQ
TokenData { header: Header { typ: Some("JWT"), alg: EdDSA, cty: None, jku: None, jwk: None, kid: None, x5u: None, x5c: None, x5t: None, x5t_s256: None }, claims: Claims { sub: "[email protected]", company: "ACME", exp: 1674675239 } }

chanced avatar Jan 25 '23 19:01 chanced

Reading a pem ed25519 key definitely does not work.

GunnarMorrigan avatar Jun 15 '23 06:06 GunnarMorrigan

It seems like DecodingKey::from_ed_der function actually expects raw 32 bytes public key, which ring's Ed25519KeyPair::public_key returns. Also running openssl asn1parse -inform der -in file-with-pubkey shows again that these 32 bytes are not DER encoded. I've also additionally checked it using ed25519-dalek crate. So essentially it seems DecodingKey::from_ed_der name is just misleading and DecodingKey doesn't yet support DER encoded ed25519 public keys. Maybe it would be a good idea to add a new method like DecodingKey::from_ed behaving exactly the same as existing DecodingKey::from_ed_der, but specified in the descrition that it expects raw 32 bytes public key. What to do with existing misleading name of DecodingKey::from_ed_der I'm not sure, changing implementation would be a (potentially) quite annoying breaking change.

tokarevart avatar Jan 13 '24 04:01 tokarevart

Regarding PEM format I had no issues while testing just now.

tokarevart avatar Jan 13 '24 04:01 tokarevart