#![allow(non_snake_case)]
use crate::{error::Format, format::schema};
use super::error;
use super::Signature;
#[cfg(feature = "pem")]
use ed25519_dalek::pkcs8::DecodePrivateKey;
use ed25519_dalek::Signer;
use ed25519_dalek::*;
use rand_core::{CryptoRng, RngCore};
use std::{convert::TryInto, hash::Hash, ops::Drop};
use zeroize::Zeroize;
#[derive(Debug, PartialEq)]
pub struct KeyPair {
pub(super) kp: ed25519_dalek::SigningKey,
}
impl KeyPair {
pub fn new() -> Self {
Self::new_with_rng(&mut rand::rngs::OsRng)
}
pub fn new_with_rng<T: RngCore + CryptoRng>(rng: &mut T) -> Self {
let kp = ed25519_dalek::SigningKey::generate(rng);
KeyPair { kp }
}
pub fn from(key: &PrivateKey) -> Self {
KeyPair {
kp: ed25519_dalek::SigningKey::from_bytes(&key.0),
}
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, error::Format> {
let bytes: [u8; 32] = bytes
.try_into()
.map_err(|_| Format::InvalidKeySize(bytes.len()))?;
Ok(KeyPair {
kp: ed25519_dalek::SigningKey::from_bytes(&bytes),
})
}
pub fn sign(&self, data: &[u8]) -> Result<Signature, error::Format> {
Ok(Signature(
self.kp
.try_sign(&data)
.map_err(|s| s.to_string())
.map_err(error::Signature::InvalidSignatureGeneration)
.map_err(error::Format::Signature)?
.to_bytes()
.to_vec(),
))
}
pub fn private(&self) -> PrivateKey {
PrivateKey(self.kp.to_bytes())
}
pub fn public(&self) -> PublicKey {
PublicKey(self.kp.verifying_key())
}
pub fn algorithm(&self) -> crate::format::schema::public_key::Algorithm {
crate::format::schema::public_key::Algorithm::Ed25519
}
#[cfg(feature = "pem")]
pub fn from_private_key_der(bytes: &[u8]) -> Result<Self, error::Format> {
let kp = SigningKey::from_pkcs8_der(bytes)
.map_err(|e| error::Format::InvalidKey(e.to_string()))?;
Ok(KeyPair { kp })
}
#[cfg(feature = "pem")]
pub fn from_private_key_pem(str: &str) -> Result<Self, error::Format> {
let kp = SigningKey::from_pkcs8_pem(str)
.map_err(|e| error::Format::InvalidKey(e.to_string()))?;
Ok(KeyPair { kp })
}
#[cfg(feature = "pem")]
pub fn to_private_key_der(&self) -> Result<zeroize::Zeroizing<Vec<u8>>, error::Format> {
use ed25519_dalek::pkcs8::EncodePrivateKey;
let kp = self
.kp
.to_pkcs8_der()
.map_err(|e| error::Format::PKCS8(e.to_string()))?;
Ok(kp.to_bytes())
}
#[cfg(feature = "pem")]
pub fn to_private_key_pem(&self) -> Result<zeroize::Zeroizing<String>, error::Format> {
use ed25519_dalek::pkcs8::EncodePrivateKey;
use p256::pkcs8::LineEnding;
let kp = self
.kp
.to_pkcs8_pem(LineEnding::LF)
.map_err(|e| error::Format::PKCS8(e.to_string()))?;
Ok(kp)
}
}
impl std::default::Default for KeyPair {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, PartialEq)]
pub struct PrivateKey(pub(crate) ed25519_dalek::SecretKey);
impl PrivateKey {
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_vec()
}
pub fn to_bytes_hex(&self) -> String {
hex::encode(self.0)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, error::Format> {
let bytes: [u8; 32] = bytes
.try_into()
.map_err(|_| Format::InvalidKeySize(bytes.len()))?;
Ok(PrivateKey(bytes))
}
pub fn from_bytes_hex(str: &str) -> Result<Self, error::Format> {
let bytes = hex::decode(str).map_err(|e| error::Format::InvalidKey(e.to_string()))?;
Self::from_bytes(&bytes)
}
#[cfg(feature = "pem")]
pub fn from_der(bytes: &[u8]) -> Result<Self, error::Format> {
let kp = SigningKey::from_pkcs8_der(bytes)
.map_err(|e| error::Format::InvalidKey(e.to_string()))?;
Ok(PrivateKey(kp.to_bytes()))
}
#[cfg(feature = "pem")]
pub fn from_pem(str: &str) -> Result<Self, error::Format> {
let kp = SigningKey::from_pkcs8_pem(str)
.map_err(|e| error::Format::InvalidKey(e.to_string()))?;
Ok(PrivateKey(kp.to_bytes()))
}
#[cfg(feature = "pem")]
pub fn to_der(&self) -> Result<zeroize::Zeroizing<Vec<u8>>, error::Format> {
use ed25519_dalek::pkcs8::EncodePrivateKey;
let kp = ed25519_dalek::SigningKey::from_bytes(&self.0)
.to_pkcs8_der()
.map_err(|e| error::Format::PKCS8(e.to_string()))?;
Ok(kp.to_bytes())
}
#[cfg(feature = "pem")]
pub fn to_pem(&self) -> Result<zeroize::Zeroizing<String>, error::Format> {
use ed25519_dalek::pkcs8::EncodePrivateKey;
use p256::pkcs8::LineEnding;
let kp = ed25519_dalek::SigningKey::from_bytes(&self.0)
.to_pkcs8_pem(LineEnding::LF)
.map_err(|e| error::Format::PKCS8(e.to_string()))?;
Ok(kp)
}
pub fn public(&self) -> PublicKey {
PublicKey(SigningKey::from_bytes(&self.0).verifying_key())
}
pub fn algorithm(&self) -> crate::format::schema::public_key::Algorithm {
crate::format::schema::public_key::Algorithm::Ed25519
}
}
impl std::clone::Clone for PrivateKey {
fn clone(&self) -> Self {
PrivateKey::from_bytes(&self.to_bytes()).unwrap()
}
}
impl Drop for PrivateKey {
fn drop(&mut self) {
self.0.zeroize();
}
}
#[derive(Debug, Clone, Copy, Eq)]
pub struct PublicKey(ed25519_dalek::VerifyingKey);
impl PublicKey {
pub fn to_bytes(&self) -> [u8; 32] {
self.0.to_bytes()
}
pub fn to_bytes_hex(&self) -> String {
hex::encode(self.to_bytes())
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, error::Format> {
let bytes: [u8; 32] = bytes
.try_into()
.map_err(|_| Format::InvalidKeySize(bytes.len()))?;
ed25519_dalek::VerifyingKey::from_bytes(&bytes)
.map(PublicKey)
.map_err(|s| s.to_string())
.map_err(Format::InvalidKey)
}
pub fn from_bytes_hex(str: &str) -> Result<Self, error::Format> {
let bytes = hex::decode(str).map_err(|e| error::Format::InvalidKey(e.to_string()))?;
Self::from_bytes(&bytes)
}
pub fn from_proto(key: &schema::PublicKey) -> Result<Self, error::Format> {
if key.algorithm != schema::public_key::Algorithm::Ed25519 as i32 {
return Err(error::Format::DeserializationError(format!(
"deserialization error: unexpected key algorithm {}",
key.algorithm
)));
}
PublicKey::from_bytes(&key.key)
}
pub fn to_proto(&self) -> schema::PublicKey {
schema::PublicKey {
algorithm: schema::public_key::Algorithm::Ed25519 as i32,
key: self.to_bytes().to_vec(),
}
}
pub fn verify_signature(
&self,
data: &[u8],
signature: &Signature,
) -> Result<(), error::Format> {
let signature_bytes: [u8; 64] = signature.0.clone().try_into().map_err(|e| {
error::Format::BlockSignatureDeserializationError(format!(
"block signature deserialization error: {:?}",
e
))
})?;
let sig = ed25519_dalek::Signature::from_bytes(&signature_bytes);
self.0
.verify_strict(&data, &sig)
.map_err(|s| s.to_string())
.map_err(error::Signature::InvalidSignature)
.map_err(error::Format::Signature)
}
pub fn algorithm(&self) -> crate::format::schema::public_key::Algorithm {
crate::format::schema::public_key::Algorithm::Ed25519
}
#[cfg(feature = "pem")]
pub fn from_der(bytes: &[u8]) -> Result<Self, error::Format> {
use ed25519_dalek::pkcs8::DecodePublicKey;
let pubkey = ed25519_dalek::VerifyingKey::from_public_key_der(bytes)
.map_err(|e| error::Format::InvalidKey(e.to_string()))?;
Ok(PublicKey(pubkey))
}
#[cfg(feature = "pem")]
pub fn from_pem(str: &str) -> Result<Self, error::Format> {
use ed25519_dalek::pkcs8::DecodePublicKey;
let pubkey = ed25519_dalek::VerifyingKey::from_public_key_pem(str)
.map_err(|e| error::Format::InvalidKey(e.to_string()))?;
Ok(PublicKey(pubkey))
}
#[cfg(feature = "pem")]
pub fn to_der(&self) -> Result<Vec<u8>, error::Format> {
use ed25519_dalek::pkcs8::EncodePublicKey;
let kp = self
.0
.to_public_key_der()
.map_err(|e| error::Format::PKCS8(e.to_string()))?;
Ok(kp.to_vec())
}
#[cfg(feature = "pem")]
pub fn to_pem(&self) -> Result<String, error::Format> {
use ed25519_dalek::pkcs8::EncodePublicKey;
use p256::pkcs8::LineEnding;
let kp = self
.0
.to_public_key_pem(LineEnding::LF)
.map_err(|e| error::Format::PKCS8(e.to_string()))?;
Ok(kp)
}
pub(crate) fn write(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ed25519/{}", hex::encode(&self.to_bytes()))
}
pub fn print(&self) -> String {
format!("ed25519/{}", hex::encode(&self.to_bytes()))
}
}
impl PartialEq for PublicKey {
fn eq(&self, other: &Self) -> bool {
self.0.to_bytes() == other.0.to_bytes()
}
}
impl Hash for PublicKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
(crate::format::schema::public_key::Algorithm::Ed25519 as i32).hash(state);
self.0.to_bytes().hash(state);
}
}