mirror of
https://github.com/BitskiCo/jwk-rs
synced 2024-11-21 19:49:20 +00:00
Use stable Rust
This commit is contained in:
parent
8014d18bf0
commit
9592cad01c
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
@ -41,7 +41,7 @@ jobs:
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly
|
||||
toolchain: stable
|
||||
override: true
|
||||
|
||||
- name: Build (release)
|
||||
@ -58,7 +58,7 @@ jobs:
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly
|
||||
toolchain: stable
|
||||
override: true
|
||||
|
||||
- uses: actions-rs/tarpaulin@v0.1
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "jsonwebkey"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
authors = ["Nick Hynes <nhynes@nhynes.com>"]
|
||||
description = "JSON Web Key (JWK) (de)serialization, generation, and conversion."
|
||||
readme = "README.md"
|
||||
@ -12,6 +12,7 @@ edition = "2018"
|
||||
base64 = "0.12"
|
||||
bitflags = "1.2"
|
||||
derive_more = "0.99"
|
||||
generic-array = "0.14"
|
||||
jsonwebtoken = { version = "7.2", optional = true }
|
||||
num-bigint = { version = "0.2", optional = true }
|
||||
p256 = { version = "0.3", optional = true }
|
||||
@ -30,3 +31,6 @@ generate = ["p256", "rand"]
|
||||
|
||||
[dev-dependencies]
|
||||
jsonwebtoken = "7.2"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
*[JSON Web Key (JWK)](https://tools.ietf.org/html/rfc7517#section-4.3) (de)serialization, generation, and conversion.*
|
||||
|
||||
Note: requires rustc nightly >= 1.45 for conveniences around fixed-size arrays.
|
||||
|
||||
**Goals**
|
||||
|
||||
tl;dr: get keys into a format that can be used by other crates; be as safe as possible while doing so.
|
||||
|
@ -1,61 +1,55 @@
|
||||
use std::{array::FixedSizeArray, fmt};
|
||||
|
||||
use derive_more::{AsRef, Deref, From};
|
||||
use serde::{
|
||||
de::{self, Deserialize, Deserializer},
|
||||
ser::{Serialize, Serializer},
|
||||
};
|
||||
use derive_more::{AsRef, Deref};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use serde::de::{self, Deserialize, Deserializer};
|
||||
use zeroize::{Zeroize, Zeroizing};
|
||||
|
||||
use crate::utils::{deserialize_base64, serialize_base64};
|
||||
|
||||
/// A zeroizing-on-drop container for a `[u8; N]` that deserializes from base64.
|
||||
#[derive(Clone, Zeroize, Deref, AsRef, From)]
|
||||
#[zeroize(drop)]
|
||||
pub struct ByteArray<const N: usize>(pub [u8; N]);
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deref, AsRef)]
|
||||
#[serde(transparent)]
|
||||
pub struct ByteArray<N: ArrayLength<u8>>(
|
||||
#[serde(serialize_with = "crate::utils::serde_base64::serialize")] pub GenericArray<u8, N>,
|
||||
);
|
||||
|
||||
impl<const N: usize> fmt::Debug for ByteArray<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if cfg!(debug_assertions) {
|
||||
write!(f, "{}", base64::encode(self.0.as_slice()))
|
||||
} else {
|
||||
write!(f, "ByteArray<{}>", N)
|
||||
}
|
||||
impl<N: ArrayLength<u8>, T: Into<GenericArray<u8, N>>> From<T> for ByteArray<N> {
|
||||
fn from(arr: T) -> Self {
|
||||
Self(arr.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> PartialEq for ByteArray<N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.as_slice() == other.0.as_slice()
|
||||
impl<N: ArrayLength<u8>> Drop for ByteArray<N> {
|
||||
fn drop(&mut self) {
|
||||
Zeroize::zeroize(self.0.as_mut_slice())
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Eq for ByteArray<N> {}
|
||||
impl<N: ArrayLength<u8>> ByteArray<N> {
|
||||
/// An unwrapping version of `try_from_slice`.
|
||||
pub fn from_slice(bytes: impl AsRef<[u8]>) -> Self {
|
||||
Self::try_from_slice(bytes).unwrap()
|
||||
}
|
||||
|
||||
impl<const N: usize> ByteArray<N> {
|
||||
pub fn try_from_slice(bytes: impl AsRef<[u8]>) -> Result<Self, String> {
|
||||
let mut arr = Self([0u8; N]);
|
||||
let bytes = bytes.as_ref();
|
||||
if bytes.len() != N {
|
||||
Err(format!("expected {} bytes but got {}", N, bytes.len()))
|
||||
if bytes.len() != N::USIZE {
|
||||
Err(format!(
|
||||
"expected {} bytes but got {}",
|
||||
N::USIZE,
|
||||
bytes.len()
|
||||
))
|
||||
} else {
|
||||
arr.0.copy_from_slice(bytes);
|
||||
Ok(arr)
|
||||
Ok(Self(GenericArray::clone_from_slice(bytes)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Serialize for ByteArray<N> {
|
||||
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||
serialize_base64(self.0.as_slice(), s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, const N: usize> Deserialize<'de> for ByteArray<N> {
|
||||
impl<'de, N: ArrayLength<u8>> Deserialize<'de> for ByteArray<N> {
|
||||
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||
let bytes = Zeroizing::new(deserialize_base64(d)?);
|
||||
let bytes = Zeroizing::new(crate::utils::serde_base64::deserialize(d)?);
|
||||
Self::try_from_slice(&*bytes).map_err(|_| {
|
||||
de::Error::invalid_length(bytes.len(), &format!("{} base64-encoded bytes", N).as_str())
|
||||
de::Error::invalid_length(
|
||||
bytes.len(),
|
||||
&format!("{} base64-encoded bytes", N::USIZE).as_str(),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -64,6 +58,8 @@ impl<'de, const N: usize> Deserialize<'de> for ByteArray<N> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use generic_array::typenum::*;
|
||||
|
||||
static BYTES: &[u8] = &[1, 2, 3, 4, 5, 6, 7];
|
||||
static BASE64_JSON: &str = "\"AQIDBAUGBw==\"";
|
||||
|
||||
@ -73,26 +69,26 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_serde_byte_array_good() {
|
||||
let arr = ByteArray::<7>::try_from_slice(BYTES).unwrap();
|
||||
let arr = ByteArray::<U7>::try_from_slice(BYTES).unwrap();
|
||||
let b64 = serde_json::to_string(&arr).unwrap();
|
||||
assert_eq!(b64, BASE64_JSON);
|
||||
let bytes: ByteArray<7> = serde_json::from_str(&b64).unwrap();
|
||||
assert_eq!(bytes.as_ref(), BYTES);
|
||||
let bytes: ByteArray<U7> = serde_json::from_str(&b64).unwrap();
|
||||
assert_eq!(bytes.as_slice(), BYTES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_deserialize_byte_array_invalid() {
|
||||
let mut de = serde_json::Deserializer::from_str("\"Z\"");
|
||||
ByteArray::<0>::deserialize(&mut de).unwrap_err();
|
||||
ByteArray::<U0>::deserialize(&mut de).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_base64_deserialize_array_long() {
|
||||
ByteArray::<6>::deserialize(&mut get_de()).unwrap_err();
|
||||
ByteArray::<U6>::deserialize(&mut get_de()).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_base64_deserialize_array_short() {
|
||||
ByteArray::<8>::deserialize(&mut get_de()).unwrap_err();
|
||||
ByteArray::<U8>::deserialize(&mut get_de()).unwrap_err();
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,13 @@
|
||||
use std::fmt;
|
||||
|
||||
use derive_more::{AsRef, Deref, From};
|
||||
use serde::{
|
||||
de::{Deserialize, Deserializer},
|
||||
ser::{Serialize, Serializer},
|
||||
};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use crate::utils::{deserialize_base64, serialize_base64};
|
||||
|
||||
/// A zeroizing-on-drop container for a `Vec<u8>` that deserializes from base64.
|
||||
#[derive(Clone, PartialEq, Eq, Zeroize, Deref, AsRef, From)]
|
||||
#[derive(Clone, PartialEq, Eq, Zeroize, Serialize, Deserialize, Deref, AsRef, From)]
|
||||
#[zeroize(drop)]
|
||||
pub struct ByteVec(pub Vec<u8>);
|
||||
#[serde(transparent)]
|
||||
pub struct ByteVec(#[serde(with = "crate::utils::serde_base64")] pub Vec<u8>);
|
||||
|
||||
impl fmt::Debug for ByteVec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@ -24,18 +19,6 @@ impl fmt::Debug for ByteVec {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ByteVec {
|
||||
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||
serialize_base64(&self.0, s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ByteVec {
|
||||
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||
Ok(Self(deserialize_base64(d)?))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
36
src/lib.rs
36
src/lib.rs
@ -1,5 +1,5 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(box_syntax, const_generics, fixed_size_array)]
|
||||
#![deny(rust_2018_idioms, unreachable_pub)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
//! *[JSON Web Key (JWK)](https://tools.ietf.org/html/rfc7517#section-4.3) (de)serialization, generation, and conversion.*
|
||||
//!
|
||||
@ -58,6 +58,9 @@
|
||||
//! 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.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
mod byte_array;
|
||||
mod byte_vec;
|
||||
mod key_ops;
|
||||
@ -67,6 +70,7 @@ mod utils;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use generic_array::typenum::U32;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub use byte_array::ByteArray;
|
||||
@ -94,7 +98,7 @@ pub struct JsonWebKey {
|
||||
impl JsonWebKey {
|
||||
pub fn new(key: Key) -> Self {
|
||||
Self {
|
||||
key: box key,
|
||||
key: Box::new(key),
|
||||
key_use: None,
|
||||
key_ops: KeyOps::empty(),
|
||||
key_id: None,
|
||||
@ -143,7 +147,7 @@ impl std::str::FromStr for JsonWebKey {
|
||||
}
|
||||
|
||||
impl std::fmt::Display for JsonWebKey {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if f.alternate() {
|
||||
write!(f, "{}", serde_json::to_string_pretty(self).unwrap())
|
||||
} else {
|
||||
@ -179,7 +183,7 @@ pub enum Key {
|
||||
impl Key {
|
||||
/// Returns true iff this key only contains private components (i.e. a private asymmetric
|
||||
/// key or a symmetric key).
|
||||
fn is_private(&self) -> bool {
|
||||
pub fn is_private(&self) -> bool {
|
||||
match self {
|
||||
Self::Symmetric { .. }
|
||||
| Self::EC {
|
||||
@ -194,7 +198,7 @@ impl Key {
|
||||
}
|
||||
|
||||
/// Returns the public part of this key (symmetric keys have no public parts).
|
||||
pub fn to_public(&self) -> Option<Cow<Self>> {
|
||||
pub fn to_public(&self) -> Option<Cow<'_, Self>> {
|
||||
if !self.is_private() {
|
||||
return Some(Cow::Borrowed(self));
|
||||
}
|
||||
@ -236,7 +240,7 @@ impl Key {
|
||||
let prime256v1_oid = ObjectIdentifier::from_slice(&[1, 2, 840, 10045, 3, 1, 7]);
|
||||
let oids = &[Some(&ec_public_oid), Some(&prime256v1_oid)];
|
||||
|
||||
let write_public = |writer: DERWriter| {
|
||||
let write_public = |writer: DERWriter<'_>| {
|
||||
let public_bytes: Vec<u8> = [0x04 /* uncompressed */]
|
||||
.iter()
|
||||
.chain(x.iter())
|
||||
@ -248,7 +252,7 @@ impl Key {
|
||||
|
||||
match d {
|
||||
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_bytes(&**private_point);
|
||||
// The following tagged value is optional. OpenSSL produces it,
|
||||
@ -268,17 +272,17 @@ impl Key {
|
||||
1, 2, 840, 113549, 1, 1, 1, // rsaEncryption
|
||||
]);
|
||||
let oids = &[Some(&rsa_encryption_oid), None];
|
||||
let write_bytevec = |writer: DERWriter, vec: &ByteVec| {
|
||||
let write_bytevec = |writer: DERWriter<'_>, vec: &ByteVec| {
|
||||
let bigint = BigUint::from_bytes_be(vec.as_slice());
|
||||
writer.write_biguint(&bigint);
|
||||
};
|
||||
|
||||
let write_public = |writer: &mut DERWriterSeq| {
|
||||
let write_public = |writer: &mut DERWriterSeq<'_>| {
|
||||
write_bytevec(writer.next(), &public.n);
|
||||
writer.next().write_u32(PUBLIC_EXPONENT);
|
||||
};
|
||||
|
||||
let write_private = |writer: &mut DERWriterSeq, private: &RsaPrivate| {
|
||||
let write_private = |writer: &mut DERWriterSeq<'_>, private: &RsaPrivate| {
|
||||
// https://tools.ietf.org/html/rfc3447#appendix-A.1.2
|
||||
writer.next().write_i8(0); // version (two-prime)
|
||||
write_public(writer);
|
||||
@ -389,8 +393,8 @@ impl Key {
|
||||
Self::EC {
|
||||
curve: Curve::P256 {
|
||||
d: Some(sk_scalar.to_bytes().into()),
|
||||
x: ByteArray::try_from_slice(x_bytes).unwrap(),
|
||||
y: ByteArray::try_from_slice(y_bytes).unwrap(),
|
||||
x: ByteArray::from_slice(x_bytes),
|
||||
y: ByteArray::from_slice(y_bytes),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -404,11 +408,11 @@ pub enum Curve {
|
||||
P256 {
|
||||
/// The private scalar.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
d: Option<ByteArray<32>>,
|
||||
d: Option<ByteArray<U32>>,
|
||||
/// The curve point x coordinate.
|
||||
x: ByteArray<32>,
|
||||
x: ByteArray<U32>,
|
||||
/// The curve point y coordinate.
|
||||
y: ByteArray<32>,
|
||||
y: ByteArray<U32>,
|
||||
},
|
||||
}
|
||||
|
||||
|
53
src/tests.rs
53
src/tests.rs
@ -2,6 +2,8 @@ use super::*;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::byte_array::ByteArray;
|
||||
|
||||
// Generated using https://mkjwk.org
|
||||
static P256_JWK_FIXTURE: &str = r#"{
|
||||
"kty": "EC",
|
||||
@ -40,29 +42,24 @@ fn deserialize_es256() {
|
||||
assert_eq!(
|
||||
jwk,
|
||||
JsonWebKey {
|
||||
key: box Key::EC {
|
||||
key: Box::new(Key::EC {
|
||||
// The parameters were decoded using a 10-liner Rust script.
|
||||
curve: Curve::P256 {
|
||||
d: Some(
|
||||
[
|
||||
102, 130, 144, 246, 62, 29, 132, 128, 101, 49, 21, 107, 191, 228, 6,
|
||||
240, 255, 211, 246, 203, 173, 191, 127, 253, 229, 232, 168, 244, 203,
|
||||
105, 128, 168
|
||||
]
|
||||
.into()
|
||||
),
|
||||
x: [
|
||||
d: Some(ByteArray::from_slice(&[
|
||||
102, 130, 144, 246, 62, 29, 132, 128, 101, 49, 21, 107, 191, 228, 6, 240,
|
||||
255, 211, 246, 203, 173, 191, 127, 253, 229, 232, 168, 244, 203, 105, 128,
|
||||
168
|
||||
])),
|
||||
x: ByteArray::from_slice(&[
|
||||
64, 227, 7, 154, 255, 122, 181, 89, 73, 191, 235, 141, 170, 154, 231, 13,
|
||||
34, 136, 143, 144, 34, 45, 53, 202, 70, 137, 151, 98, 118, 175, 208, 221
|
||||
]
|
||||
.into(),
|
||||
y: [
|
||||
]),
|
||||
y: ByteArray::from_slice(&[
|
||||
78, 54, 25, 160, 121, 220, 181, 171, 68, 19, 163, 66, 172, 169, 151, 65,
|
||||
210, 73, 62, 115, 115, 100, 69, 252, 156, 25, 153, 117, 237, 192, 99, 137
|
||||
]
|
||||
.into(),
|
||||
},
|
||||
])
|
||||
},
|
||||
}),
|
||||
algorithm: Some(Algorithm::ES256),
|
||||
key_id: Some("a key".into()),
|
||||
key_ops: KeyOps::empty(),
|
||||
@ -74,13 +71,13 @@ fn deserialize_es256() {
|
||||
#[test]
|
||||
fn serialize_es256() {
|
||||
let jwk = JsonWebKey {
|
||||
key: box Key::EC {
|
||||
key: Box::new(Key::EC {
|
||||
curve: Curve::P256 {
|
||||
d: None,
|
||||
x: [1u8; 32].into(),
|
||||
y: [2u8; 32].into(),
|
||||
},
|
||||
x: ByteArray::from_slice(&[1u8; 32]),
|
||||
y: ByteArray::from_slice(&[2u8; 32]),
|
||||
},
|
||||
}),
|
||||
key_id: None,
|
||||
algorithm: None,
|
||||
key_ops: KeyOps::empty(),
|
||||
@ -130,10 +127,10 @@ fn deserialize_hs256() {
|
||||
assert_eq!(
|
||||
jwk,
|
||||
JsonWebKey {
|
||||
key: box Key::Symmetric {
|
||||
key: Box::new(Key::Symmetric {
|
||||
// The parameters were decoded using a 10-liner Rust script.
|
||||
key: vec![180, 3, 141, 233].into(),
|
||||
},
|
||||
}),
|
||||
algorithm: Some(Algorithm::HS256),
|
||||
key_id: None,
|
||||
key_ops: KeyOps::SIGN | KeyOps::VERIFY,
|
||||
@ -145,9 +142,9 @@ fn deserialize_hs256() {
|
||||
#[test]
|
||||
fn serialize_hs256() {
|
||||
let jwk = JsonWebKey {
|
||||
key: box Key::Symmetric {
|
||||
key: Box::new(Key::Symmetric {
|
||||
key: vec![42; 16].into(),
|
||||
},
|
||||
}),
|
||||
key_id: None,
|
||||
algorithm: None,
|
||||
key_ops: KeyOps::empty(),
|
||||
@ -165,7 +162,7 @@ fn deserialize_rs256() {
|
||||
assert_eq!(
|
||||
jwk,
|
||||
JsonWebKey {
|
||||
key: box Key::RSA {
|
||||
key: Box::new(Key::RSA {
|
||||
public: RsaPublic {
|
||||
e: PublicExponent,
|
||||
n: vec![
|
||||
@ -223,7 +220,7 @@ fn deserialize_rs256() {
|
||||
.into()
|
||||
)
|
||||
})
|
||||
},
|
||||
}),
|
||||
algorithm: None,
|
||||
key_id: None,
|
||||
key_ops: KeyOps::WRAP_KEY,
|
||||
@ -235,7 +232,7 @@ fn deserialize_rs256() {
|
||||
#[test]
|
||||
fn serialize_rs256() {
|
||||
let jwk = JsonWebKey {
|
||||
key: box Key::RSA {
|
||||
key: Box::new(Key::RSA {
|
||||
public: RsaPublic {
|
||||
e: PublicExponent,
|
||||
n: vec![105, 183, 62].into(),
|
||||
@ -248,7 +245,7 @@ fn serialize_rs256() {
|
||||
dq: None,
|
||||
qi: None,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
key_id: None,
|
||||
algorithm: None,
|
||||
key_ops: KeyOps::empty(),
|
||||
|
23
src/utils.rs
23
src/utils.rs
@ -16,11 +16,17 @@ fn base64_decode(b64: impl AsRef<[u8]>) -> Result<Vec<u8>, base64::DecodeError>
|
||||
base64::decode_config(b64, base64_config())
|
||||
}
|
||||
|
||||
pub fn serialize_base64<S: Serializer>(bytes: impl AsRef<[u8]>, s: S) -> Result<S::Ok, S::Error> {
|
||||
pub(crate) mod serde_base64 {
|
||||
use super::*;
|
||||
|
||||
pub(crate) fn serialize<S: Serializer>(
|
||||
bytes: impl AsRef<[u8]>,
|
||||
s: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
base64_encode(bytes).serialize(s)
|
||||
}
|
||||
|
||||
pub fn deserialize_base64<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
|
||||
pub(crate) fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
|
||||
let base64_str = Zeroizing::new(String::deserialize(d)?);
|
||||
base64_decode(&*base64_str).map_err(|e| {
|
||||
#[cfg(debug_assertions)]
|
||||
@ -30,15 +36,16 @@ pub fn deserialize_base64<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D:
|
||||
de::Error::custom(err_msg.strip_suffix(".").unwrap_or(&err_msg))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "pkcs-convert")]
|
||||
pub mod pkcs8 {
|
||||
pub(crate) mod pkcs8 {
|
||||
use yasna::{
|
||||
models::{ObjectIdentifier, TaggedDerValue},
|
||||
DERWriter, DERWriterSeq,
|
||||
};
|
||||
|
||||
fn write_oids(writer: &mut DERWriterSeq, oids: &[Option<&ObjectIdentifier>]) {
|
||||
fn write_oids(writer: &mut DERWriterSeq<'_>, oids: &[Option<&ObjectIdentifier>]) {
|
||||
for oid in oids {
|
||||
match oid {
|
||||
Some(oid) => writer.next().write_oid(oid),
|
||||
@ -47,9 +54,9 @@ pub mod pkcs8 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_private(
|
||||
pub(crate) fn write_private(
|
||||
oids: &[Option<&ObjectIdentifier>],
|
||||
body_writer: impl FnOnce(&mut DERWriterSeq),
|
||||
body_writer: impl FnOnce(&mut DERWriterSeq<'_>),
|
||||
) -> Vec<u8> {
|
||||
yasna::construct_der(|writer| {
|
||||
writer.write_sequence(|writer| {
|
||||
@ -66,9 +73,9 @@ pub mod pkcs8 {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_public(
|
||||
pub(crate) fn write_public(
|
||||
oids: &[Option<&ObjectIdentifier>],
|
||||
body_writer: impl FnOnce(DERWriter),
|
||||
body_writer: impl FnOnce(DERWriter<'_>),
|
||||
) -> Vec<u8> {
|
||||
yasna::construct_der(|writer| {
|
||||
writer.write_sequence(|writer| {
|
||||
|
Loading…
Reference in New Issue
Block a user