lawliet89 / biscuit

JOSE (JSON Web Token) Library for Rust
https://lawliet89.github.io/biscuit
Other
181 stars 35 forks source link

Generate a JWT with a RSA signature #166

Open stephane-ein opened 4 years ago

stephane-ein commented 4 years ago

Hello,

I would like to generate a JWT with a RSA signature and I try to do the following :

let private_key = "-----BEGIN PRIVATE KEY-----\nMIIjioNDS78DsqqpCnWsI@9122 ... WA==-----END PRIVATE KEY-----"
let signing_secret = Secret::bytes_from_str(private_key.as_str());

let expected_claims = ClaimsSet::<CreateSessionClaims> {
    registered: RegisteredClaims {
        ..Default::default()
    }
};

let expected_jwt = JWT::new_decoded(From::from(
    RegisteredHeader {
        algorithm: SignatureAlgorithm::RS256,
        ..Default::default()
    }),expected_claims.clone());

let token = expected_jwt.into_encoded(&signing_secret).unwrap();
let token = token.unwrap_encoded().to_string();

But I got the following error :

GenericError("Invalid secret type. A RsaKeyPair is required")

I looked through the documentation and the code and it seems we cannot generate a secret from a RSA string value but only from a file (with rsa_keypair_from_file) or from jwk::RSAKeyParameters.

Is there a way to generate an encoding key with RSA like this library https://github.com/Keats/jsonwebtoken ?

let private_key = "-----BEGIN PRIVATE KEY-----\nMIIjioNDS78DsqqpCnWsI@9122 ... WA==-----END PRIVATE KEY-----"
let token = encode(&Header::new(Algorithm::RS256), &my_claims, &EncodingKey::from_rsa_pem(private_key.to_string()))?)?;

Regards

JadedEvan commented 3 years ago

@stephane-ein I was looking at the issue that you opened in the firestore-db-and-auth repository. Is this still an issue with recent changes to this crate? Digging into the code it as thought it now supports reading from a string value.

Scratch my earlier comment. I think I've figured out that there is something wrong in the example that you've shared above. It would appear that the RSA private key that you're using in the example is not a DER encoded private key. The jsonwebtoken crate requires that you use DER format. Any JWT that uses the RS256 signature is going to require a key pair, not an individual file.

I'm able to get around the error you've received above by using the Secret::rsa_keypair_from_file method. A few changes are required to the dummy code to get this working:

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
struct PrivateClaims {
    company: String,
    department: String,
}

let signing_secret = biscuit::jws::Secret::rsa_keypair_from_file(path).unwrap();

let expected_claims = ClaimsSet::<PrivateClaims> {
    registered: biscuit::RegisteredClaims {
        ..Default::default()
    },
    private: PrivateClaims {
        company: "company".to_string(),
        department: "department".to_string()
    }
};

let expected_jwt = JWT::new_decoded(From::from(
    biscuit::jws::RegisteredHeader {
        algorithm: biscuit::jwa::SignatureAlgorithm::RS256,
        ..Default::default()
    }),expected_claims.clone());

let token = expected_jwt.into_encoded(&signing_secret).unwrap();
let token = token.unwrap_encoded().to_string();
jbg commented 2 years ago

Note that if you have a PEM string as in @stephane-ein's code, you can strip the first and last lines (-----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----) and base64-decode to get DER.