use crate::hash::HashAlgorithm;
use crate::key::ec::{EcComponent, EcCurve, NamedEcCurve};
use crate::key::{KeyError, PrivateKey, PublicKey};
use rsa::signature::Signer;
use picky_asn1_x509::{AlgorithmIdentifier, oids};
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum SignatureError {
#[error("Key error: {source}")]
Key { source: KeyError },
#[error("RSA error: {context}")]
Rsa { context: String },
#[error("EC error: {context}")]
Ec { context: String },
#[error("ED error: {context}")]
Ed { context: String },
#[error("invalid signature")]
BadSignature,
#[error("unsupported algorithm: {algorithm}")]
UnsupportedAlgorithm { algorithm: String },
}
impl From<rsa::errors::Error> for SignatureError {
fn from(e: rsa::errors::Error) -> Self {
SignatureError::Rsa { context: e.to_string() }
}
}
impl From<rsa::signature::Error> for SignatureError {
fn from(e: rsa::signature::Error) -> Self {
SignatureError::Rsa { context: e.to_string() }
}
}
impl From<KeyError> for SignatureError {
fn from(e: KeyError) -> Self {
SignatureError::Key { source: e }
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SignatureAlgorithm {
RsaPkcs1v15(HashAlgorithm),
Ecdsa(HashAlgorithm),
Ed25519,
}
impl TryFrom<&'_ AlgorithmIdentifier> for SignatureAlgorithm {
type Error = SignatureError;
fn try_from(v: &AlgorithmIdentifier) -> Result<Self, Self::Error> {
let oid_string: String = v.oid().into();
match oid_string.as_str() {
oids::MD5_WITH_RSA_ENCRYPTHION => Ok(Self::RsaPkcs1v15(HashAlgorithm::MD5)),
oids::SHA1_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA1)),
oids::SHA224_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA2_224)),
oids::SHA256_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA2_256)),
oids::SHA384_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA2_384)),
oids::SHA512_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA2_512)),
oids::ID_RSASSA_PKCS1_V1_5_WITH_SHA3_384 => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA3_384)),
oids::ID_RSASSA_PKCS1_V1_5_WITH_SHA3_512 => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA3_512)),
oids::ECDSA_WITH_SHA256 => Ok(Self::Ecdsa(HashAlgorithm::SHA2_256)),
oids::ECDSA_WITH_SHA384 => Ok(Self::Ecdsa(HashAlgorithm::SHA2_384)),
oids::ED25519 => Ok(Self::Ed25519),
_ => Err(SignatureError::UnsupportedAlgorithm { algorithm: oid_string }),
}
}
}
impl TryFrom<SignatureAlgorithm> for AlgorithmIdentifier {
type Error = SignatureError;
fn try_from(ty: SignatureAlgorithm) -> Result<Self, Self::Error> {
match ty {
SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::MD5) => {
Ok(AlgorithmIdentifier::new_md5_with_rsa_encryption())
}
SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA1) => {
Ok(AlgorithmIdentifier::new_sha1_with_rsa_encryption())
}
SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_224) => {
Ok(AlgorithmIdentifier::new_sha224_with_rsa_encryption())
}
SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_256) => {
Ok(AlgorithmIdentifier::new_sha256_with_rsa_encryption())
}
SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_384) => {
Ok(AlgorithmIdentifier::new_sha384_with_rsa_encryption())
}
SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_512) => {
Ok(AlgorithmIdentifier::new_sha512_with_rsa_encryption())
}
SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA3_384) => {
Ok(AlgorithmIdentifier::new_sha3_384_with_rsa_encryption())
}
SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA3_512) => {
Ok(AlgorithmIdentifier::new_sha3_512_with_rsa_encryption())
}
SignatureAlgorithm::Ecdsa(HashAlgorithm::SHA2_256) => Ok(AlgorithmIdentifier::new_ecdsa_with_sha256()),
SignatureAlgorithm::Ecdsa(HashAlgorithm::SHA2_384) => Ok(AlgorithmIdentifier::new_ecdsa_with_sha384()),
SignatureAlgorithm::Ecdsa(HashAlgorithm::SHA2_512) => Ok(AlgorithmIdentifier::new_ecdsa_with_sha512()),
SignatureAlgorithm::Ecdsa(hash) => {
let msg = format!("ECDSA doesn't support {hash:?} hashing algorithm");
Err(SignatureError::Ec { context: msg })
}
SignatureAlgorithm::Ed25519 => Ok(AlgorithmIdentifier::new_ed25519()),
}
}
}
impl SignatureAlgorithm {
pub fn from_algorithm_identifier(algorithm_identifier: &AlgorithmIdentifier) -> Result<Self, SignatureError> {
Self::try_from(algorithm_identifier)
}
pub fn sign(self, msg: &[u8], private_key: &PrivateKey) -> Result<Vec<u8>, SignatureError> {
match self {
SignatureAlgorithm::RsaPkcs1v15(picky_hash_algo) => {
use rsa::signature::SignatureEncoding as _;
use rsa::{RsaPrivateKey, pkcs1v15};
let rsa_private_key = RsaPrivateKey::try_from(private_key)?;
let signature = match picky_hash_algo {
HashAlgorithm::MD5 => pkcs1v15::SigningKey::<md5::Md5>::new(rsa_private_key).try_sign(msg)?,
HashAlgorithm::SHA1 => pkcs1v15::SigningKey::<sha1::Sha1>::new(rsa_private_key).try_sign(msg)?,
HashAlgorithm::SHA2_224 => {
pkcs1v15::SigningKey::<sha2::Sha224>::new(rsa_private_key).try_sign(msg)?
}
HashAlgorithm::SHA2_256 => {
pkcs1v15::SigningKey::<sha2::Sha256>::new(rsa_private_key).try_sign(msg)?
}
HashAlgorithm::SHA2_384 => {
pkcs1v15::SigningKey::<sha2::Sha384>::new(rsa_private_key).try_sign(msg)?
}
HashAlgorithm::SHA2_512 => {
pkcs1v15::SigningKey::<sha2::Sha512>::new(rsa_private_key).try_sign(msg)?
}
HashAlgorithm::SHA3_384 => {
pkcs1v15::SigningKey::<sha3::Sha3_384>::new(rsa_private_key).try_sign(msg)?
}
HashAlgorithm::SHA3_512 => {
pkcs1v15::SigningKey::<sha3::Sha3_512>::new(rsa_private_key).try_sign(msg)?
}
};
Ok(signature.to_vec())
}
SignatureAlgorithm::Ecdsa(picky_hash_algo) => {
use crate::key::ec::EcdsaKeypair;
use p256::ecdsa::signature::Signer;
let ec_keypair = EcdsaKeypair::try_from(private_key)?;
match ec_keypair.curve() {
NamedEcCurve::Known(EcCurve::NistP256) => match picky_hash_algo {
HashAlgorithm::SHA2_256 => {
let secret_validated =
EcCurve::NistP256.validate_component(EcComponent::Secret(ec_keypair.secret()))?;
let key_bytes =
p256::elliptic_curve::array::Array::try_from(secret_validated).map_err(|_| {
SignatureError::Ec {
context: format!(
"validated secret is not the right size(expected: {}, actual: {})",
EcCurve::NistP256.field_bytes_size(),
secret_validated.len(),
),
}
})?;
let key =
p256::ecdsa::SigningKey::from_bytes(&key_bytes).map_err(|e| SignatureError::Ec {
context: format!("Cannot decode p256 EC keypair: {e}"),
})?;
let sig: p256::ecdsa::Signature = key.try_sign(msg).map_err(|e| SignatureError::Ec {
context: format!("Cannot produce p256 signature: {e}"),
})?;
Ok(sig.to_der().as_bytes().to_vec())
}
_ => Err(SignatureError::UnsupportedAlgorithm {
algorithm: format!(
"ECDSA P-256 curve with {picky_hash_algo:?} hash algorithm is not supported"
),
}),
},
NamedEcCurve::Known(EcCurve::NistP384) => match picky_hash_algo {
HashAlgorithm::SHA2_384 => {
let secret_validated =
EcCurve::NistP384.validate_component(EcComponent::Secret(ec_keypair.secret()))?;
let key_bytes =
p384::elliptic_curve::array::Array::try_from(secret_validated).map_err(|_| {
SignatureError::Ec {
context: format!(
"validated secret is not the right size(expected: {}, actual: {})",
EcCurve::NistP384.field_bytes_size(),
secret_validated.len(),
),
}
})?;
let key =
p384::ecdsa::SigningKey::from_bytes(&key_bytes).map_err(|e| SignatureError::Ec {
context: format!("Cannot decode p384 EC keypair: {e}"),
})?;
let sig: p384::ecdsa::Signature = key.try_sign(msg).map_err(|e| SignatureError::Ec {
context: format!("Cannot produce p384 signature: {e}"),
})?;
Ok(sig.to_der().as_bytes().to_vec())
}
_ => Err(SignatureError::UnsupportedAlgorithm {
algorithm: format!(
"ECDSA P-384 curve with {picky_hash_algo:?} hash algorithm is not supported"
),
}),
},
NamedEcCurve::Known(EcCurve::NistP521) => match picky_hash_algo {
HashAlgorithm::SHA2_512 => {
let secret_validated =
EcCurve::NistP521.validate_component(EcComponent::Secret(ec_keypair.secret()))?;
let key_bytes =
p521::elliptic_curve::array::Array::try_from(secret_validated).map_err(|_| {
SignatureError::Ec {
context: format!(
"validated secret is not the right size(expected: {}, actual: {})",
EcCurve::NistP521.field_bytes_size(),
secret_validated.len(),
),
}
})?;
let key =
p521::ecdsa::SigningKey::from_bytes(&key_bytes).map_err(|e| SignatureError::Ec {
context: format!("Cannot decode p521 EC keypair: {e}"),
})?;
let sig: p521::ecdsa::Signature = key.try_sign(msg).map_err(|e| SignatureError::Ec {
context: format!("Cannot produce p521 signature: {e}"),
})?;
Ok(sig.to_der().as_bytes().to_vec())
}
_ => Err(SignatureError::UnsupportedAlgorithm {
algorithm: format!(
"ECDSA P-521 curve with {picky_hash_algo:?} hash algorithm is not supported"
),
}),
},
NamedEcCurve::Unsupported(oid) => Err(KeyError::unsupported_curve(oid, "signing").into()),
}
}
SignatureAlgorithm::Ed25519 => {
use crate::key::ed::{EdAlgorithm, EdKeypair, EdPublicKey, NamedEdAlgorithm};
let keypair = EdKeypair::try_from(private_key)?;
let public_key = EdPublicKey::try_from(&keypair)?;
match keypair.algorithm() {
NamedEdAlgorithm::Known(EdAlgorithm::Ed25519) => {
let public_key = public_key.data().try_into().map_err(|e| SignatureError::Ed {
context: format!("invalid key size: {e}"),
})?;
let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(public_key).map_err(
|e: ed25519_dalek::ed25519::Error| SignatureError::Ed {
context: format!("Cannot decode ed25519 public key: {e}"),
},
)?;
let secret_key: ed25519_dalek::SecretKey =
keypair.secret().try_into().map_err(|e| SignatureError::Ed {
context: format!("invalid secret key size: {e}"),
})?;
let esk = ed25519_dalek::hazmat::ExpandedSecretKey::from(&secret_key);
let signature = ed25519_dalek::hazmat::raw_sign::<sha2::Sha512>(&esk, msg, &verifying_key);
Ok(signature.to_vec())
}
NamedEdAlgorithm::Known(EdAlgorithm::X25519) => Err(SignatureError::Ed {
context: "X25519 algorithm is not designed for signing".to_string(),
}),
NamedEdAlgorithm::Unsupported(oid) => {
Err(KeyError::unsupported_ed_algorithm(oid, "signing").into())
}
}
}
}
}
pub fn verify(self, public_key: &PublicKey, msg: &[u8], signature: &[u8]) -> Result<(), SignatureError> {
match self {
SignatureAlgorithm::RsaPkcs1v15(picky_hash_algo) => {
use rsa::signature::Verifier as _;
use rsa::{RsaPublicKey, pkcs1v15};
let rsa_public_key = RsaPublicKey::try_from(public_key)?;
let signature = pkcs1v15::Signature::try_from(signature)?;
match picky_hash_algo {
HashAlgorithm::MD5 => {
pkcs1v15::VerifyingKey::<md5::Md5>::new(rsa_public_key).verify(msg, &signature)
}
HashAlgorithm::SHA1 => {
pkcs1v15::VerifyingKey::<sha1::Sha1>::new(rsa_public_key).verify(msg, &signature)
}
HashAlgorithm::SHA2_224 => {
pkcs1v15::VerifyingKey::<sha2::Sha224>::new(rsa_public_key).verify(msg, &signature)
}
HashAlgorithm::SHA2_256 => {
pkcs1v15::VerifyingKey::<sha2::Sha256>::new(rsa_public_key).verify(msg, &signature)
}
HashAlgorithm::SHA2_384 => {
pkcs1v15::VerifyingKey::<sha2::Sha384>::new(rsa_public_key).verify(msg, &signature)
}
HashAlgorithm::SHA2_512 => {
pkcs1v15::VerifyingKey::<sha2::Sha512>::new(rsa_public_key).verify(msg, &signature)
}
HashAlgorithm::SHA3_384 => {
pkcs1v15::VerifyingKey::<sha3::Sha3_384>::new(rsa_public_key).verify(msg, &signature)
}
HashAlgorithm::SHA3_512 => {
pkcs1v15::VerifyingKey::<sha3::Sha3_512>::new(rsa_public_key).verify(msg, &signature)
}
}
.map_err(|_| SignatureError::BadSignature)?;
}
SignatureAlgorithm::Ecdsa(picky_hash_algo) => {
let ec_pub_key = crate::key::ec::EcdsaPublicKey::try_from(public_key)?;
let curve = match ec_pub_key.curve() {
NamedEcCurve::Known(curve) => curve,
NamedEcCurve::Unsupported(oid) => return Err(KeyError::unsupported_curve(oid, "verifying").into()),
};
match picky_hash_algo {
HashAlgorithm::SHA2_256 => {
use p256::ecdsa::signature::Verifier;
match curve {
EcCurve::NistP256 => {}
curve => {
return Err(SignatureError::UnsupportedAlgorithm {
algorithm: format!("SHA256 hash algorithm can't be used with `{curve}` curve"),
});
}
};
let encoded_point = p256::Sec1Point::from_bytes(ec_pub_key.encoded_point()).map_err(|e| {
SignatureError::Ec {
context: format!("Cannot parse p256 public key from der bytes: {e}"),
}
})?;
let vkey = p256::ecdsa::VerifyingKey::from_sec1_point(&encoded_point).map_err(|e| {
SignatureError::Ec {
context: format!("Cannot parse p256 encoded point: {e}"),
}
})?;
let signature =
p256::ecdsa::Signature::from_der(signature).map_err(|e| SignatureError::Ec {
context: format!("Cannot parse p256 signature: {e}"),
})?;
vkey.verify(msg, &signature).map_err(|_| SignatureError::BadSignature)?
}
HashAlgorithm::SHA2_384 => {
use p384::ecdsa::signature::Verifier;
match curve {
EcCurve::NistP384 => {}
curve => {
return Err(SignatureError::UnsupportedAlgorithm {
algorithm: format!("SHA384 hash algorithm can't be used with `{curve}` curve"),
});
}
};
let encoded_point = p384::Sec1Point::from_bytes(ec_pub_key.encoded_point()).map_err(|e| {
SignatureError::Ec {
context: format!("Cannot parse p384 public key from der bytes: {e}"),
}
})?;
let vkey = p384::ecdsa::VerifyingKey::from_sec1_point(&encoded_point).map_err(|e| {
SignatureError::Ec {
context: format!("Cannot parse p384 encoded point: {e}"),
}
})?;
let signature =
p384::ecdsa::Signature::from_der(signature).map_err(|e| SignatureError::Ec {
context: format!("Cannot parse p384 signature: {e}"),
})?;
vkey.verify(msg, &signature).map_err(|_| SignatureError::BadSignature)?
}
HashAlgorithm::SHA2_512 => {
use p521::ecdsa::signature::Verifier;
match curve {
EcCurve::NistP521 => {}
curve => {
return Err(SignatureError::UnsupportedAlgorithm {
algorithm: format!("SHA512 hash algorithm can't be used with `{curve}` curve"),
});
}
};
let encoded_point = p521::Sec1Point::from_bytes(ec_pub_key.encoded_point()).map_err(|e| {
SignatureError::Ec {
context: format!("Cannot parse p521 public key from der bytes: {e}"),
}
})?;
let vkey = p521::ecdsa::VerifyingKey::from_sec1_point(&encoded_point).map_err(|e| {
SignatureError::Ec {
context: format!("Cannot parse p521 encoded point: {e}"),
}
})?;
let signature =
p521::ecdsa::Signature::from_der(signature).map_err(|e| SignatureError::Ec {
context: format!("Cannot parse p521 signature: {e}"),
})?;
vkey.verify(msg, &signature).map_err(|_| SignatureError::BadSignature)?
}
_ => {
return Err(SignatureError::UnsupportedAlgorithm {
algorithm: format!("ECDSA with {picky_hash_algo:?} hash algorithm is not supported"),
});
}
}
}
SignatureAlgorithm::Ed25519 => {
use crate::key::ed::{EdAlgorithm, EdPublicKey, NamedEdAlgorithm};
use ed25519_dalek::Verifier;
let public_key = EdPublicKey::try_from(public_key)?;
match public_key.algorithm() {
NamedEdAlgorithm::Known(EdAlgorithm::Ed25519) => {
let public_key = public_key.data().try_into().map_err(|e| SignatureError::Ed {
context: format!("invalid key size: {e}"),
})?;
let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(public_key).map_err(
|e: ed25519_dalek::ed25519::Error| SignatureError::Ed {
context: format!("Cannot decode ed25519 public key: {e}"),
},
)?;
let signature = signature.try_into().map_err(|e| SignatureError::Ed {
context: format!("invalid signature size: {e}"),
})?;
let signature = ed25519_dalek::Signature::from_bytes(signature);
verifying_key
.verify(msg, &signature)
.map_err(|_| SignatureError::BadSignature)?;
}
NamedEdAlgorithm::Known(EdAlgorithm::X25519) => {
return Err(SignatureError::Ed {
context: "X25519 algorithm is not designed for signing".to_string(),
});
}
NamedEdAlgorithm::Unsupported(oid) => {
return Err(KeyError::unsupported_ed_algorithm(oid, "verifying").into());
}
}
}
}
Ok(())
}
pub fn hash_algorithm(&self) -> HashAlgorithm {
match &self {
SignatureAlgorithm::RsaPkcs1v15(hash_algo) => *hash_algo,
SignatureAlgorithm::Ecdsa(hash_algo) => *hash_algo,
SignatureAlgorithm::Ed25519 => HashAlgorithm::SHA2_512,
}
}
}
#[cfg(test)]
mod ec_tests {
use super::*;
use rstest::*;
const EC_PRIVATE_KEY_NIST256_PEM: &str = r#"-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICHio5XUa+RbeFfGtGHfbPWehTFJJtCB4/izKHJ9Vm+goAoGCCqGSM49
AwEHoUQDQgAEh7ZqcI6f0tgqq7nqdcxWM6P4GGCfkWc4q11uXFjtXOKHKCV3LzMY
g8/V1PD/YOh0HodRJAjkjXub8AmYxiTcXw==
-----END EC PRIVATE KEY-----"#;
const EC_PRIVATE_KEY_NIST384_PEM: &str = r#"-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDDT8VOfdzHbIRaWOO1F0vgotY2qM2FfYS3zpdKE7Vqbh26hFsUw+iaG
GmGnT+29kg+gBwYFK4EEACKhZANiAAQFvVVUKRdN3/bqaEpDA1aHu8FEd3ujuyS0
AadG6QAiZxH37BGumBcyTTeGHyArqb+GTpsHTUXASbP+P+p5JgkfF9wBMF1SVTvu
ACZOYcqzGbsAXXdMYqewckhc42ye0u0=
-----END EC PRIVATE KEY-----"#;
#[rstest]
#[case(HashAlgorithm::MD5, false)]
#[case(HashAlgorithm::SHA1, false)]
#[case(HashAlgorithm::SHA2_224, false)]
#[case(HashAlgorithm::SHA2_256, true)]
#[case(HashAlgorithm::SHA2_384, true)]
#[case(HashAlgorithm::SHA2_512, true)]
#[case(HashAlgorithm::SHA3_384, false)]
#[case(HashAlgorithm::SHA3_512, false)]
fn algorithm_identifier_conversions(#[case] hash: HashAlgorithm, #[case] success: bool) {
let signature_algorithm = SignatureAlgorithm::Ecdsa(hash);
let algorithm_identifier = AlgorithmIdentifier::try_from(signature_algorithm);
if success {
assert!(algorithm_identifier.is_ok());
} else {
assert!(matches!(algorithm_identifier, Err(SignatureError::Ec { context: _ })));
}
}
#[test]
fn verify_bad_signature() {
let private_key_signature = PrivateKey::from_pem_str(EC_PRIVATE_KEY_NIST256_PEM).unwrap();
let signature_algorithm = SignatureAlgorithm::Ecdsa(HashAlgorithm::SHA2_256);
let msg = b"hello world";
let signature = signature_algorithm.sign(msg, &private_key_signature).unwrap();
let another_ec_private_key_nist256_pem = r#"-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIBVYtZ17YMj89Kuu47TOxJlLVlk7MDUuAlFrVXxexgkSoAoGCCqGSM49
AwEHoUQDQgAE/irzdOJk28zjVv3sov15/NLIOxoIwL9kM2p/RfQAslATwHpD/T79
csaQwO9jFvbQFIpCvcMRjaunLfhIWiYDdg==
-----END EC PRIVATE KEY-----"#;
let another_private_key = PrivateKey::from_pem_str(another_ec_private_key_nist256_pem).unwrap();
let wrong_public_key = PublicKey::try_from(another_private_key).unwrap();
assert!(matches!(
signature_algorithm.verify(&wrong_public_key, msg, &signature),
Err(SignatureError::BadSignature)
));
}
#[rstest]
#[case(picky_test_data::EC_NIST256_PK_1, HashAlgorithm::SHA2_256, true)]
#[case(picky_test_data::EC_NIST384_PK_1, HashAlgorithm::SHA2_384, true)]
#[case(picky_test_data::EC_NIST521_PK_1, HashAlgorithm::SHA2_512, true)]
fn sign_and_verify(#[case] key_pem: &str, #[case] hash: HashAlgorithm, #[case] sign_successful: bool) {
let private_key = PrivateKey::from_pem_str(key_pem).unwrap();
let signature_algorithm = SignatureAlgorithm::Ecdsa(hash);
let msg = b"hello world";
let signature = signature_algorithm.sign(msg, &private_key);
assert_eq!(signature.is_ok(), sign_successful);
if !sign_successful {
return;
}
let public_key = PublicKey::try_from(private_key).unwrap();
signature_algorithm
.verify(&public_key, msg, &signature.unwrap())
.unwrap();
}
#[rstest]
#[case(EC_PRIVATE_KEY_NIST256_PEM, &ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING, HashAlgorithm::SHA2_256)]
#[case(EC_PRIVATE_KEY_NIST384_PEM, &ring::signature::ECDSA_P384_SHA384_ASN1_SIGNING, HashAlgorithm::SHA2_384)]
fn sign_and_verify_compatibility_with_ring(
#[case] key_pem: &str,
#[case] algorithm: &'static ring::signature::EcdsaSigningAlgorithm,
#[case] hash: HashAlgorithm,
) {
let private_key = PrivateKey::from_pem_str(key_pem).unwrap();
let public_key = PublicKey::try_from(private_key).unwrap();
let msg = b"hello world";
let (privk, pubk) = match hash {
HashAlgorithm::SHA2_256 => {
use p256::Sec1Point;
let k = p256::SecretKey::from_sec1_pem(key_pem).unwrap();
(
k.to_bytes().as_slice().to_vec(),
Into::<Sec1Point>::into(k.public_key()).as_bytes().to_vec(),
)
}
HashAlgorithm::SHA2_384 => {
use p384::Sec1Point;
let k = p384::SecretKey::from_sec1_pem(key_pem).unwrap();
(
k.to_bytes().as_slice().to_vec(),
Into::<Sec1Point>::into(k.public_key()).as_bytes().to_vec(),
)
}
_ => panic!("no this condition"),
};
let rng = ring::rand::SystemRandom::new();
let keypair =
ring::signature::EcdsaKeyPair::from_private_key_and_public_key(algorithm, &privk, &pubk, &rng).unwrap();
let rng = ring::rand::SystemRandom::new();
let signature = keypair.sign(&rng, msg).unwrap();
let sig = signature.as_ref().to_vec();
let signature_algorithm = SignatureAlgorithm::Ecdsa(hash);
signature_algorithm.verify(&public_key, msg, &sig).unwrap();
}
}