use asn1_der::{FromDerObject, DerObject};
use rand::RngCore;
use sha2::{Digest as ShaDigestTrait, Sha256};
use secp256k1::{Message, Signature};
use super::error::{DecodingError, SigningError};
use zeroize::Zeroize;
#[derive(Clone)]
pub struct Keypair {
secret: SecretKey,
public: PublicKey
}
impl Keypair {
pub fn generate() -> Keypair {
Keypair::from(SecretKey::generate())
}
pub fn public(&self) -> &PublicKey {
&self.public
}
pub fn secret(&self) -> &SecretKey {
&self.secret
}
}
impl From<SecretKey> for Keypair {
fn from(secret: SecretKey) -> Keypair {
let public = PublicKey(secp256k1::PublicKey::from_secret_key(&secret.0));
Keypair { secret, public }
}
}
impl From<Keypair> for SecretKey {
fn from(kp: Keypair) -> SecretKey {
kp.secret
}
}
#[derive(Clone)]
pub struct SecretKey(secp256k1::SecretKey);
impl SecretKey {
pub fn generate() -> SecretKey {
let mut r = rand::thread_rng();
let mut b = [0; secp256k1::util::SECRET_KEY_SIZE];
loop {
r.fill_bytes(&mut b);
if let Ok(k) = secp256k1::SecretKey::parse(&b) {
return SecretKey(k)
}
}
}
pub fn from_bytes(mut sk: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
let sk_bytes = sk.as_mut();
let secret = secp256k1::SecretKey::parse_slice(&*sk_bytes)
.map_err(|_| DecodingError::new("failed to parse secp256k1 secret key"))?;
sk_bytes.zeroize();
Ok(SecretKey(secret))
}
pub fn from_der(mut der: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
let der_obj = der.as_mut();
let obj: Vec<DerObject> = FromDerObject::deserialize((&*der_obj).iter())
.map_err(|e| DecodingError::new("Secp256k1 DER ECPrivateKey").source(e))?;
der_obj.zeroize();
let sk_obj = obj.into_iter().nth(1)
.ok_or_else(|| DecodingError::new("Not enough elements in DER"))?;
let mut sk_bytes: Vec<u8> = FromDerObject::from_der_object(sk_obj)
.map_err(DecodingError::new)?;
let sk = SecretKey::from_bytes(&mut sk_bytes)?;
sk_bytes.zeroize();
Ok(sk)
}
pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
self.sign_hash(Sha256::digest(msg).as_ref())
}
pub fn to_bytes(&self) -> [u8; 32] {
self.0.serialize()
}
pub fn sign_hash(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
let m = Message::parse_slice(msg)
.map_err(|_| SigningError::new("failed to parse secp256k1 digest"))?;
secp256k1::sign(&m, &self.0)
.map(|s| s.0.serialize_der().as_ref().into())
.map_err(|_| SigningError::new("failed to create secp256k1 signature"))
}
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct PublicKey(secp256k1::PublicKey);
impl PublicKey {
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
self.verify_hash(Sha256::digest(msg).as_ref(), sig)
}
pub fn verify_hash(&self, msg: &[u8], sig: &[u8]) -> bool {
Message::parse_slice(msg)
.and_then(|m| Signature::parse_der(sig).map(|s| secp256k1::verify(&m, &s, &self.0)))
.unwrap_or(false)
}
pub fn encode(&self) -> [u8; 33] {
self.0.serialize_compressed()
}
pub fn encode_uncompressed(&self) -> [u8; 65] {
self.0.serialize()
}
pub fn decode(k: &[u8]) -> Result<PublicKey, DecodingError> {
secp256k1::PublicKey::parse_slice(k, Some(secp256k1::PublicKeyFormat::Compressed))
.map_err(|_| DecodingError::new("failed to parse secp256k1 public key"))
.map(PublicKey)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn secp256k1_secret_from_bytes() {
let sk1 = SecretKey::generate();
let mut sk_bytes = [0; 32];
sk_bytes.copy_from_slice(&sk1.0.serialize()[..]);
let sk2 = SecretKey::from_bytes(&mut sk_bytes).unwrap();
assert_eq!(sk1.0.serialize(), sk2.0.serialize());
assert_eq!(sk_bytes, [0; 32]);
}
}