#![forbid(unsafe_code)]
#![cfg_attr(feature = "rsa", doc = "```")]
#![cfg_attr(not(feature = "rsa"), doc = "```ignore")]
#[cfg(feature = "rsa")]
pub trait RingRsaKeyPairExt {
fn rsa_key_pair_ring(&self) -> ring::rsa::KeyPair;
}
#[cfg(feature = "rsa")]
impl RingRsaKeyPairExt for uselesskey_rsa::RsaKeyPair {
fn rsa_key_pair_ring(&self) -> ring::rsa::KeyPair {
ring::rsa::KeyPair::from_pkcs8(self.private_key_pkcs8_der()).expect("valid RSA PKCS#8 DER")
}
}
#[cfg(feature = "ecdsa")]
use ring::signature::{
ECDSA_P256_SHA256_ASN1_SIGNING, ECDSA_P384_SHA384_ASN1_SIGNING,
EcdsaKeyPair as RingEcdsaKeyPair, EcdsaSigningAlgorithm,
};
#[cfg(feature = "ecdsa")]
pub trait RingEcdsaKeyPairExt {
fn ecdsa_key_pair_ring(&self) -> RingEcdsaKeyPair;
}
#[cfg(feature = "ecdsa")]
impl RingEcdsaKeyPairExt for uselesskey_ecdsa::EcdsaKeyPair {
fn ecdsa_key_pair_ring(&self) -> RingEcdsaKeyPair {
let alg: &'static EcdsaSigningAlgorithm = match self.spec() {
uselesskey_ecdsa::EcdsaSpec::Es256 => &ECDSA_P256_SHA256_ASN1_SIGNING,
uselesskey_ecdsa::EcdsaSpec::Es384 => &ECDSA_P384_SHA384_ASN1_SIGNING,
};
RingEcdsaKeyPair::from_pkcs8(
alg,
self.private_key_pkcs8_der(),
&ring::rand::SystemRandom::new(),
)
.expect("valid ECDSA PKCS#8 DER")
}
}
#[cfg(feature = "ed25519")]
pub trait RingEd25519KeyPairExt {
fn ed25519_key_pair_ring(&self) -> ring::signature::Ed25519KeyPair;
}
#[cfg(feature = "ed25519")]
impl RingEd25519KeyPairExt for uselesskey_ed25519::Ed25519KeyPair {
fn ed25519_key_pair_ring(&self) -> ring::signature::Ed25519KeyPair {
ring::signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(self.private_key_pkcs8_der())
.expect("valid Ed25519 PKCS#8 DER")
}
}
#[cfg(test)]
mod tests {
use std::sync::OnceLock;
use uselesskey_core::{Factory, Seed};
static FX: OnceLock<Factory> = OnceLock::new();
fn fx() -> Factory {
FX.get_or_init(|| {
let seed = Seed::from_env_value("uselesskey-ring-inline-test-seed-v1")
.expect("test seed should always parse");
Factory::deterministic(seed)
})
.clone()
}
#[cfg(feature = "rsa")]
mod rsa_tests {
use crate::RingRsaKeyPairExt;
use ring::signature;
use uselesskey_rsa::{RsaFactoryExt, RsaSpec};
#[test]
fn test_rsa_sign_verify() {
let fx = super::fx();
let rsa = fx.rsa("test", RsaSpec::rs256());
let ring_kp = rsa.rsa_key_pair_ring();
let msg = b"test message";
let rng = ring::rand::SystemRandom::new();
let mut sig = vec![0u8; ring_kp.public().modulus_len()];
ring_kp
.sign(&signature::RSA_PKCS1_SHA256, &rng, msg, &mut sig)
.expect("sign");
let public_key_bytes = ring_kp.public().as_ref();
let public_key = signature::UnparsedPublicKey::new(
&signature::RSA_PKCS1_2048_8192_SHA256,
public_key_bytes,
);
public_key.verify(msg, &sig).expect("verify");
}
}
#[cfg(feature = "rsa")]
mod rsa_deterministic_tests {
use crate::RingRsaKeyPairExt;
use ring::signature;
use uselesskey_core::{Factory, Seed};
use uselesskey_rsa::{RsaFactoryExt, RsaSpec};
#[test]
fn test_rsa_deterministic_sign_verify() {
let seed = Seed::from_env_value("test-seed").unwrap();
let fx = Factory::deterministic(seed);
let rsa = fx.rsa("det-test", RsaSpec::rs256());
let ring_kp = rsa.rsa_key_pair_ring();
let msg = b"deterministic message";
let rng = ring::rand::SystemRandom::new();
let mut sig = vec![0u8; ring_kp.public().modulus_len()];
ring_kp
.sign(&signature::RSA_PKCS1_SHA256, &rng, msg, &mut sig)
.expect("sign");
let public_key_bytes = ring_kp.public().as_ref();
let public_key = signature::UnparsedPublicKey::new(
&signature::RSA_PKCS1_2048_8192_SHA256,
public_key_bytes,
);
public_key.verify(msg, &sig).expect("verify");
}
}
#[cfg(feature = "ecdsa")]
mod ecdsa_tests {
use crate::RingEcdsaKeyPairExt;
use ring::signature::{self, KeyPair};
use uselesskey_core::Factory;
use uselesskey_ecdsa::{EcdsaFactoryExt, EcdsaSpec};
#[test]
fn test_ecdsa_p256_sign_verify() {
let fx = Factory::random();
let ecdsa = fx.ecdsa("test", EcdsaSpec::es256());
let ring_kp = ecdsa.ecdsa_key_pair_ring();
let msg = b"test message";
let rng = ring::rand::SystemRandom::new();
let sig = ring_kp.sign(&rng, msg).expect("sign");
let public_key_bytes = ring_kp.public_key().as_ref();
let public_key = signature::UnparsedPublicKey::new(
&signature::ECDSA_P256_SHA256_ASN1,
public_key_bytes,
);
public_key.verify(msg, sig.as_ref()).expect("verify");
}
#[test]
fn test_ecdsa_p384_sign_verify() {
let fx = Factory::random();
let ecdsa = fx.ecdsa("test", EcdsaSpec::es384());
let ring_kp = ecdsa.ecdsa_key_pair_ring();
let msg = b"test message";
let rng = ring::rand::SystemRandom::new();
let sig = ring_kp.sign(&rng, msg).expect("sign");
let public_key_bytes = ring_kp.public_key().as_ref();
let public_key = signature::UnparsedPublicKey::new(
&signature::ECDSA_P384_SHA384_ASN1,
public_key_bytes,
);
public_key.verify(msg, sig.as_ref()).expect("verify");
}
}
#[cfg(feature = "ed25519")]
mod ed25519_tests {
use crate::RingEd25519KeyPairExt;
use ring::signature::{self, KeyPair};
use uselesskey_core::Factory;
use uselesskey_ed25519::{Ed25519FactoryExt, Ed25519Spec};
#[test]
fn test_ed25519_sign_verify() {
let fx = Factory::random();
let ed = fx.ed25519("test", Ed25519Spec::new());
let ring_kp = ed.ed25519_key_pair_ring();
let msg = b"test message";
let sig = ring_kp.sign(msg);
let public_key_bytes = ring_kp.public_key().as_ref();
let public_key =
signature::UnparsedPublicKey::new(&signature::ED25519, public_key_bytes);
public_key.verify(msg, sig.as_ref()).expect("verify");
}
}
}