use std::path::Path;
use std::string::FromUtf8Error;
use libslug::slugcrypt::internals::messages::Message;
use libslug::slugcrypt::internals::signature::ed25519::{self, ED25519PublicKey, ED25519SecretKey, ED25519Signature}; use libslug::slugcrypt::internals::signature::sphincs_plus::{SPHINCSPublicKey,SPHINCSSignature,SPHINCSSecretKey}; use libslug::slugcrypt::internals::signature::ml_dsa::{SlugMLDSA3,MLDSA3Keypair,MLDSA3PublicKey,MLDSA3SecretKey,MLDSA3Signature};
use libslug::slugcrypt::internals::digest::sha3::Sha3Hasher; use libslug::slugcrypt::internals::digest::blake2::{SlugBlake2bHasher, SlugBlake2sHasher}; use libslug::slugcrypt::internals::digest::digest::SlugDigest;
use libslug::slugcrypt::internals::digest::sha2::Sha2Hasher;
use libslug::slugcrypt::internals::csprng::SlugCSPRNG;
use slugencode::errors::SlugEncodingError;
use zeroize::{Zeroize,ZeroizeOnDrop};
use serde::{Serialize,Deserialize};
use serde_yaml;
use serde::{Serializer,Deserializer};
use serde::ser::Error;
use libslug::prelude::SlugCSPRNGAPI;
use slugencode::SlugEncodingUsage;
pub mod registry;
pub mod timestamping;
pub mod analysis;
pub mod fs;
pub mod prelude;
pub mod rustyfunds;
pub mod constants;
pub mod x59;
pub mod format;
pub mod errors;
pub const CERTVERSION: u8 = 1;
use crate::errors::RustySignatureErrors;
#[derive(Debug,Serialize,Deserialize,Zeroize,ZeroizeOnDrop,Clone)]
pub struct UserCertificate {
pub version: u8,
pub id: Option<u64>, pub id_8: String,
pub alg: Algorithms,
pub fingerprint: String,
pub clkey: ED25519PublicKey,
pub pqkey: SPHINCSPublicKey,
}
impl UserCertificate {
pub fn into_public_key_format(&self) -> Result<String,SlugEncodingError> {
let mut output: String = String::new();
let slugencoder = SlugEncodingUsage::new(slugencode::SlugEncodings::Hex);
let classicalkeyhex = slugencoder.encode(self.clkey.as_bytes())?;
let postquantumkeyhex = slugencoder.encode(self.pqkey.as_bytes())?;
output.push_str(&classicalkeyhex);
output.push_str(":");
output.push_str(&postquantumkeyhex);
return Ok(output)
}
pub fn into_public_key_format_with_prepended(&self) -> Result<String,SlugEncodingError> {
let mut output: String = String::new();
let x = self.into_public_key_format()?;
let prefix = Self::prefix_with_shulgin_signing();
output.push_str(&prefix);
output.push_str(&x);
return Ok(output)
}
pub fn prefix_with_shulgin_signing() -> String {
let mut output: String = String::new();
output.push_str(&constants::BRACE_OPEN);
output.push_str(&constants::RUSTYSIGSPREFIX);
output.push_str(&constants::PATH_ADDITION);
output.push_str(&constants::SHULGINSIGNINGPREFIX);
output.push_str(&constants::BRACE_CLOSE);
return output
}
pub fn from_public_key_format<T: AsRef<str>>(pk: T) -> Result<Self, RustySignatureErrors> {
let x = pk.as_ref();
let pk_iter: Vec<&str> = x.split(":").collect();
let mut ed25519_stack: [u8;32] = [0u8;32];
let ed25519 = ED25519PublicKey::from_hex_string(pk_iter[0].to_ascii_uppercase());
let sphincs = SPHINCSPublicKey::from_hex_string(pk_iter[1].to_ascii_uppercase());
let ed25519_bytes = match ed25519 {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::EncodingError(00)),
};
let sphincs_bytes = match sphincs {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::EncodingError(01)),
};
if ed25519_bytes.len() == 32 {
ed25519_stack.copy_from_slice(&ed25519_bytes);
}
else {
return Err(RustySignatureErrors::EncodingError(02))
}
let ed25519_output = ED25519PublicKey::from_bytes(ed25519_stack);
let sphincs_2 = SPHINCSPublicKey::from_bytes(&sphincs_bytes);
let sphincs_output = match sphincs_2 {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::EncodingError(03)),
};
let fingerprint_8 = get_fingerprint_8(&ed25519_output.clone(), &sphincs_output.clone());
let fingerprint = get_fingerprint(&ed25519_output.clone(), &sphincs_output.clone());
Ok(Self {
version: CERTVERSION,
id: None,
id_8: fingerprint_8,
alg: Algorithms::ShulginSigning,
fingerprint: fingerprint,
clkey: ed25519_output,
pqkey: sphincs_output,
})
}
}
#[derive(Debug,Serialize,Deserialize,Zeroize,ZeroizeOnDrop,Clone)]
pub struct UserCertificatePriv {
pub cert: UserCertificate,
pub clkeypriv: ED25519SecretKey,
pub pqkeypriv: SPHINCSSecretKey,
pub pqkeypub: SPHINCSPublicKey,
}
impl UserCertificatePriv {
pub fn into_secret_key_format(&self) -> Result<String, FromUtf8Error> {
let mut output: String = String::new();
let x_cl = self.clkeypriv.to_hex_string();
let x_pq = self.pqkeypriv.to_hex_string()?;
let x_pq_pk = self.pqkeypub.to_hex_string()?;
output.push_str(&x_cl);
output.push_str(":");
output.push_str(&x_pq);
output.push_str(":");
output.push_str(&x_pq_pk);
Ok(output)
}
pub fn from_secret_key_format<T: AsRef<str>>(sk: T) -> Result<Self, RustySignatureErrors> {
let x = sk.as_ref();
let sk_iter: Vec<&str> = x.split(":").collect();
let (ed25519_sk, ed25519_pk) = Self::from_ed25519_hex(sk_iter[0])?;
let (sphincs_sk, sphincs_pk) = Self::from_sphincs_hex(sk_iter[1], sk_iter[2])?;
let certificate = UserCertificate {
version: CERTVERSION,
id: None,
id_8: get_fingerprint_8(&ed25519_pk, &sphincs_pk),
fingerprint: get_fingerprint(&ed25519_pk, &sphincs_pk),
alg: Algorithms::ShulginSigning,
pqkey: sphincs_pk.clone(),
clkey: ed25519_pk,
};
Ok(Self {
cert: certificate,
clkeypriv: ed25519_sk,
pqkeypriv: sphincs_sk,
pqkeypub: sphincs_pk.clone(),
})
}
pub fn from_ed25519_hex(s: &str) -> Result<(ED25519SecretKey,ED25519PublicKey), RustySignatureErrors> {
let output = ED25519SecretKey::from_hex_string(s.to_ascii_uppercase());
let ed25519_sk_bytes = match output {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::ED25519Error(0))
};
let ed25519_converted = ED25519SecretKey::from_bytes(&ed25519_sk_bytes);
let output = match ed25519_converted {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::ED25519Error(1))
};
let public_key = output.public_key();
let output_pk = match public_key {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::ED25519Error(2))
};
return Ok((output,output_pk))
}
pub fn from_sphincs_hex(sk: &str, pk: &str) -> Result<(SPHINCSSecretKey,SPHINCSPublicKey),RustySignatureErrors> {
let sphincs_pk_bytes = SPHINCSPublicKey::from_hex_string(pk.to_ascii_uppercase());
let bytes_pk = match sphincs_pk_bytes {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::SPHINCSError(0))
};
let sphincs_pk = SPHINCSPublicKey::from_bytes(&bytes_pk);
let output_pk = match sphincs_pk {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::SPHINCSError(1))
};
let sphincs_sk_bytes = SPHINCSSecretKey::from_hex_string(sk.to_ascii_uppercase());
let bytes_sk = match sphincs_sk_bytes {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::SPHINCSError(2))
};
let sphincs_sk = SPHINCSSecretKey::from_bytes(&bytes_sk);
let sphincs_output_sk = match sphincs_sk {
Ok(v) => v,
Err(_) => return Err(RustySignatureErrors::SPHINCSError(3))
};
return Ok((sphincs_output_sk, output_pk))
}
}
#[derive(Debug,Serialize,Deserialize,Zeroize,ZeroizeOnDrop,Clone)]
pub struct RustySignature {
message: Vec<u8>,
signinginfo: SigningInfo,
clsig: ED25519Signature,
pqsig: SPHINCSSignature,
}
pub struct RustySignaturesUsage;
impl RustySignaturesUsage {
pub fn new() -> UserCertificatePriv {
UserCertificatePriv::generate()
}
pub fn verify(cert: UserCertificate, sig: RustySignature) -> bool {
let msg = Self::verification_process(&sig);
let hash_validility = Self::verify_pk_rand(&cert, &sig);
let classical = cert.clkey.verify(sig.clsig.clone(), &msg).expect("Failed To Verify ED25519 Signature or Message");
let postquantum = cert.pqkey.verify(Message::new(&msg), sig.pqsig.clone()).expect("Failed To Verify SPHINCS+ Signature or Message");
if classical == true && postquantum == true && hash_validility == true {
return true
}
else {
return false
}
}
fn verification_process(sig: &RustySignature) -> Vec<u8> {
let mut v = Vec::new();
v.extend_from_slice(sig.signinginfo.yamalize().as_bytes());
v.extend_from_slice(&sig.message);
return v
}
fn verify_pk(cert: &UserCertificate, sig: &RustySignature) -> bool {
let mut s: String = String::new();
s.push_str(cert.clkey.to_hex_string().as_str());
s.push_str(":");
s.push_str(cert.pqkey.to_hex_string().expect("Failed To Get SPHINCS+").as_str());
let mut hasher = Sha3Hasher::new(224);
let digest = SlugDigest::from_bytes(&hasher.update(s.as_bytes())).expect("Failed To Hash");
let final_digest = digest.to_string().to_string();
let pk_hash = sig.signinginfo.pk_hash.clone();
let id = sig.signinginfo.id.clone();
let mut hasher = SlugBlake2sHasher::new(6);
let output = hasher.update(&pk_hash);
let blake2s_digest = SlugDigest::from_bytes(&output).unwrap();
let final_blake2s_digest = blake2s_digest.to_string().to_string();
if pk_hash.clone() == final_digest && id.clone() == final_blake2s_digest {
return true
}
else {
return false
}
}
fn verify_pk_rand(cert: &UserCertificate, sig: &RustySignature) -> bool {
let mut x: Vec<u8> = vec![];
let mut s: String = String::new();
s.push_str(cert.clkey.to_hex_string().as_str());
s.push_str(":");
s.push_str(cert.pqkey.to_hex_string().expect("Failed To Get SPHINCS+").as_str());
x.extend_from_slice(&sig.signinginfo.argon);
x.extend_from_slice(&sig.signinginfo.oscsprng);
x.extend_from_slice(s.as_bytes());
let mut hasher = Sha3Hasher::new(224);
let digest = SlugDigest::from_bytes(&hasher.update(&x)).expect("Failed To Hash");
let final_digest = digest.to_string().to_string();
let pk_hash = sig.signinginfo.pk_hash.clone();
let id = sig.signinginfo.id.clone();
let mut hasher = SlugBlake2sHasher::new(6);
let output = hasher.update(&pk_hash);
let blake2s_digest = SlugDigest::from_bytes(&output).unwrap();
let final_blake2s_digest = blake2s_digest.to_string().to_string();
if pk_hash.clone() == final_digest && id.clone() == final_blake2s_digest {
return true
}
else {
return false
}
}
}
#[derive(Debug, Serialize,Deserialize,Zeroize,ZeroizeOnDrop, Clone)]
pub struct SigningInfo {
pub argon: [u8;32],
pub oscsprng: [u8;32],
pub pk_hash: String, pub id: String, }
impl SigningInfo {
pub fn yamalize(&self) -> String {
let signing_info = serde_yaml::to_string(&self).expect("Failed To Serialize SigningInfo");
return signing_info
}
fn integrity_blake2(&self) -> Vec<u8> {
let hasher = SlugBlake2bHasher::new(64);
return hasher.update(&self.yamalize().as_bytes());
}
fn integrity_sha384(&self) -> Vec<u8> {
let hasher = Sha2Hasher::new(384);
hasher.update(&self.yamalize().as_bytes())
}
pub fn get_integrity_as_bytes(&self, hasher: RustySignatureHashingIntegrity) -> Vec<u8> {
let output = match hasher {
RustySignatureHashingIntegrity::BLAKE2b_64 => self.integrity_blake2(),
RustySignatureHashingIntegrity::SHA2_384 => self.integrity_sha384(),
};
return output
}
pub fn integrity(&self, hasher: RustySignatureHashingIntegrity) -> String {
let output = SlugDigest::from_bytes(&self.get_integrity_as_bytes(hasher)).unwrap().to_string().to_string();
return output
}
}
impl RustySignature {
pub fn digest(&self) -> String {
let hasher = SlugBlake2bHasher::new(64);
let digest = hasher.update(&self.serialize_to_yaml().expect("Failed to serialize"));
SlugDigest::from_bytes(&digest).unwrap().to_string().to_string()
}
fn integrity_blake2(&self) -> Vec<u8> {
let hasher = SlugBlake2bHasher::new(64);
return hasher.update(&self.message);
}
fn integrity_sha384(&self) -> Vec<u8> {
let hasher = Sha2Hasher::new(384);
hasher.update(&self.message)
}
pub fn get_integrity_as_bytes(&self, hasher: RustySignatureHashingIntegrity) -> Vec<u8> {
let output = match hasher {
RustySignatureHashingIntegrity::BLAKE2b_64 => self.integrity_blake2(),
RustySignatureHashingIntegrity::SHA2_384 => self.integrity_sha384(),
};
return output
}
pub fn integrity(&self, hasher: RustySignatureHashingIntegrity) -> String {
let output = SlugDigest::from_bytes(&self.get_integrity_as_bytes(hasher)).unwrap().to_string().to_string();
return output
}
pub fn serialize_to_yaml(&self) -> Result<String, serde_yaml::Error> {
let x = serde_yaml::to_string(&self)?;
Ok(x)
}
}
enum RustySignatureHashingIntegrity {
BLAKE2b_64,
SHA2_384,
}
pub struct Signer;
impl Signer {
pub fn add_to_signing<T: AsRef<str>>(nonce_pass: T, pk: &ED25519PublicKey, pksphincs: &SPHINCSPublicKey) -> SigningInfo {
let (argonrng, oscsprng) = Self::csprng(nonce_pass.as_ref());
let pk_hash_randomnized_for_signing = Self::key_rand(&argonrng, &oscsprng, pk, pksphincs);
let id_rand = Self::id(&pk_hash_randomnized_for_signing);
return SigningInfo {
argon: argonrng,
oscsprng: oscsprng,
pk_hash: pk_hash_randomnized_for_signing, id: id_rand
}
}
fn csprng<T: AsRef<str>>(nonce_pass: T) -> ([u8;32],[u8;32]) {
let csprng = SlugCSPRNG::new(nonce_pass.as_ref());
let os_csprng = SlugCSPRNG::os_rand();
(csprng,os_csprng)
}
fn key(pk: &ED25519PublicKey, pksphincs: &SPHINCSPublicKey) -> String {
let mut hasher = Sha3Hasher::new(224);
let mut input_pk: String = String::new();
input_pk.push_str(&pk.to_hex_string());
input_pk.push_str(":");
input_pk.push_str(&pksphincs.to_hex_string().expect("Failed To Get SPHINCS+"));
let output = hasher.update(input_pk.as_bytes());
let final_hash = SlugDigest::from_bytes(&output).expect("Failed To Get Hash From Bytes");
return final_hash.to_string().to_string()
}
fn key_rand(argon: &[u8], csprng: &[u8], pk: &ED25519PublicKey, pksphincs: &SPHINCSPublicKey) -> String {
let mut hasher = Sha3Hasher::new(224);
let mut input_to_hash: Vec<u8> = vec![];
let mut input_pk: String = String::new();
input_pk.push_str(&pk.to_hex_string());
input_pk.push_str(&":");
input_pk.push_str(&pksphincs.to_hex_string().expect("Failed To Convert To Hex String"));
input_to_hash.extend_from_slice(argon);
input_to_hash.extend_from_slice(csprng);
input_to_hash.extend_from_slice(input_pk.as_bytes());
let output = hasher.update(&input_to_hash);
let final_hash = SlugDigest::from_bytes(&output).unwrap();
return final_hash.to_string().to_string()
}
fn id(s: &str) -> String {
let mut hasher = SlugBlake2sHasher::new(6);
let x = SlugDigest::from_bytes(&hasher.update(s.as_bytes())).expect("Failed To Use BLAKE2s");
x.to_string().to_string()
}
}
impl UserCertificatePriv {
pub fn generate() -> Self {
let ed25519sk = ED25519SecretKey::generate();
let (sphincspk,sphincssk) = SPHINCSSecretKey::generate();
return Self {
cert: UserCertificate {
version: CERTVERSION,
id: None,
fingerprint: get_fingerprint(&ed25519sk.public_key().expect("Failed To Convert ED25519 To Public Key"), &sphincspk),
id_8: get_fingerprint_8(&ed25519sk.public_key().expect("Failed To Convert ED25519 To Public Key"), &sphincspk),
alg: Algorithms::ShulginSigning,
clkey: ed25519sk.public_key().expect("Failed To Convert ED25519 To Public Key"),
pqkey: sphincspk.clone()
},
clkeypriv: ed25519sk,
pqkeypriv: sphincssk,
pqkeypub: sphincspk.clone(),
}
}
pub fn sign<T: AsRef<[u8]>, U: AsRef<str>>(&self, message: T, password: U) -> RustySignature {
let signing_info = Signer::add_to_signing(password.as_ref(), &self.cert.clkey, &self.cert.pqkey);
let mut to_be_signed: Vec<u8> = Vec::new();
let serialized_signing_info = signing_info.yamalize();
to_be_signed.extend_from_slice(serialized_signing_info.as_bytes());
to_be_signed.extend_from_slice(message.as_ref());
let sig = self.clkeypriv.sign(&to_be_signed).unwrap();
let sphincssig = self.pqkeypriv.sign(Message::new(&to_be_signed)).unwrap();
return RustySignature {
message: message.as_ref().to_vec(),
signinginfo: signing_info,
clsig: sig,
pqsig: sphincssig,
}
}
pub fn sign_with_os_salt<T: AsRef<[u8]>>(&self, message: T) -> RustySignature {
let password = SlugCSPRNGAPI::from_os();
let encoder = SlugEncodingUsage::new(slugencode::SlugEncodings::Hex);
let final_output = encoder.encode(password).unwrap();
let signing_info = Signer::add_to_signing(final_output, &self.cert.clkey, &self.cert.pqkey);
let mut to_be_signed: Vec<u8> = Vec::new();
let serialized_signing_info = signing_info.yamalize();
to_be_signed.extend_from_slice(serialized_signing_info.as_bytes());
to_be_signed.extend_from_slice(message.as_ref());
let sig = self.clkeypriv.sign(&to_be_signed).unwrap();
let sphincssig = self.pqkeypriv.sign(Message::new(&to_be_signed)).unwrap();
return RustySignature {
message: message.as_ref().to_vec(),
signinginfo: signing_info,
clsig: sig,
pqsig: sphincssig,
}
}
pub fn export(&self) -> Result<String, serde_yaml::Error> {
serde_yaml::to_string(self)
}
pub fn import<T: AsRef<str>>(s: T) -> Result<Self, serde_yaml::Error> {
serde_yaml::from_str(s.as_ref())
}
pub fn publiccert(&self) -> UserCertificate {
return self.cert.clone()
}
}
impl UserCertificate {
pub fn verify(&self) -> bool {
let fp = get_fingerprint(&self.clkey, &self.pqkey);
let id8 = get_fingerprint_8(&self.clkey, &self.pqkey);
if self.fingerprint == fp && self.id_8 == id8 {
return true
}
else {
return false
}
}
pub fn export(&self) -> Result<String, serde_yaml::Error> {
serde_yaml::to_string(&self)
}
pub fn import<T: AsRef<str>>(s: T) -> Result<Self, serde_yaml::Error> {
serde_yaml::from_str(s.as_ref())
}
}
#[derive(Debug, Serialize,Deserialize,Clone,PartialEq,PartialOrd,Zeroize,ZeroizeOnDrop)]
pub enum Algorithms {
ShulginSigning, AnneSigning,
ED25519,
}
pub fn get_fingerprint(ed25519: &ED25519PublicKey, sphincs: &SPHINCSPublicKey) -> String {
let mut hasher = SlugBlake2bHasher::new(48);
let mut input: String = String::new();
input.push_str(ed25519.to_hex_string().as_str());
input.push_str(":");
input.push_str(sphincs.to_hex_string().unwrap().as_str());
let output = hasher.update(input.as_bytes());
return SlugDigest::from_bytes(&output).unwrap().to_string().to_string()
}
pub fn get_fingerprint_8(ed25519: &ED25519PublicKey, sphincs: &SPHINCSPublicKey) -> String {
let mut hasher = SlugBlake2bHasher::new(8usize);
let mut input: String = String::new();
input.push_str(ed25519.to_hex_string().as_str());
input.push_str(":");
input.push_str(sphincs.to_hex_string().unwrap().as_str());
let output = hasher.update(input.as_bytes());
return SlugDigest::from_bytes(&output).unwrap().to_string().to_string()
}
#[test]
fn nw() {
let privcert = UserCertificatePriv::generate();
let rustysig = privcert.sign("This is my first message on the internet","123456789");
let cert = privcert.publiccert();
let sig_validility = RustySignaturesUsage::verify(cert, rustysig);
println!("Is Valid: {}", sig_validility)
}
#[test]
fn cert_test() {
let privcert = UserCertificatePriv::generate();
let yaml = privcert.export().unwrap();
let pk_format = privcert.cert.into_public_key_format().unwrap();
println!("{}",yaml);
println!("Public Key: {}",pk_format);
}
#[test]
fn certificate() {
let cert = UserCertificatePriv::generate();
let x = cert.publiccert();
let pkf = x.into_public_key_format().unwrap();
let pkfpre = x.into_public_key_format_with_prepended().unwrap();
println!("{}", pkf.clone());
let from_format: UserCertificate = UserCertificate::from_public_key_format(pkf.clone()).unwrap();
let output = from_format.into_public_key_format().unwrap();
println!("{}", pkfpre);
println!("{:?}", from_format);
println!();
println!("{}", output);
}