mirror of
https://github.com/BitskiCo/jwk-rs
synced 2024-11-22 03:49:22 +00:00
Add jwt and panicking conversions
This commit is contained in:
parent
7a8536dabe
commit
72368980c4
@ -24,7 +24,8 @@ yasna = { version = "0.3", optional = true, features = ["num-bigint"] }
|
|||||||
zeroize = { version = "1.1", features = ["zeroize_derive"] }
|
zeroize = { version = "1.1", features = ["zeroize_derive"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
convert = ["num-bigint", "yasna"]
|
pkcs-convert = ["num-bigint", "yasna"]
|
||||||
|
jwt-convert = ["pkcs-convert", "jsonwebtoken"]
|
||||||
generate = ["p256", "rand"]
|
generate = ["p256", "rand"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
27
README.md
27
README.md
@ -34,13 +34,16 @@ let jwt_str = r#"{
|
|||||||
"k": "Wpj30SfkzM_m0Sa_B2NqNw",
|
"k": "Wpj30SfkzM_m0Sa_B2NqNw",
|
||||||
"alg": "HS256"
|
"alg": "HS256"
|
||||||
}"#;
|
}"#;
|
||||||
let jwk: jwk::JsonWebKey = jwt_str.parse().unwrap();
|
let the_jwk: jwk::JsonWebKey = jwt_str.parse().unwrap();
|
||||||
println!("{:#?}", jwk); // looks like `jwt_str` but with reordered fields.
|
println!("{:#?}", the_jwk); // looks like `jwt_str` but with reordered fields.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using with other crates
|
### Using with other crates
|
||||||
|
|
||||||
|
*Note:* The following example requires the `jwt-convert` feature.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
#[cfg(all(feature = "generate", feature = "jwt-convert"))] {
|
||||||
extern crate jsonwebtoken as jwt;
|
extern crate jsonwebtoken as jwt;
|
||||||
extern crate jsonwebkey as jwk;
|
extern crate jsonwebkey as jwk;
|
||||||
|
|
||||||
@ -50,24 +53,24 @@ struct TokenClaims {}
|
|||||||
let mut my_jwk = jwk::JsonWebKey::new(jwk::Key::generate_p256());
|
let mut my_jwk = jwk::JsonWebKey::new(jwk::Key::generate_p256());
|
||||||
my_jwk.set_algorithm(jwk::Algorithm::ES256);
|
my_jwk.set_algorithm(jwk::Algorithm::ES256);
|
||||||
|
|
||||||
let encoding_key = jwt::EncodingKey::from_ec_der(&my_jwk.key.to_der().unwrap());
|
let alg: jwt::Algorithm = my_jwk.algorithm.unwrap().into();
|
||||||
let token = jwt::encode(
|
let token = jwt::encode(
|
||||||
&jwt::Header::new(my_jwk.algorithm.unwrap().into()),
|
&jwt::Header::new(alg),
|
||||||
&TokenClaims {},
|
&TokenClaims {},
|
||||||
&encoding_key,
|
&my_jwk.key.to_encoding_key(),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
let public_pem = my_jwk.key.to_public().unwrap().to_pem().unwrap();
|
let mut validation = jwt::Validation::new(alg);
|
||||||
let decoding_key = jwt::DecodingKey::from_ec_pem(public_pem.as_bytes()).unwrap();
|
|
||||||
let mut validation = jwt::Validation::new(my_jwk.algorithm.unwrap().into());
|
|
||||||
validation.validate_exp = false;
|
validation.validate_exp = false;
|
||||||
jwt::decode::<TokenClaims>(&token, &decoding_key, &validation).unwrap();
|
jwt::decode::<TokenClaims>(&token, &my_jwk.key.to_decoding_key(), &validation).unwrap();
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* `convert` - enables `Key::{to_der, to_pem}`.
|
* `pkcs-convert` - enables `Key::{to_der, to_pem}`.
|
||||||
This pulls in the [yasna](https://crates.io/crates/yasna) crate.
|
This pulls in the [yasna](https://crates.io/crates/yasna) crate.
|
||||||
* `generate` - enables `Key::{generate_p256, generate_symmetric}`.
|
* `generate` - enables `Key::{generate_p256, generate_symmetric}`.
|
||||||
This pulls in the [p256](https://crates.io/crates/p256) and [rand](https://crates.io/crates/rand) crates.
|
This pulls in the [p256](https://crates.io/crates/p256) and [rand](https://crates.io/crates/rand) crates.
|
||||||
* `jsonwebtoken` - enables conversions to types in the [jsonwebtoken](https://crates.io/crates/jsonwebtoken) crate.
|
* `jwt-convert` - enables conversions to types in the
|
||||||
|
[jsonwebtoken](https://crates.io/crates/jsonwebtoken) crate.
|
||||||
|
132
src/lib.rs
132
src/lib.rs
@ -20,13 +20,14 @@
|
|||||||
//! "k": "Wpj30SfkzM_m0Sa_B2NqNw",
|
//! "k": "Wpj30SfkzM_m0Sa_B2NqNw",
|
||||||
//! "alg": "HS256"
|
//! "alg": "HS256"
|
||||||
//! }"#;
|
//! }"#;
|
||||||
//! let jwk: jwk::JsonWebKey = jwt_str.parse().unwrap();
|
//! let the_jwk: jwk::JsonWebKey = jwt_str.parse().unwrap();
|
||||||
//! println!("{:#?}", jwk); // looks like `jwt_str` but with reordered fields.
|
//! println!("{:#?}", the_jwk); // looks like `jwt_str` but with reordered fields.
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ### Using with other crates
|
//! ### Using with other crates
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
|
//! #[cfg(all(feature = "generate", feature = "jwt-convert"))] {
|
||||||
//! extern crate jsonwebtoken as jwt;
|
//! extern crate jsonwebtoken as jwt;
|
||||||
//! extern crate jsonwebkey as jwk;
|
//! extern crate jsonwebkey as jwk;
|
||||||
//!
|
//!
|
||||||
@ -36,18 +37,17 @@
|
|||||||
//! let mut my_jwk = jwk::JsonWebKey::new(jwk::Key::generate_p256());
|
//! let mut my_jwk = jwk::JsonWebKey::new(jwk::Key::generate_p256());
|
||||||
//! my_jwk.set_algorithm(jwk::Algorithm::ES256);
|
//! my_jwk.set_algorithm(jwk::Algorithm::ES256);
|
||||||
//!
|
//!
|
||||||
//! let encoding_key = jwt::EncodingKey::from_ec_der(&my_jwk.key.to_der().unwrap());
|
//! let alg: jwt::Algorithm = my_jwk.algorithm.unwrap().into();
|
||||||
//! let token = jwt::encode(
|
//! let token = jwt::encode(
|
||||||
//! &jwt::Header::new(my_jwk.algorithm.unwrap().into()),
|
//! &jwt::Header::new(alg),
|
||||||
//! &TokenClaims {},
|
//! &TokenClaims {},
|
||||||
//! &encoding_key,
|
//! &my_jwk.key.to_encoding_key(),
|
||||||
//! ).unwrap();
|
//! ).unwrap();
|
||||||
//!
|
//!
|
||||||
//! let public_pem = my_jwk.key.to_public().unwrap().to_pem().unwrap();
|
//! let mut validation = jwt::Validation::new(alg);
|
||||||
//! let decoding_key = jwt::DecodingKey::from_ec_pem(public_pem.as_bytes()).unwrap();
|
|
||||||
//! let mut validation = jwt::Validation::new(my_jwk.algorithm.unwrap().into());
|
|
||||||
//! validation.validate_exp = false;
|
//! validation.validate_exp = false;
|
||||||
//! jwt::decode::<TokenClaims>(&token, &decoding_key, &validation).unwrap();
|
//! jwt::decode::<TokenClaims>(&token, &my_jwk.key.to_decoding_key(), &validation).unwrap();
|
||||||
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Features
|
//! ## Features
|
||||||
@ -65,13 +65,15 @@ mod key_ops;
|
|||||||
mod tests;
|
mod tests;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub use byte_array::ByteArray;
|
pub use byte_array::ByteArray;
|
||||||
pub use byte_vec::ByteVec;
|
pub use byte_vec::ByteVec;
|
||||||
pub use key_ops::KeyOps;
|
pub use key_ops::KeyOps;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct JsonWebKey {
|
pub struct JsonWebKey {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub key: Box<Key>,
|
pub key: Box<Key>,
|
||||||
@ -196,12 +198,12 @@ impl Key {
|
|||||||
!self.is_private()
|
!self.is_private()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the public part of this key, if it's symmetric.
|
/// Returns the public part of this key (symmetric keys have no public parts).
|
||||||
pub fn to_public(&self) -> Option<Self> {
|
pub fn to_public(&self) -> Option<Cow<Self>> {
|
||||||
if self.is_public() {
|
if self.is_public() {
|
||||||
return Some(self.clone());
|
return Some(Cow::Borrowed(self));
|
||||||
}
|
}
|
||||||
Some(match self {
|
Some(Cow::Owned(match self {
|
||||||
Self::Symmetric { .. } => return None,
|
Self::Symmetric { .. } => return None,
|
||||||
Self::EC {
|
Self::EC {
|
||||||
curve: Curve::P256 { x, y, .. },
|
curve: Curve::P256 { x, y, .. },
|
||||||
@ -216,19 +218,19 @@ impl Key {
|
|||||||
public: public.clone(),
|
public: public.clone(),
|
||||||
private: None,
|
private: None,
|
||||||
},
|
},
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If this key is asymmetric, encodes it as PKCS#8.
|
/// If this key is asymmetric, encodes it as PKCS#8.
|
||||||
#[cfg(feature = "convert")]
|
#[cfg(feature = "pkcs-convert")]
|
||||||
pub fn to_der(&self) -> Result<Vec<u8>, PkcsConvertError> {
|
pub fn try_to_der(&self) -> Result<Vec<u8>, ConversionError> {
|
||||||
use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
use yasna::{models::ObjectIdentifier, DERWriter, DERWriterSeq, Tag};
|
use yasna::{models::ObjectIdentifier, DERWriter, DERWriterSeq, Tag};
|
||||||
|
|
||||||
use crate::utils::pkcs8;
|
use crate::utils::pkcs8;
|
||||||
|
|
||||||
if let Self::Symmetric { .. } = self {
|
if let Self::Symmetric { .. } = self {
|
||||||
return Err(PkcsConvertError::NotAsymmetric);
|
return Err(ConversionError::NotAsymmetric);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
@ -253,8 +255,7 @@ impl Key {
|
|||||||
Some(private_point) => {
|
Some(private_point) => {
|
||||||
pkcs8::write_private(oids, |writer: &mut DERWriterSeq| {
|
pkcs8::write_private(oids, |writer: &mut DERWriterSeq| {
|
||||||
writer.next().write_i8(1); // version
|
writer.next().write_i8(1); // version
|
||||||
use std::array::FixedSizeArray;
|
writer.next().write_bytes(&**private_point);
|
||||||
writer.next().write_bytes(private_point.as_slice());
|
|
||||||
// The following tagged value is optional. OpenSSL produces it,
|
// The following tagged value is optional. OpenSSL produces it,
|
||||||
// but many tools, including jwt.io and `jsonwebtoken`, don't like it,
|
// but many tools, including jwt.io and `jsonwebtoken`, don't like it,
|
||||||
// so we don't include it.
|
// so we don't include it.
|
||||||
@ -308,7 +309,7 @@ impl Key {
|
|||||||
qi: Some(_),
|
qi: Some(_),
|
||||||
},
|
},
|
||||||
) => pkcs8::write_private(oids, |writer| write_private(writer, private)),
|
) => pkcs8::write_private(oids, |writer| write_private(writer, private)),
|
||||||
Some(_) => return Err(PkcsConvertError::MissingRsaParams),
|
Some(_) => return Err(ConversionError::MissingRsaParams),
|
||||||
None => pkcs8::write_public(oids, |writer| {
|
None => pkcs8::write_public(oids, |writer| {
|
||||||
let body =
|
let body =
|
||||||
yasna::construct_der(|writer| writer.write_sequence(write_public));
|
yasna::construct_der(|writer| writer.write_sequence(write_public));
|
||||||
@ -320,11 +321,18 @@ impl Key {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unwrapping `try_to_der`.
|
||||||
|
/// Panics if the key is not asymmetric or there are missing RSA components.
|
||||||
|
#[cfg(feature = "pkcs-convert")]
|
||||||
|
pub fn to_der(&self) -> Vec<u8> {
|
||||||
|
self.try_to_der().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// If this key is asymmetric, encodes it as PKCS#8 with PEM armoring.
|
/// If this key is asymmetric, encodes it as PKCS#8 with PEM armoring.
|
||||||
#[cfg(feature = "convert")]
|
#[cfg(feature = "pkcs-convert")]
|
||||||
pub fn to_pem(&self) -> Result<String, PkcsConvertError> {
|
pub fn try_to_pem(&self) -> Result<String, ConversionError> {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let der_b64 = base64::encode(self.to_der()?);
|
let der_b64 = base64::encode(self.try_to_der()?);
|
||||||
let key_ty = if self.is_private() {
|
let key_ty = if self.is_private() {
|
||||||
"PRIVATE"
|
"PRIVATE"
|
||||||
} else {
|
} else {
|
||||||
@ -332,6 +340,7 @@ impl Key {
|
|||||||
};
|
};
|
||||||
let mut pem = String::new();
|
let mut pem = String::new();
|
||||||
writeln!(&mut pem, "-----BEGIN {} KEY-----", key_ty).unwrap();
|
writeln!(&mut pem, "-----BEGIN {} KEY-----", key_ty).unwrap();
|
||||||
|
//^ re: `unwrap`, if writing to a string fails, we've got bigger issues.
|
||||||
const MAX_LINE_LEN: usize = 64;
|
const MAX_LINE_LEN: usize = 64;
|
||||||
for i in (0..der_b64.len()).step_by(MAX_LINE_LEN) {
|
for i in (0..der_b64.len()).step_by(MAX_LINE_LEN) {
|
||||||
writeln!(
|
writeln!(
|
||||||
@ -345,6 +354,13 @@ impl Key {
|
|||||||
Ok(pem)
|
Ok(pem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unwrapping `try_to_pem`.
|
||||||
|
/// Panics if the key is not asymmetric or there are missing RSA components.
|
||||||
|
#[cfg(feature = "pkcs-convert")]
|
||||||
|
pub fn to_pem(&self) -> String {
|
||||||
|
self.try_to_pem().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Generates a new symmetric key with the specified number of bits.
|
/// Generates a new symmetric key with the specified number of bits.
|
||||||
/// Best used with one of the HS algorithms (e.g., HS256).
|
/// Best used with one of the HS algorithms (e.g., HS256).
|
||||||
#[cfg(feature = "generate")]
|
#[cfg(feature = "generate")]
|
||||||
@ -473,16 +489,62 @@ pub enum Algorithm {
|
|||||||
ES256,
|
ES256,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "jsonwebtoken"))]
|
#[cfg(feature = "jwt-convert")]
|
||||||
impl Into<jsonwebtoken::Algorithm> for Algorithm {
|
const _IMPL_JWT_CONVERSIONS: () = {
|
||||||
fn into(self) -> jsonwebtoken::Algorithm {
|
use jsonwebtoken as jwt;
|
||||||
match self {
|
|
||||||
Self::HS256 => jsonwebtoken::Algorithm::HS256,
|
impl Into<jwt::Algorithm> for Algorithm {
|
||||||
Self::ES256 => jsonwebtoken::Algorithm::ES256,
|
fn into(self) -> jsonwebtoken::Algorithm {
|
||||||
Self::RS256 => jsonwebtoken::Algorithm::RS256,
|
match self {
|
||||||
|
Self::HS256 => jwt::Algorithm::HS256,
|
||||||
|
Self::ES256 => jwt::Algorithm::ES256,
|
||||||
|
Self::RS256 => jwt::Algorithm::RS256,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
impl Key {
|
||||||
|
/// Returns an `EncodingKey` if the key is private.
|
||||||
|
pub fn try_to_encoding_key(&self) -> Result<jwt::EncodingKey, ConversionError> {
|
||||||
|
if self.is_public() {
|
||||||
|
return Err(ConversionError::NotPrivate);
|
||||||
|
}
|
||||||
|
Ok(match self {
|
||||||
|
Self::Symmetric { key } => jwt::EncodingKey::from_secret(key),
|
||||||
|
// The following two conversion will not panic, as we've ensured that the keys
|
||||||
|
// are private and tested that the successful output of `try_to_pem` is valid.
|
||||||
|
Self::EC { .. } => {
|
||||||
|
jwt::EncodingKey::from_ec_pem(self.try_to_pem()?.as_bytes()).unwrap()
|
||||||
|
}
|
||||||
|
Self::RSA { .. } => {
|
||||||
|
jwt::EncodingKey::from_rsa_pem(self.try_to_pem()?.as_bytes()).unwrap()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unwrapping `try_to_encoding_key`. Panics if the key is public.
|
||||||
|
pub fn to_encoding_key(&self) -> jwt::EncodingKey {
|
||||||
|
self.try_to_encoding_key().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_decoding_key(&self) -> jwt::DecodingKey<'static> {
|
||||||
|
match self {
|
||||||
|
Self::Symmetric { key } => jwt::DecodingKey::from_secret(key).into_static(),
|
||||||
|
Self::EC { .. } => {
|
||||||
|
// The following will not panic: all EC JWKs have public components due to
|
||||||
|
// typing. PEM conversion will always succeed, for the same reason.
|
||||||
|
// Hence, jwt::DecodingKey shall have no issue with de-converting.
|
||||||
|
jwt::DecodingKey::from_ec_pem(self.to_public().unwrap().to_pem().as_bytes())
|
||||||
|
.unwrap()
|
||||||
|
.into_static()
|
||||||
|
}
|
||||||
|
Self::RSA { .. } => jwt::DecodingKey::from_rsa_pem(self.to_pem().as_bytes())
|
||||||
|
.unwrap()
|
||||||
|
.into_static(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -497,10 +559,14 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum PkcsConvertError {
|
pub enum ConversionError {
|
||||||
#[error("encoding RSA JWK as PKCS#8 requires specifing all of p, q, dp, dq, qi")]
|
#[error("encoding RSA JWK as PKCS#8 requires specifing all of p, q, dp, dq, qi")]
|
||||||
MissingRsaParams,
|
MissingRsaParams,
|
||||||
|
|
||||||
#[error("a symmetric key can not be encoded using PKCS#8")]
|
#[error("a symmetric key can not be encoded using PKCS#8")]
|
||||||
NotAsymmetric,
|
NotAsymmetric,
|
||||||
|
|
||||||
|
#[cfg(feature = "jwt-convert")]
|
||||||
|
#[error("a public key cannot be converted to a `jsonwebtoken::EncodingKey`")]
|
||||||
|
NotPrivate,
|
||||||
}
|
}
|
||||||
|
22
src/tests.rs
22
src/tests.rs
@ -86,7 +86,7 @@ fn serialize_es256() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "generate")]
|
#[cfg(all(feature = "jwt-convert", feature = "generate"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn generate_p256() {
|
fn generate_p256() {
|
||||||
extern crate jsonwebtoken as jwt;
|
extern crate jsonwebtoken as jwt;
|
||||||
@ -97,7 +97,7 @@ fn generate_p256() {
|
|||||||
let mut the_jwk = JsonWebKey::new(Key::generate_p256());
|
let mut the_jwk = JsonWebKey::new(Key::generate_p256());
|
||||||
the_jwk.set_algorithm(Algorithm::ES256).unwrap();
|
the_jwk.set_algorithm(Algorithm::ES256).unwrap();
|
||||||
|
|
||||||
let encoding_key = jwt::EncodingKey::from_ec_der(&the_jwk.key.to_der().unwrap());
|
let encoding_key = jwt::EncodingKey::from_ec_der(&the_jwk.key.to_der());
|
||||||
let token = jwt::encode(
|
let token = jwt::encode(
|
||||||
&jwt::Header::new(the_jwk.algorithm.unwrap().into()),
|
&jwt::Header::new(the_jwk.algorithm.unwrap().into()),
|
||||||
&TokenClaims {},
|
&TokenClaims {},
|
||||||
@ -107,7 +107,7 @@ fn generate_p256() {
|
|||||||
|
|
||||||
let mut validation = jwt::Validation::new(the_jwk.algorithm.unwrap().into());
|
let mut validation = jwt::Validation::new(the_jwk.algorithm.unwrap().into());
|
||||||
validation.validate_exp = false;
|
validation.validate_exp = false;
|
||||||
let public_pem = the_jwk.key.to_public().unwrap().to_pem().unwrap();
|
let public_pem = the_jwk.key.to_public().unwrap().to_pem();
|
||||||
let decoding_key = jwt::DecodingKey::from_ec_pem(public_pem.as_bytes()).unwrap();
|
let decoding_key = jwt::DecodingKey::from_ec_pem(public_pem.as_bytes()).unwrap();
|
||||||
jwt::decode::<TokenClaims>(&token, &decoding_key, &validation).unwrap();
|
jwt::decode::<TokenClaims>(&token, &decoding_key, &validation).unwrap();
|
||||||
}
|
}
|
||||||
@ -290,14 +290,14 @@ fn mismatched_algorithm() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "convert")]
|
#[cfg(feature = "pkcs-convert")]
|
||||||
#[test]
|
#[test]
|
||||||
fn p256_private_to_pem() {
|
fn p256_private_to_pem() {
|
||||||
// generated using mkjwk, converted using node-jwk-to-pem, verified using openssl
|
// generated using mkjwk, converted using node-jwk-to-pem, verified using openssl
|
||||||
let jwk = JsonWebKey::from_str(P256_JWK_FIXTURE).unwrap();
|
let jwk = JsonWebKey::from_str(P256_JWK_FIXTURE).unwrap();
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
jwk.key.to_pem().unwrap(),
|
jwk.key.to_pem(),
|
||||||
"-----BEGIN PRIVATE KEY-----
|
"-----BEGIN PRIVATE KEY-----
|
||||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgZoKQ9j4dhIBlMRVr
|
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgZoKQ9j4dhIBlMRVr
|
||||||
v+QG8P/T9sutv3/95eio9MtpgKihRANCAARA4wea/3q1WUm/642qmucNIoiPkCIt
|
v+QG8P/T9sutv3/95eio9MtpgKihRANCAARA4wea/3q1WUm/642qmucNIoiPkCIt
|
||||||
@ -307,13 +307,13 @@ NcpGiZdidq/Q3U42GaB53LWrRBOjQqypl0HSST5zc2RF/JwZmXXtwGOJ
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "convert")]
|
#[cfg(feature = "pkcs-convert")]
|
||||||
#[test]
|
#[test]
|
||||||
fn p256_public_to_pem() {
|
fn p256_public_to_pem() {
|
||||||
let jwk = JsonWebKey::from_str(P256_JWK_FIXTURE).unwrap();
|
let jwk = JsonWebKey::from_str(P256_JWK_FIXTURE).unwrap();
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
jwk.key.to_public().unwrap().to_pem().unwrap(),
|
jwk.key.to_public().unwrap().to_pem(),
|
||||||
"-----BEGIN PUBLIC KEY-----
|
"-----BEGIN PUBLIC KEY-----
|
||||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQOMHmv96tVlJv+uNqprnDSKIj5Ai
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQOMHmv96tVlJv+uNqprnDSKIj5Ai
|
||||||
LTXKRomXYnav0N1ONhmgedy1q0QTo0KsqZdB0kk+c3NkRfycGZl17cBjiQ==
|
LTXKRomXYnav0N1ONhmgedy1q0QTo0KsqZdB0kk+c3NkRfycGZl17cBjiQ==
|
||||||
@ -322,13 +322,13 @@ LTXKRomXYnav0N1ONhmgedy1q0QTo0KsqZdB0kk+c3NkRfycGZl17cBjiQ==
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "convert")]
|
#[cfg(feature = "pkcs-convert")]
|
||||||
#[test]
|
#[test]
|
||||||
fn rsa_private_to_pem() {
|
fn rsa_private_to_pem() {
|
||||||
let jwk = JsonWebKey::from_str(RSA_JWK_FIXTURE).unwrap();
|
let jwk = JsonWebKey::from_str(RSA_JWK_FIXTURE).unwrap();
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
jwk.key.to_pem().unwrap(),
|
jwk.key.to_pem(),
|
||||||
"-----BEGIN PRIVATE KEY-----
|
"-----BEGIN PRIVATE KEY-----
|
||||||
MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApCzbcd9kjvg5rfGH
|
MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApCzbcd9kjvg5rfGH
|
||||||
dEMWnXo49zbB6FLQ+m0B0BvVp0aojVWYa0xujC+ZP7ZhxByPxyc2PazwFJJi9ivZ
|
dEMWnXo49zbB6FLQ+m0B0BvVp0aojVWYa0xujC+ZP7ZhxByPxyc2PazwFJJi9ivZ
|
||||||
@ -343,13 +343,13 @@ J2lmylxUG0M=
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "convert")]
|
#[cfg(feature = "pkcs-convert")]
|
||||||
#[test]
|
#[test]
|
||||||
fn rsa_public_to_pem() {
|
fn rsa_public_to_pem() {
|
||||||
let jwk = JsonWebKey::from_str(RSA_JWK_FIXTURE).unwrap();
|
let jwk = JsonWebKey::from_str(RSA_JWK_FIXTURE).unwrap();
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
jwk.key.to_public().unwrap().to_pem().unwrap(),
|
jwk.key.to_public().unwrap().to_pem(),
|
||||||
"-----BEGIN PUBLIC KEY-----
|
"-----BEGIN PUBLIC KEY-----
|
||||||
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKQs23HfZI74Oa3xh3RDFp16OPc2wehS
|
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKQs23HfZI74Oa3xh3RDFp16OPc2wehS
|
||||||
0PptAdAb1adGqI1VmGtMbowvmT+2YcQcj8cnNj2s8BSSYvYr2f4IEcMCAwEAAQ==
|
0PptAdAb1adGqI1VmGtMbowvmT+2YcQcj8cnNj2s8BSSYvYr2f4IEcMCAwEAAQ==
|
||||||
|
@ -31,7 +31,7 @@ pub fn deserialize_base64<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "convert")]
|
#[cfg(feature = "pkcs-convert")]
|
||||||
pub mod pkcs8 {
|
pub mod pkcs8 {
|
||||||
use yasna::{
|
use yasna::{
|
||||||
models::{ObjectIdentifier, TaggedDerValue},
|
models::{ObjectIdentifier, TaggedDerValue},
|
||||||
|
Loading…
Reference in New Issue
Block a user