use std::str::FromStr;
use bls_signatures::Serialize as BLSSerialize;
use pem::Pem;
use serde::{Serialize, Deserialize};
use zeroize::{Zeroize, ZeroizeOnDrop};
use serde_big_array::BigArray;
use slugencode::{SlugEncodingUsage, SlugEncodings, errors::SlugEncodingError};
use crate::errors::SlugErrors;
use rand::rngs::OsRng;
use crate::slugcrypt::traits::{IntoEncoding, FromEncoding};
use crate::slugcrypt::traits::{FromBincode,IntoBincode};
use crate::slugcrypt::traits::{FromStandardPem, IntoStandardPem};
use crate::slugcrypt::traits::{IntoStandardEncoding,FromStandardEncoding};
pub mod protocol_info {
pub const PROTOCOL_NAME: &str = "libslug20/bls12-381";
pub const BLS_PK_SIZE: usize = 48;
pub const BLS_SK_SIZE: usize = 32;
pub const BLS_SIG_SIZE: usize = 96;
pub const SOURCE_LIBRARY: &str = "bls-signatures";
pub const ENCODINGS: [&str;6] = ["Hexadecimal (Upper)","Base32 (Crockford)","Base58","PEM","Base64","Base64 URL Safe"];
pub const SIGNATURE_ALGORITHM: &str = "BLS12-381";
pub const RANDOMNESS: [&str;1] = ["Operating-System CSPRNG"];
pub const CSUITE: &str = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
pub const FEATURES: [&str;3] = ["Aggregate Signatures","Fast Verification","Deterministic Signing"];
}
impl BLSSignature {
pub fn aggregate(signatures: &[BLSSignature]) -> Result<BLSSignature, SlugErrors> {
let mut sigs = Vec::with_capacity(signatures.len());
for s in signatures {
let s0 = bls_signatures::Signature::from_bytes(&s.signature)
.map_err(|_| SlugErrors::SigningFailure(crate::errors::SlugErrorAlgorithms::SIG_BLS))?;
sigs.push(s0);
}
let agg = bls_signatures::aggregate(&sigs)
.map_err(|_| SlugErrors::SigningFailure(crate::errors::SlugErrorAlgorithms::SIG_BLS))?;
let bytes = agg.as_bytes();
if bytes.len() != protocol_info::BLS_SIG_SIZE {
return Err(SlugErrors::SigningFailure(crate::errors::SlugErrorAlgorithms::SIG_BLS));
}
let mut out = [0u8; protocol_info::BLS_SIG_SIZE];
out.copy_from_slice(&bytes);
Ok(BLSSignature { signature: out })
}
}
#[derive(Debug, Zeroize, ZeroizeOnDrop, Serialize, Deserialize, Clone, PartialEq, PartialOrd, Hash)]
pub struct BLSSecretKey {
#[serde(with = "BigArray")]
sk: [u8; protocol_info::BLS_SK_SIZE],
}
#[derive(Debug, Zeroize, ZeroizeOnDrop, Serialize, Deserialize, Clone, PartialEq, PartialOrd, Hash)]
pub struct BLSPublicKey {
#[serde(with = "BigArray")]
pk: [u8; protocol_info::BLS_PK_SIZE],
}
#[derive(Debug, Zeroize, ZeroizeOnDrop, Serialize, Deserialize, Clone, PartialEq, PartialOrd, Hash)]
pub struct BLSSignature {
#[serde(with = "BigArray")]
signature: [u8; protocol_info::BLS_SIG_SIZE],
}
pub struct SlugBLS;
impl SlugBLS {
pub fn generate() -> (BLSPublicKey, BLSSecretKey) {
let mut rng = OsRng {};
let sk = bls_signatures::PrivateKey::generate(&mut rng);
let pk = sk.public_key();
let sk_bytes = sk.as_bytes();
let pk_bytes = pk.as_bytes();
let mut sk_array = [0u8; protocol_info::BLS_SK_SIZE];
let mut pk_array = [0u8; protocol_info::BLS_PK_SIZE];
sk_array.copy_from_slice(&sk_bytes[..protocol_info::BLS_SK_SIZE]);
pk_array.copy_from_slice(&pk_bytes[..protocol_info::BLS_PK_SIZE]);
(BLSPublicKey { pk: pk_array }, BLSSecretKey { sk: sk_array })
}
}
impl BLSSecretKey {
pub fn generate() -> Self {
let mut rng = OsRng {};
let sk = bls_signatures::PrivateKey::generate(&mut rng);
let sk_bytes = sk.as_bytes();
let mut sk_array = [0u8; protocol_info::BLS_SK_SIZE];
sk_array.copy_from_slice(&sk_bytes[..protocol_info::BLS_SK_SIZE]);
Self { sk: sk_array }
}
pub fn sign<T: AsRef<[u8]>>(&self, message: T) -> Result<BLSSignature, SlugErrors> {
let sk = bls_signatures::PrivateKey::from_bytes(&self.sk)
.map_err(|_| SlugErrors::SigningFailure(crate::errors::SlugErrorAlgorithms::SIG_BLS))?;
let sig = sk.sign(message.as_ref());
let sig_bytes = sig.as_bytes();
let mut sig_array = [0u8; protocol_info::BLS_SIG_SIZE];
if sig_bytes.len() != protocol_info::BLS_SIG_SIZE {
return Err(SlugErrors::SigningFailure(crate::errors::SlugErrorAlgorithms::SIG_BLS));
}
sig_array.copy_from_slice(&sig_bytes);
Ok(BLSSignature { signature: sig_array })
}
pub fn as_bytes(&self) -> &[u8] {
&self.sk
}
pub fn to_bytes(&self) -> [u8; protocol_info::BLS_SK_SIZE] {
self.sk
}
pub fn to_vec(&self) -> Vec<u8> {
self.sk.to_vec()
}
pub fn to_hex(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Hex).encode(&self.sk)
}
pub fn to_base32(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base32).encode(&self.sk)
}
pub fn to_base32_unpadded(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base32unpadded).encode(&self.sk)
}
pub fn to_base58(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base58).encode(&self.sk)
}
pub fn to_base64(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base64).encode(&self.sk)
}
pub fn to_base64_url_safe(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base64urlsafe).encode(&self.sk)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, SlugErrors> {
if bytes.len() != protocol_info::BLS_SK_SIZE {
return Err(SlugErrors::InvalidLengthFromBytes);
}
let mut sk_array = [0u8; protocol_info::BLS_SK_SIZE];
sk_array.copy_from_slice(bytes);
Ok(Self { sk: sk_array })
}
pub fn from_hex<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Hex);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base32<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base32);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base32_unpadded<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base32unpadded);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base58<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base58);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base64<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base64);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base64_url_safe<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn to_pem(&self) -> String {
let pem = Pem::new("BLS PRIVATE KEY", self.as_bytes());
return pem.to_string()
}
pub fn from_pem<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let pem = pem::parse(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
if pem.tag() != "BLS PRIVATE KEY" {
return Err(SlugErrors::InvalidLengthFromBytes)
}
Ok(Self::from_bytes(&pem.contents())?)
}
}
impl BLSPublicKey {
pub fn verify<T: AsRef<[u8]>>(&self, message: T, signature: &BLSSignature) -> Result<bool, SlugErrors> {
let pk = Self::to_usable_types(&self)?;
let sig = bls_signatures::Signature::from_bytes(&signature.signature).map_err(|_| SlugErrors::VerifyingError(crate::errors::SlugErrorAlgorithms::SIG_BLS))?;
let ok = pk.verify(sig, message.as_ref());
Ok(ok)
}
pub fn to_usable_types(&self) -> Result<bls_signatures::PublicKey, SlugErrors> {
let pk = bls_signatures::PublicKey::from_bytes(&self.pk)
.map_err(|_| SlugErrors::VerifyingError(crate::errors::SlugErrorAlgorithms::SIG_BLS))?;
Ok(pk)
}
pub fn as_bytes(&self) -> &[u8] {
&self.pk
}
pub fn to_hex(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Hex).encode(&self.pk)
}
pub fn to_base32(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base32).encode(&self.pk)
}
pub fn to_base32_unpadded(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base32unpadded).encode(&self.pk)
}
pub fn to_base58(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base58).encode(&self.pk)
}
pub fn to_base64(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base64).encode(&self.pk)
}
pub fn to_base64_url_safe(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base64urlsafe).encode(&self.pk)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, SlugErrors> {
if bytes.len() != protocol_info::BLS_PK_SIZE {
return Err(SlugErrors::InvalidLengthFromBytes);
}
let mut pk_array = [0u8; protocol_info::BLS_PK_SIZE];
pk_array.copy_from_slice(bytes);
Ok(Self { pk: pk_array })
}
pub fn to_pem(&self) -> String {
let pem = Pem::new("BLS PUBLIC KEY", self.as_bytes());
return pem.to_string()
}
pub fn from_pem<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let pem = pem::parse(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
if pem.tag() != "BLS PUBLIC KEY" {
return Err(SlugErrors::InvalidLengthFromBytes)
}
Ok(Self::from_bytes(&pem.contents())?)
}
pub fn from_hex<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Hex);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base32<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base32);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base32_unpadded<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base32unpadded);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base58<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base58);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base64<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base64);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base64_url_safe<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
}
impl BLSSignature {
pub fn as_bytes(&self) -> &[u8] {
&self.signature
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, SlugErrors> {
if bytes.len() != protocol_info::BLS_SIG_SIZE {
return Err(SlugErrors::InvalidLengthFromBytes);
}
let mut sig_array = [0u8; protocol_info::BLS_SIG_SIZE];
sig_array.copy_from_slice(bytes);
Ok(Self { signature: sig_array })
}
pub fn from_hex<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Hex);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base32<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base32);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base32_unpadded<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base32unpadded);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base58<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base58);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base64<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base64);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn from_base64_url_safe<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let decoder = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe);
let bytes = decoder.decode(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
Self::from_bytes(&bytes)
}
pub fn to_hex(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Hex).encode(&self.signature)
}
pub fn to_base32(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base32).encode(&self.signature)
}
pub fn to_base32_unpadded(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base32unpadded).encode(&self.signature)
}
pub fn to_base58(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base58).encode(&self.signature)
}
pub fn to_base64(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base64).encode(&self.signature)
}
pub fn to_base64_url_safe(&self) -> Result<String, SlugEncodingError> {
SlugEncodingUsage::new(SlugEncodings::Base64urlsafe).encode(&self.signature)
}
}
impl BLSSignature {
pub fn to_pem(&self) -> String {
let pem = Pem::new("BLS SIGNATURE", self.as_bytes());
return pem.to_string()
}
pub fn from_pem<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let pem = pem::parse(s.as_ref()).map_err(|_| SlugErrors::InvalidLengthFromBytes)?;
if pem.tag() != "BLS SIGNATURE" {
return Err(SlugErrors::InvalidLengthFromBytes)
}
Ok(Self::from_bytes(&pem.contents())?)
}
}
impl IntoEncoding for BLSPublicKey {
fn into_hex(&self) -> Result<String, SlugErrors> {
let encoder = SlugEncodingUsage::new(SlugEncodings::Hex);
let output = encoder.encode(self.pk)?;
return Ok(output)
}
fn into_base32(&self) -> Result<String, SlugErrors> {
let encoder = SlugEncodingUsage::new(SlugEncodings::Base32);
let output = encoder.encode(self.pk)?;
return Ok(output)
}
fn into_base32_unpadded(&self) -> Result<String, SlugErrors> {
let encoder = SlugEncodingUsage::new(SlugEncodings::Base32unpadded);
let output = encoder.encode(self.pk)?;
return Ok(output)
}
fn into_base58(&self) -> Result<String, SlugErrors> {
let encoder = SlugEncodingUsage::new(SlugEncodings::Base58);
let output = encoder.encode(self.pk)?;
return Ok(output)
}
fn into_base64(&self) -> Result<String, SlugErrors> {
let encoder = SlugEncodingUsage::new(SlugEncodings::Base64);
let output = encoder.encode(self.pk)?;
return Ok(output)
}
fn into_base64_url_safe(&self) -> Result<String, SlugErrors> {
let encoder = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe);
let output = encoder.encode(self.pk)?;
return Ok(output)
}
}
impl IntoEncoding for BLSSecretKey {
fn into_hex(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Hex);
let output = x.encode(&self.sk)?;
return Ok(output)
}
fn into_base32(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32);
let output = x.encode(&self.sk)?;
return Ok(output)
}
fn into_base32_unpadded(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32unpadded);
let output = x.encode(&self.sk)?;
return Ok(output)
}
fn into_base58(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base58);
let output = x.encode(&self.sk)?;
return Ok(output)
}
fn into_base64(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64);
let output = x.encode(&self.sk)?;
return Ok(output)
}
fn into_base64_url_safe(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe);
let output = x.encode(&self.sk)?;
return Ok(output)
}
}
impl IntoEncoding for BLSSignature {
fn into_hex(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Hex);
let output = x.encode(&self.signature)?;
return Ok(output)
}
fn into_base32(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32);
let output = x.encode(&self.signature)?;
return Ok(output)
}
fn into_base32_unpadded(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32unpadded);
let output = x.encode(&self.signature)?;
return Ok(output)
}
fn into_base58(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base58);
let output = x.encode(&self.signature)?;
return Ok(output)
}
fn into_base64(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64);
let output = x.encode(&self.signature)?;
return Ok(output)
}
fn into_base64_url_safe(&self) -> Result<String,SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe);
let output = x.encode(&self.signature)?;
return Ok(output)
}
}
impl FromEncoding for BLSPublicKey {
fn from_hex<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Hex);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base32<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base32_unpadded<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32unpadded);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base58<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base58);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base64<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base64_url_safe<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
}
impl FromEncoding for BLSSecretKey {
fn from_hex<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Hex);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base32<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base32_unpadded<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32unpadded);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base58<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base58);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base64<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
fn from_base64_url_safe<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe);
let output = x.decode(s.as_ref())?;
let pk = Self::from_bytes(&output)?;
return Ok(pk)
}
}
impl FromEncoding for BLSSignature {
fn from_hex<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Hex);
let output = x.decode(s.as_ref())?;
let sig = Self::from_bytes(&output)?;
return Ok(sig)
}
fn from_base32<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32);
let output = x.decode(s.as_ref())?;
let sig = Self::from_bytes(&output)?;
return Ok(sig)
}
fn from_base32_unpadded<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base32unpadded);
let output = x.decode(s.as_ref())?;
let sig = Self::from_bytes(&output)?;
return Ok(sig)
}
fn from_base58<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base58);
let output = x.decode(s.as_ref())?;
let sig = Self::from_bytes(&output)?;
return Ok(sig)
}
fn from_base64<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64);
let output = x.decode(s.as_ref())?;
let sig = Self::from_bytes(&output)?;
return Ok(sig)
}
fn from_base64_url_safe<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let x = SlugEncodingUsage::new(SlugEncodings::Base64urlsafe);
let output = x.decode(s.as_ref())?;
let sig = Self::from_bytes(&output)?;
return Ok(sig)
}
}
impl FromBincode for BLSPublicKey {
fn from_bincode<T: AsRef<[u8]>>(bytes: T) -> Result<Self, SlugErrors> {
let output = bincode::deserialize(bytes.as_ref())?;
Ok(output)
}
}
impl FromBincode for BLSSecretKey {
fn from_bincode<T: AsRef<[u8]>>(bytes: T) -> Result<Self, SlugErrors> {
let output = bincode::deserialize(bytes.as_ref())?;
Ok(output)
}
}
impl FromBincode for BLSSignature {
fn from_bincode<T: AsRef<[u8]>>(bytes: T) -> Result<Self, SlugErrors> {
let output = bincode::deserialize(bytes.as_ref())?;
Ok(output)
}
}
impl IntoBincode for BLSPublicKey {
fn into_bincode(&self) -> Result<Vec<u8>, SlugErrors> {
let output = bincode::serialize(self)?;
Ok(output)
}
}
impl IntoBincode for BLSSecretKey {
fn into_bincode(&self) -> Result<Vec<u8>, SlugErrors> {
let output = bincode::serialize(self)?;
Ok(output)
}
}
impl IntoBincode for BLSSignature {
fn into_bincode(&self) -> Result<Vec<u8>, SlugErrors> {
let output = bincode::serialize(self)?;
Ok(output)
}
}
impl IntoStandardPem for BLSPublicKey {
fn into_standard_pem(&self) -> Result<String,SlugErrors> {
let output = self.into_bincode()?;
let pem: Pem = Pem::new(&Self::label_for_standard_pem(), output);
let output = pem.to_string();
return Ok(output)
}
fn label_for_standard_pem() -> String {
String::from("OpenInternetCryptographyProject/BLS12-381-Public-Key")
}
fn label_for_standard_pem_secret() -> String {
String::from("OpenInternetCryptographyProject/BLS12-381-Secret-Key")
}
}
impl IntoStandardPem for BLSSecretKey {
fn into_standard_pem(&self) -> Result<String,SlugErrors> {
let output = self.into_bincode()?;
let pem: Pem = Pem::new(&Self::label_for_standard_pem(), output);
let output = pem.to_string();
return Ok(output)
}
fn label_for_standard_pem() -> String {
String::from("OpenInternetCryptographyProject/BLS12-381-Secret-Key")
}
fn label_for_standard_pem_secret() -> String {
String::from("OpenInternetCryptographyProject/BLS12-381-Secret-Key")
}
}
impl IntoStandardPem for BLSSignature {
fn into_standard_pem(&self) -> Result<String,SlugErrors> {
let output = self.into_bincode()?;
let pem: Pem = Pem::new(&Self::label_for_standard_pem(), output);
let output = pem.to_string();
return Ok(output)
}
fn label_for_standard_pem() -> String {
String::from("OpenInternetCryptographyProject/BLS12-381-Signature")
}
fn label_for_standard_pem_secret() -> String {
String::from("OpenInternetCryptographyProject/BLS12-381-Secret-Key")
}
}
impl FromStandardPem for BLSPublicKey {
fn from_standard_pem<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let pem: Pem = Pem::from_str(s.as_ref())?;
if pem.tag() != Self::label_for_standard_pem() {
return Err(SlugErrors::InvalidLengthFromBytes)
}
let output: BLSPublicKey = Self::from_bincode(pem.contents())?;
return Ok(output)
}
}
impl FromStandardPem for BLSSecretKey {
fn from_standard_pem<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let pem: Pem = Pem::from_str(s.as_ref())?;
if pem.tag() != Self::label_for_standard_pem() {
return Err(SlugErrors::InvalidLengthFromBytes)
}
let output: BLSSecretKey = Self::from_bincode(pem.contents())?;
return Ok(output)
}
}
impl FromStandardPem for BLSSignature {
fn from_standard_pem<T: AsRef<str>>(s: T) -> Result<Self, SlugErrors> {
let pem: Pem = Pem::from_str(s.as_ref())?;
if pem.tag() != Self::label_for_standard_pem() {
return Err(SlugErrors::InvalidLengthFromBytes)
}
let output: BLSSignature = Self::from_bincode(pem.contents())?;
return Ok(output)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bls_roundtrip_sign_verify() {
let (pk, sk) = SlugBLS::generate();
let msg = b"test message";
let sig = sk.sign(msg).expect("sign");
let ok = pk.verify(msg, &sig).expect("verify");
assert!(ok);
}
}