From a05c16869abed017b4372c1a107c86161f36adc3 Mon Sep 17 00:00:00 2001 From: Andrew Korzhuev Date: Fri, 8 Sep 2023 18:35:40 +0200 Subject: [PATCH] jwt: remove openssl dep --- Cargo.toml | 1 + jwt/Cargo.toml | 2 +- jwt/README.md | 2 +- jwt/examples/json_api.rs | 2 +- jwt/src/lib.rs | 47 +++++++++++++++++++++++++++------------- 5 files changed, 36 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 751c311..0bb17d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "jwt", "snowflake-api" diff --git a/jwt/Cargo.toml b/jwt/Cargo.toml index cfcfbc1..1a36323 100644 --- a/jwt/Cargo.toml +++ b/jwt/Cargo.toml @@ -13,10 +13,10 @@ license = "Apache-2.0" [dependencies] thiserror = "1" +rsa = "0.9" sha2 = "0.10" base64 = "0.21" jsonwebtoken = "8" -openssl = "0.10" serde = "1" time = "0.3" diff --git a/jwt/README.md b/jwt/README.md index 84ca490..8614c44 100644 --- a/jwt/README.md +++ b/jwt/README.md @@ -19,7 +19,7 @@ use std::fs; use snowflake_jwt; fn get_token(private_key_path: &str, account_identifier: &str, username: &str) -> Result { - let pem = fs::read(private_key_path)?; + let pem = fs::read_to_string(private_key_path)?; let full_identifier = format!("{}.{}", account_identifier, username); let jwt = snowflake_jwt::generate_jwt_token(&pem, &full_identifier)?; diff --git a/jwt/examples/json_api.rs b/jwt/examples/json_api.rs index 2211233..33da289 100644 --- a/jwt/examples/json_api.rs +++ b/jwt/examples/json_api.rs @@ -42,7 +42,7 @@ struct Args { fn main() -> Result<()> { let args = Args::parse(); - let pem = fs::read(&args.private_key)?; + let pem = fs::read_to_string(&args.private_key)?; let full_identifier = format!("{}.{}", &args.account_identifier, &args.username); let jwt = snowflake_jwt::generate_jwt_token(&pem, &full_identifier)?; diff --git a/jwt/src/lib.rs b/jwt/src/lib.rs index b20c349..a0a96eb 100644 --- a/jwt/src/lib.rs +++ b/jwt/src/lib.rs @@ -6,21 +6,35 @@ use base64::Engine; use jsonwebtoken::{encode, Algorithm, EncodingKey, Header}; -use openssl::rsa::Rsa; +use rsa::pkcs1::EncodeRsaPrivateKey; +use rsa::pkcs8::{DecodePrivateKey, EncodePublicKey}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use thiserror::Error; use time::{Duration, OffsetDateTime}; -use crate::JwtError::JwtEncodingError; - #[derive(Error, Debug)] pub enum JwtError { #[error(transparent)] - OpenSslError(#[from] openssl::error::ErrorStack), + Rsa(#[from] rsa::Error), + + #[error(transparent)] + Pkcs8(#[from] rsa::pkcs8::Error), + + #[error(transparent)] + Spki(#[from] rsa::pkcs8::spki::Error), + + #[error(transparent)] + Pkcs1(#[from] rsa::pkcs1::Error), - #[error("unable to encode JWT: `{0}`")] - JwtEncodingError(String), + #[error(transparent)] + Utf8(#[from] std::string::FromUtf8Error), + + #[error(transparent)] + Der(#[from] rsa::pkcs1::der::Error), + + #[error(transparent)] + JwtEncoding(#[from] jsonwebtoken::errors::Error), } #[derive(Debug, Serialize, Deserialize)] @@ -86,24 +100,27 @@ fn pubkey_fingerprint(pubkey: &[u8]) -> String { base64::engine::general_purpose::STANDARD.encode(hasher.finalize()) } -pub fn generate_jwt_token>( - private_key_pem: T, +pub fn generate_jwt_token( + private_key_pem: &str, // Snowflake expects uppercase . full_identifier: &str, ) -> Result { // Reading a private key: // rsa-2048.p8 -> public key -> der bytes -> hash - let privk = Rsa::private_key_from_pem(private_key_pem.as_ref())?; - let pubk = privk.public_key_to_der()?; - - let iss = format!("{}.SHA256:{}", full_identifier, pubkey_fingerprint(&pubk)); + let pkey = rsa::RsaPrivateKey::from_pkcs8_pem(private_key_pem)?; + let pubk = pkey.to_public_key().to_public_key_der()?; + let iss = format!( + "{}.SHA256:{}", + full_identifier, + pubkey_fingerprint(pubk.as_bytes()) + ); let iat = OffsetDateTime::now_utc(); let exp = iat + Duration::days(1); let claims = Claims::new(iss, full_identifier.to_owned(), iat, exp); - let ek = EncodingKey::from_rsa_der(&privk.private_key_to_der()?); + let ek = EncodingKey::from_rsa_der(pkey.to_pkcs1_der()?.as_bytes()); - encode(&Header::new(Algorithm::RS256), &claims, &ek) - .map_err(|e| JwtEncodingError(e.to_string())) + let res = encode(&Header::new(Algorithm::RS256), &claims, &ek)?; + Ok(res) }