Create inline module for crypto primitives
This commit is contained in:
parent
3679fc3eb2
commit
e0ac09439e
68
src/lib.rs
68
src/lib.rs
|
@ -8,11 +8,6 @@ use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[cfg(feature = "aws-lc-rs")]
|
|
||||||
pub(crate) use aws_lc_rs as ring_like;
|
|
||||||
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
|
|
||||||
pub(crate) use ring as ring_like;
|
|
||||||
|
|
||||||
use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
|
use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
|
||||||
use http_body_util::{BodyExt, Full};
|
use http_body_util::{BodyExt, Full};
|
||||||
use hyper::body::{Bytes, Incoming};
|
use hyper::body::{Bytes, Incoming};
|
||||||
|
@ -22,10 +17,6 @@ use hyper_util::client::legacy::connect::Connect;
|
||||||
use hyper_util::client::legacy::Client as HyperClient;
|
use hyper_util::client::legacy::Client as HyperClient;
|
||||||
#[cfg(feature = "hyper-rustls")]
|
#[cfg(feature = "hyper-rustls")]
|
||||||
use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor};
|
use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor};
|
||||||
use ring_like::digest::{digest, SHA256};
|
|
||||||
use ring_like::rand::SystemRandom;
|
|
||||||
use ring_like::signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING};
|
|
||||||
use ring_like::{hmac, pkcs8};
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
@ -550,20 +541,28 @@ impl fmt::Debug for Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Key {
|
struct Key {
|
||||||
rng: SystemRandom,
|
rng: crypto::SystemRandom,
|
||||||
signing_algorithm: SigningAlgorithm,
|
signing_algorithm: SigningAlgorithm,
|
||||||
inner: EcdsaKeyPair,
|
inner: crypto::EcdsaKeyPair,
|
||||||
thumb: String,
|
thumb: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Key {
|
impl Key {
|
||||||
fn generate() -> Result<(Self, pkcs8::Document), Error> {
|
fn generate() -> Result<(Self, crypto::pkcs8::Document), Error> {
|
||||||
let rng = SystemRandom::new();
|
let rng = crypto::SystemRandom::new();
|
||||||
let pkcs8 = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &rng)?;
|
let pkcs8 =
|
||||||
|
crypto::EcdsaKeyPair::generate_pkcs8(&crypto::ECDSA_P256_SHA256_FIXED_SIGNING, &rng)?;
|
||||||
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
|
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
|
||||||
let key = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, pkcs8.as_ref(), &rng)?;
|
let key = crypto::EcdsaKeyPair::from_pkcs8(
|
||||||
|
&crypto::ECDSA_P256_SHA256_FIXED_SIGNING,
|
||||||
|
pkcs8.as_ref(),
|
||||||
|
&rng,
|
||||||
|
)?;
|
||||||
#[cfg(feature = "aws-lc-rs")]
|
#[cfg(feature = "aws-lc-rs")]
|
||||||
let key = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, pkcs8.as_ref())?;
|
let key = crypto::EcdsaKeyPair::from_pkcs8(
|
||||||
|
&crypto::ECDSA_P256_SHA256_FIXED_SIGNING,
|
||||||
|
pkcs8.as_ref(),
|
||||||
|
)?;
|
||||||
let thumb = BASE64_URL_SAFE_NO_PAD.encode(Jwk::thumb_sha256(&key)?);
|
let thumb = BASE64_URL_SAFE_NO_PAD.encode(Jwk::thumb_sha256(&key)?);
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
|
@ -578,11 +577,16 @@ impl Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self, Error> {
|
fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self, Error> {
|
||||||
let rng = SystemRandom::new();
|
let rng = crypto::SystemRandom::new();
|
||||||
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
|
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
|
||||||
let key = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, pkcs8_der, &rng)?;
|
let key = crypto::EcdsaKeyPair::from_pkcs8(
|
||||||
|
&crypto::ECDSA_P256_SHA256_FIXED_SIGNING,
|
||||||
|
pkcs8_der,
|
||||||
|
&rng,
|
||||||
|
)?;
|
||||||
#[cfg(feature = "aws-lc-rs")]
|
#[cfg(feature = "aws-lc-rs")]
|
||||||
let key = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, pkcs8_der)?;
|
let key =
|
||||||
|
crypto::EcdsaKeyPair::from_pkcs8(&crypto::ECDSA_P256_SHA256_FIXED_SIGNING, pkcs8_der)?;
|
||||||
|
|
||||||
let thumb = BASE64_URL_SAFE_NO_PAD.encode(Jwk::thumb_sha256(&key)?);
|
let thumb = BASE64_URL_SAFE_NO_PAD.encode(Jwk::thumb_sha256(&key)?);
|
||||||
|
|
||||||
|
@ -596,7 +600,7 @@ impl Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Signer for Key {
|
impl Signer for Key {
|
||||||
type Signature = ring_like::signature::Signature;
|
type Signature = crypto::Signature;
|
||||||
|
|
||||||
fn header<'n, 'u: 'n, 's: 'u>(&'s self, nonce: Option<&'n str>, url: &'u str) -> Header<'n> {
|
fn header<'n, 'u: 'n, 's: 'u>(&'s self, nonce: Option<&'n str>, url: &'u str) -> Header<'n> {
|
||||||
debug_assert!(nonce.is_some());
|
debug_assert!(nonce.is_some());
|
||||||
|
@ -638,7 +642,7 @@ impl KeyAuthorization {
|
||||||
///
|
///
|
||||||
/// <https://datatracker.ietf.org/doc/html/rfc8737#section-3>
|
/// <https://datatracker.ietf.org/doc/html/rfc8737#section-3>
|
||||||
pub fn digest(&self) -> impl AsRef<[u8]> {
|
pub fn digest(&self) -> impl AsRef<[u8]> {
|
||||||
digest(&SHA256, self.0.as_bytes())
|
crypto::digest(&crypto::SHA256, self.0.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the base64-encoded SHA256 digest of the key authorization
|
/// Get the base64-encoded SHA256 digest of the key authorization
|
||||||
|
@ -660,7 +664,7 @@ impl fmt::Debug for KeyAuthorization {
|
||||||
/// See RFC 8555 section 7.3.4 for more information.
|
/// See RFC 8555 section 7.3.4 for more information.
|
||||||
pub struct ExternalAccountKey {
|
pub struct ExternalAccountKey {
|
||||||
id: String,
|
id: String,
|
||||||
key: hmac::Key,
|
key: crypto::hmac::Key,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExternalAccountKey {
|
impl ExternalAccountKey {
|
||||||
|
@ -668,13 +672,13 @@ impl ExternalAccountKey {
|
||||||
pub fn new(id: String, key_value: &[u8]) -> Self {
|
pub fn new(id: String, key_value: &[u8]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
key: hmac::Key::new(hmac::HMAC_SHA256, key_value),
|
key: crypto::hmac::Key::new(crypto::hmac::HMAC_SHA256, key_value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Signer for ExternalAccountKey {
|
impl Signer for ExternalAccountKey {
|
||||||
type Signature = hmac::Tag;
|
type Signature = crypto::hmac::Tag;
|
||||||
|
|
||||||
fn header<'n, 'u: 'n, 's: 'u>(&'s self, nonce: Option<&'n str>, url: &'u str) -> Header<'n> {
|
fn header<'n, 'u: 'n, 's: 'u>(&'s self, nonce: Option<&'n str>, url: &'u str) -> Header<'n> {
|
||||||
debug_assert_eq!(nonce, None);
|
debug_assert_eq!(nonce, None);
|
||||||
|
@ -687,7 +691,7 @@ impl Signer for ExternalAccountKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign(&self, payload: &[u8]) -> Result<Self::Signature, Error> {
|
fn sign(&self, payload: &[u8]) -> Result<Self::Signature, Error> {
|
||||||
Ok(hmac::sign(&self.key, payload))
|
Ok(crypto::hmac::sign(&self.key, payload))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,6 +754,20 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod crypto {
|
||||||
|
#[cfg(feature = "aws-lc-rs")]
|
||||||
|
pub(crate) use aws_lc_rs as ring_like;
|
||||||
|
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
|
||||||
|
pub(crate) use ring as ring_like;
|
||||||
|
|
||||||
|
pub(crate) use ring_like::digest::{digest, Digest, SHA256};
|
||||||
|
pub(crate) use ring_like::error::{KeyRejected, Unspecified};
|
||||||
|
pub(crate) use ring_like::rand::SystemRandom;
|
||||||
|
pub(crate) use ring_like::signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING};
|
||||||
|
pub(crate) use ring_like::signature::{KeyPair, Signature};
|
||||||
|
pub(crate) use ring_like::{hmac, pkcs8};
|
||||||
|
}
|
||||||
|
|
||||||
const JOSE_JSON: &str = "application/jose+json";
|
const JOSE_JSON: &str = "application/jose+json";
|
||||||
const REPLAY_NONCE: &str = "Replay-Nonce";
|
const REPLAY_NONCE: &str = "Replay-Nonce";
|
||||||
|
|
||||||
|
|
25
src/types.rs
25
src/types.rs
|
@ -1,22 +1,17 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[cfg(feature = "aws-lc-rs")]
|
|
||||||
pub(crate) use aws_lc_rs as ring_like;
|
|
||||||
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
|
|
||||||
pub(crate) use ring as ring_like;
|
|
||||||
|
|
||||||
use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
|
use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
|
||||||
use http_body_util::BodyExt;
|
use http_body_util::BodyExt;
|
||||||
use hyper::body::Incoming;
|
use hyper::body::Incoming;
|
||||||
use hyper::Response;
|
use hyper::Response;
|
||||||
use ring_like::digest::{digest, Digest, SHA256};
|
|
||||||
use ring_like::signature::{EcdsaKeyPair, KeyPair};
|
|
||||||
use rustls_pki_types::CertificateDer;
|
use rustls_pki_types::CertificateDer;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::ser::SerializeMap;
|
use serde::ser::SerializeMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::crypto::{self, KeyPair};
|
||||||
|
|
||||||
/// Error type for instant-acme
|
/// Error type for instant-acme
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -30,10 +25,10 @@ pub enum Error {
|
||||||
Base64(#[from] base64::DecodeError),
|
Base64(#[from] base64::DecodeError),
|
||||||
/// Failed from cryptographic operations
|
/// Failed from cryptographic operations
|
||||||
#[error("cryptographic operation failed: {0}")]
|
#[error("cryptographic operation failed: {0}")]
|
||||||
Crypto(#[from] ring_like::error::Unspecified),
|
Crypto(#[from] crypto::Unspecified),
|
||||||
/// Failed to instantiate a private key
|
/// Failed to instantiate a private key
|
||||||
#[error("invalid key bytes: {0}")]
|
#[error("invalid key bytes: {0}")]
|
||||||
CryptoKey(#[from] ring_like::error::KeyRejected),
|
CryptoKey(#[from] crypto::KeyRejected),
|
||||||
/// HTTP failure
|
/// HTTP failure
|
||||||
#[error("HTTP request failure: {0}")]
|
#[error("HTTP request failure: {0}")]
|
||||||
Http(#[from] hyper::http::Error),
|
Http(#[from] hyper::http::Error),
|
||||||
|
@ -205,7 +200,7 @@ pub(crate) enum KeyOrKeyId<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> KeyOrKeyId<'a> {
|
impl<'a> KeyOrKeyId<'a> {
|
||||||
pub(crate) fn from_key(key: &EcdsaKeyPair) -> KeyOrKeyId<'static> {
|
pub(crate) fn from_key(key: &crypto::EcdsaKeyPair) -> KeyOrKeyId<'static> {
|
||||||
KeyOrKeyId::Key(Jwk::new(key))
|
KeyOrKeyId::Key(Jwk::new(key))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,7 +216,7 @@ pub(crate) struct Jwk {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Jwk {
|
impl Jwk {
|
||||||
pub(crate) fn new(key: &EcdsaKeyPair) -> Self {
|
pub(crate) fn new(key: &crypto::EcdsaKeyPair) -> Self {
|
||||||
let (x, y) = key.public_key().as_ref()[1..].split_at(32);
|
let (x, y) = key.public_key().as_ref()[1..].split_at(32);
|
||||||
Self {
|
Self {
|
||||||
alg: SigningAlgorithm::Es256,
|
alg: SigningAlgorithm::Es256,
|
||||||
|
@ -233,10 +228,12 @@ impl Jwk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn thumb_sha256(key: &EcdsaKeyPair) -> Result<Digest, serde_json::Error> {
|
pub(crate) fn thumb_sha256(
|
||||||
|
key: &crypto::EcdsaKeyPair,
|
||||||
|
) -> Result<crypto::Digest, serde_json::Error> {
|
||||||
let jwk = Self::new(key);
|
let jwk = Self::new(key);
|
||||||
Ok(digest(
|
Ok(crypto::digest(
|
||||||
&SHA256,
|
&crypto::SHA256,
|
||||||
&serde_json::to_vec(&JwkThumb {
|
&serde_json::to_vec(&JwkThumb {
|
||||||
crv: jwk.crv,
|
crv: jwk.crv,
|
||||||
kty: jwk.kty,
|
kty: jwk.kty,
|
||||||
|
|
Loading…
Reference in New Issue