use std::convert::{TryFrom, TryInto};
use super::*;
#[derive(Debug, Clone)]
pub enum SignatureAlgorithm {
EdDsa,
Es256,
Es256k,
}
impl Signer for SignatureAlgorithm {
fn signer(&self) -> SigningMethod {
match self {
SignatureAlgorithm::EdDsa => {
Box::new(|key: &[u8], message: &[u8]| -> Result<Vec<u8>, Error> {
use ed25519_dalek::{Signer, SigningKey, SECRET_KEY_LENGTH};
let key = SigningKey::from_bytes(
key.try_into().map_err(|_| Error::InvalidKeySize(format!("ed25519 expects key size of {}", SECRET_KEY_LENGTH)))?
);
let s = key.sign(message);
Ok(s.to_bytes().to_vec())
})
}
SignatureAlgorithm::Es256 => {
Box::new(|key: &[u8], message: &[u8]| -> Result<Vec<u8>, Error> {
use p256::ecdsa::{signature::Signer, Signature, SigningKey};
let sk = SigningKey::from_bytes(
key.try_into().map_err(|_| Error::InvalidKeySize(format!("p256 invalid key size")))?
)?;
let signature: Signature = sk.sign(message);
Ok(signature.to_bytes().to_vec())
})
}
SignatureAlgorithm::Es256k => {
Box::new(|key: &[u8], message: &[u8]| -> Result<Vec<u8>, Error> {
use k256::ecdsa::{signature::Signer, Signature, SigningKey};
let sk = SigningKey::from_bytes(
key.try_into().map_err(|_| Error::InvalidKeySize(format!("k256 invalid key size")))?
).map_err(|e| Error::Generic(e.to_string()))?;
let signature: Signature = sk.sign(message);
Ok(signature.to_bytes().to_vec())
})
}
}
}
fn validator(&self) -> ValidationMethod {
match self {
SignatureAlgorithm::EdDsa => Box::new(
|key: &[u8], message: &[u8], signature: &[u8]| -> Result<bool, Error> {
use ed25519_dalek::{VerifyingKey, Signature, Verifier, SECRET_KEY_LENGTH};
let ed25519_key = key.try_into()
.map_err(|_| Error::InvalidKeySize(format!("ed25519 expects key size of {}", SECRET_KEY_LENGTH)))?;
let key = VerifyingKey::from_bytes(ed25519_key)?;
let s = Signature::try_from(signature)?;
Ok(key.verify(message, &s).is_ok())
},
),
SignatureAlgorithm::Es256 => Box::new(
|key: &[u8], message: &[u8], signature: &[u8]| -> Result<bool, Error> {
use p256::ecdsa::{signature::Verifier, Signature, VerifyingKey};
let key = VerifyingKey::from_sec1_bytes(key)?;
let s = Signature::try_from(signature)?;
Ok(key.verify(message, &s).is_ok())
},
),
SignatureAlgorithm::Es256k => Box::new(
|key: &[u8], message: &[u8], signature: &[u8]| -> Result<bool, Error> {
use k256::ecdsa::{signature::Verifier, Signature, VerifyingKey};
let vk = VerifyingKey::from_sec1_bytes(key)?;
let signature = Signature::try_from(signature)?;
Ok(vk.verify(message, &signature).is_ok())
},
),
}
}
}
impl TryFrom<&String> for SignatureAlgorithm {
type Error = Error;
fn try_from(value: &String) -> Result<Self, Self::Error> {
match &value[..] {
"EdDSA" => Ok(Self::EdDsa),
"ES256" => Ok(Self::Es256),
"ES256K" => Ok(Self::Es256k),
_ => Err(Error::JwsParseError),
}
}
}
#[test]
fn es256k_test() {
use k256::{ecdsa::SigningKey, elliptic_curve::rand_core::OsRng};
let sk = SigningKey::random(&mut OsRng);
let vk = &sk.verifying_key();
let m = b"this is the message we're signing in this test...";
let signer = SignatureAlgorithm::Es256k.signer();
let validator = SignatureAlgorithm::Es256k.validator();
let sk: Vec<u8> = sk.to_bytes().to_vec();
let vk = vk.to_sec1_bytes().to_vec();
let signature = signer(&sk, m);
let validation = validator(&vk, m, &signature.unwrap());
assert!(&validation.is_ok());
assert!(validation.unwrap());
}