use bip39::Language;
use ed25519_dalek::{Signer,Verifier};
use ed25519_dalek::ed25519::SignatureEncoding;
use ed25519_dalek::SignatureError;
use ed25519_dalek::SigningKey;
use ed25519_dalek::VerifyingKey;
use ed25519_dalek::Signature;
use ed25519_dalek::SecretKey;
use rand::rngs::OsRng;
use zeroize::{Zeroize,ZeroizeOnDrop};
use serde::{Serialize,Deserialize};
use crate::slugcrypt::internals::bip39::SlugMnemonic;
use crate::slugcrypt::internals::csprng::SlugCSPRNG;
use crate::errors::SlugErrors;
use subtle_encoding::hex;
use subtle_encoding::Error;
use bip39::ErrorKind;
use base32;
use base58::{FromBase58,ToBase58,FromBase58Error};
use serde_big_array::BigArray;
use slugencode::prelude::*;
use pem::Pem;
use crate::slugcrypt::traits::{IntoPemPublic,IntoPemSecret,IntoPemSignature};
use crate::slugcrypt::traits::{IntoX59PublicKey,IntoX59SecretKey,IntoX59Signature};
#[derive(Zeroize,ZeroizeOnDrop,Serialize,Deserialize, Clone, Debug, PartialEq, PartialOrd, Hash)]
pub struct ED25519PublicKey([u8;32]);
#[derive(Zeroize,ZeroizeOnDrop,Serialize,Deserialize, Clone, Debug, PartialEq, PartialOrd, Hash)]
pub struct ED25519SecretKey([u8;32]);
#[derive(Zeroize,ZeroizeOnDrop,Debug,Serialize,Deserialize, Clone, PartialEq, PartialOrd, Hash)]
pub struct ED25519Signature(#[serde(with = "BigArray")][u8;64]);
pub mod protocol_info {
pub const PROTOCOL_NAME: &str = "libslug20/ed25519";
pub const PK_SIZE: usize = 32;
pub const SK_SIZE: usize = 32;
pub const SIG_SIZE: usize = 64;
pub const DERIVES_PUBLIC_KEY_FROM_SECRET: bool = true;
pub const RANDOMNESS: [&str;4] = ["Operating-System CSPRNG","SecureRand","Deterministic With Password","BIP39"];
pub const ENCODINGS: [&str;6] = ["Hexadecimal (Upper)","Base32 (Crockford)","Base58","PEM","Base64","Base64 URL Safe"];
}
impl ED25519SecretKey {
pub fn generate() -> ED25519SecretKey {
let csprng = SlugCSPRNG::os_rand();
let signing_key = SigningKey::from_bytes(&csprng);
return ED25519SecretKey(signing_key.to_bytes())
}
pub fn generate_securerand(pass: &str) -> ED25519SecretKey {
let csprng = SlugCSPRNG::new(pass);
let signing_key = SigningKey::from_bytes(&csprng);
return ED25519SecretKey(signing_key.to_bytes())
}
pub fn generate_deterministic(pass: &str, salt: &str) -> ED25519SecretKey {
let csprng = SlugCSPRNG::derive_from_password_with_salt(pass, salt);
let signing_key = SigningKey::from_bytes(&csprng);
return ED25519SecretKey(signing_key.to_bytes());
}
pub fn from_bip39(mnemonic: SlugMnemonic, password: &str) -> Result<Self,ErrorKind> {
let seed = mnemonic.to_seed(password)?;
Ok(Self::from_bytes(&seed).unwrap())
}
pub fn to_bytes(&self) -> [u8;32] {
self.0
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
pub fn to_hex_string(&self) -> String {
String::from_utf8(hex::encode_upper(self.0)).unwrap()
}
pub fn from_hex_string<T: AsRef<str>>(hex_str: T) -> Result<Vec<u8>,Error> {
let bytes = hex::decode_upper(hex_str.as_ref().as_bytes())?;
Ok(bytes)
}
pub fn from_bytes(bytes: &[u8]) -> Result<ED25519SecretKey, SlugErrors> {
let mut secret_key_array: [u8;32] = [0u8;32];
if bytes.len() == 32 {
secret_key_array.copy_from_slice(bytes);
return Ok(ED25519SecretKey(secret_key_array))
}
else {
return Err(SlugErrors::InvalidLengthFromBytes)
}
}
pub fn to_usable_type(&self) -> SigningKey {
SigningKey::from_bytes(&self.0)
}
pub fn public_key(&self) -> Result<ED25519PublicKey,SignatureError> {
let vk = self.to_usable_type().verifying_key();
Ok(ED25519PublicKey(vk.to_bytes()))
}
pub fn sign<T: AsRef<[u8]>>(&self, msg: T) -> Result<ED25519Signature,SignatureError> {
let signature = self.to_usable_type().try_sign(msg.as_ref())?;
return Ok(ED25519Signature(signature.to_bytes()))
}
pub fn to_pem(&self) -> String {
let pem = Pem::new("ED25519 Secret Key", &self.0);
let x = pem::encode(&pem);
return x
}
pub fn from_pem<T: AsRef<str>>(pem_str: T) -> Result<Self,SlugErrors> {
let pem = pem::parse(pem_str.as_ref()).unwrap();
if pem.tag() != "ED25519 Secret Key" {
return Err(SlugErrors::Other(String::from("ED25519 From Pem Failure")))
}
ED25519SecretKey::from_bytes(&pem.contents())
}
pub fn from_slice(bytes: &[u8]) -> Result<Self,SlugErrors> {
let mut x: [u8;32] = [0u8;32];
if bytes.len() == 32 {
x.copy_from_slice(bytes);
}
else {
return Err(SlugErrors::InvalidLengthFromBytes)
}
Ok(Self::from_bytes(&x).unwrap())
}
pub fn to_hexadecimal(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Hex).encode(&self.0)?;
Ok(x)
}
pub fn to_base32(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32).encode(&self.0)?;
Ok(x)
}
pub fn to_base58(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base58).encode(&self.0)?;
Ok(x)
}
pub fn to_base64(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64).encode(&self.0)?;
Ok(x)
}
pub fn to_base64_url_safe(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe).encode(&self.0)?;
Ok(x)
}
pub fn to_base32_unpadded(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32unpadded).encode(&self.0)?;
Ok(x)
}
pub fn from_hex<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Hex).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base32<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base32).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base58<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base58).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base64<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base64).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base64_url_safe<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base32_unpadded<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base32unpadded).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn public_key_bytes(&self) -> Result<[u8;32],SignatureError> {
let vk = self.to_usable_type().verifying_key();
Ok(vk.to_bytes())
}
}
impl ED25519PublicKey {
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn to_bytes(&self) -> [u8;32] {
self.0
}
pub fn from_bytes(bytes: [u8;32]) -> Self {
Self(bytes)
}
pub fn from_slice(bytes: &[u8]) -> Result<Self,SlugErrors> {
let mut x: [u8;32] = [0u8;32];
if bytes.len() == 32 {
x.copy_from_slice(bytes);
}
else {
return Err(SlugErrors::InvalidLengthFromBytes)
}
Ok(Self::from_bytes(x))
}
fn to_usable_type(&self) -> Result<VerifyingKey,SignatureError> {
VerifyingKey::from_bytes(&self.0)
}
pub fn verify<T: AsRef<[u8]>>(&self, signature: ED25519Signature, msg: T) -> Result<bool,SignatureError> {
let x = self.to_usable_type().unwrap().verify_strict(msg.as_ref(), &signature.to_usable_type())?;
return Ok(true)
}
pub fn to_hex_string(&self) -> String {
String::from_utf8(hex::encode_upper(self.0)).unwrap()
}
pub fn from_hex_string<T: AsRef<str>>(hex_str: T) -> Result<Vec<u8>,Error> {
let bytes = hex::decode_upper(hex_str.as_ref().as_bytes())?;
Ok(bytes)
}
pub fn to_base32_string(&self) -> String {
base32::encode(base32::Alphabet::Crockford, &self.0)
}
pub fn from_base32_string<T: AsRef<str>>(bs32_str: T) -> Vec<u8> {
let bytes = base32::decode(base32::Alphabet::Crockford, bs32_str.as_ref()).unwrap();
return bytes
}
pub fn to_pem(&self) -> String {
let pem = Pem::new("ED25519 Public Key", &self.0);
let x = pem::encode(&pem);
return x
}
pub fn from_pem<T: AsRef<str>>(pem_str: T) -> Result<Self,SlugErrors> {
let pem = pem::parse(pem_str.as_ref()).unwrap();
if pem.tag() != "ED25519 Public Key" {
return Err(SlugErrors::Other(String::from("ED25519 From Pem Failure")))
}
return Ok(ED25519PublicKey::from_slice(&pem.contents()).unwrap())
}
pub fn to_hexadecimal(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Hex).encode(&self.0)?;
Ok(x)
}
pub fn to_base32(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32).encode(&self.0)?;
Ok(x)
}
pub fn to_base58(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base58).encode(&self.0)?;
Ok(x)
}
pub fn to_base64(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64).encode(&self.0)?;
Ok(x)
}
pub fn to_base64_url_safe(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe).encode(&self.0)?;
Ok(x)
}
pub fn to_base32_unpadded(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32unpadded).encode(&self.0)?;
Ok(x)
}
pub fn from_hex<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Hex).decode(s.as_ref())?;
Ok(Self::from_slice(&bytes).unwrap())
}
pub fn from_base32<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base32).decode(s.as_ref())?;
Ok(Self::from_slice(&bytes).unwrap())
}
pub fn from_base58<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base58).decode(s.as_ref())?;
Ok(Self::from_slice(&bytes).unwrap())
}
pub fn from_base64<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base64).decode(s.as_ref())?;
Ok(Self::from_slice(&bytes).unwrap())
}
pub fn from_base64_url_safe<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe).decode(s.as_ref())?;
Ok(Self::from_slice(&bytes).unwrap())
}
pub fn from_base32_unpadded<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base32unpadded).decode(s.as_ref())?;
Ok(Self::from_slice(&bytes).unwrap())
}
}
impl ED25519Signature {
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn to_bytes(&self) -> [u8;64] {
self.0
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self,SlugErrors> {
let mut signature_array: [u8;64] = [0u8;64];
if bytes.len() == 64 {
signature_array.copy_from_slice(bytes);
return Ok(Self(signature_array))
}
else {
return Err(SlugErrors::InvalidLengthFromBytes)
}
}
pub fn to_usable_type(&self) -> Signature {
Signature::from_bytes(&self.0)
}
pub fn to_base58_string(&self) -> String {
self.0.to_base58()
}
pub fn from_base58_string<T: AsRef<str>>(base58_str: T) -> Result<Vec<u8>,FromBase58Error> {
let bytes = base58_str.as_ref().from_base58()?;
Ok(bytes)
}
pub fn to_hex_string(&self) -> String {
String::from_utf8(hex::encode_upper(self.0)).unwrap()
}
pub fn from_hex_string<T: AsRef<str>>(hex_str: T) -> Result<Vec<u8>,Error> {
let bytes = hex::decode_upper(hex_str.as_ref().as_bytes())?;
Ok(bytes)
}
pub fn from_pem<T: AsRef<str>>(pem_str: T) -> Result<Self,SlugErrors> {
let pem = pem::parse(pem_str.as_ref()).unwrap();
if pem.tag() != "ED25519 Signature" {
return Err(SlugErrors::Other(String::from("ED25519 From Pem Failure")))
}
ED25519Signature::from_bytes(&pem.contents())
}
pub fn to_pem(&self) -> String {
let pem = Pem::new("ED25519 Signature", &self.0);
let x = pem::encode(&pem);
return x
}
pub fn to_hexadecimal(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Hex).encode(&self.0)?;
Ok(x)
}
pub fn to_base32(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32).encode(&self.0)?;
Ok(x)
}
pub fn to_base58(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base58).encode(&self.0)?;
Ok(x)
}
pub fn to_base64(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64).encode(&self.0)?;
Ok(x)
}
pub fn to_base64_url_safe(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe).encode(&self.0)?;
Ok(x)
}
pub fn to_base32_unpadded(&self) -> Result<String,SlugEncodingError> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32unpadded).encode(&self.0)?;
Ok(x)
}
pub fn from_hex<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Hex).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base32<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base32).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base58<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base58).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base64<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base64).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base64_url_safe<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
pub fn from_base32_unpadded<T: AsRef<str>>(s: T) -> Result<Self,SlugEncodingError> {
let bytes = SlugEncodingUsage::new(SlugEncodings::Base32unpadded).decode(s.as_ref())?;
Ok(Self::from_bytes(&bytes).unwrap())
}
}
#[test]
fn run() {
let sk = ED25519SecretKey::generate();
println!("Secret Key: {:?}", sk);
}
#[test]
fn ed25519() {
let sk = ED25519SecretKey::generate();
let cert = sk.public_key().unwrap();
}