use crate::basic_crypto_functions::{PublicKey, Secretkey};
use super::{super::byte_array::ByteArray, BasisCryptoError, BasisCryptoErrorRepr};
use openssl::{
error::ErrorStack,
hash::MessageDigest,
pkey::{PKey, PKeyRef, Private, Public},
rsa::Padding,
sign::{RsaPssSaltlen, Signer, Verifier},
};
use thiserror::Error;
#[derive(Error, Debug)]
pub(super) enum SignatureError {
#[error("Error verifying the signature: {msg}")]
Verifiy {
msg: &'static str,
source: ErrorStack,
},
#[error("Error signing the bytes: {msg}")]
Sign {
msg: &'static str,
source: ErrorStack,
},
}
pub fn verify(
pkey: &PublicKey,
hashed: &ByteArray,
signature: &ByteArray,
) -> Result<bool, BasisCryptoError> {
verify_repr(pkey.pkey_public(), hashed, signature)
.map_err(BasisCryptoErrorRepr::from)
.map_err(BasisCryptoError::from)
}
fn verify_repr(
pkey: &PKeyRef<Public>,
hashed: &ByteArray,
signature: &ByteArray,
) -> Result<bool, SignatureError> {
let pkey_temp = PKey::from_rsa(pkey.rsa().map_err(|e| SignatureError::Verifiy {
msg: "Error in pkey.rsa",
source: e,
})?)
.map_err(|e| SignatureError::Verifiy {
msg: "Error in PKey::from_rsa",
source: e,
})?;
let rsa_pkey = pkey_temp.as_ref();
let mut verifier =
Verifier::new(MessageDigest::sha256(), rsa_pkey).map_err(|e| SignatureError::Verifiy {
msg: "Error creating Sign Verifier",
source: e,
})?;
verifier
.set_rsa_padding(Padding::PKCS1_PSS)
.map_err(|e| SignatureError::Verifiy {
msg: "Error set_rsa_padding",
source: e,
})?;
verifier
.set_rsa_mgf1_md(MessageDigest::sha256())
.map_err(|e| SignatureError::Verifiy {
msg: "Error set_rsa_mgf1_md",
source: e,
})?;
verifier
.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)
.map_err(|e| SignatureError::Verifiy {
msg: "Error set_rsa_pss_saltlen",
source: e,
})?;
verifier
.verify_oneshot(signature.to_bytes(), hashed.to_bytes())
.map_err(|e| SignatureError::Verifiy {
msg: "Error verify_oneshot",
source: e,
})
}
pub fn sign(skey: &Secretkey, hashed: &ByteArray) -> Result<ByteArray, BasisCryptoError> {
sign_repr(skey.pkey_private(), hashed)
.map_err(BasisCryptoErrorRepr::from)
.map_err(BasisCryptoError::from)
}
fn sign_repr(skey: &PKeyRef<Private>, hashed: &ByteArray) -> Result<ByteArray, SignatureError> {
let pkey_temp = PKey::from_rsa(skey.rsa().map_err(|e| SignatureError::Sign {
msg: "Error in pkey.rsa",
source: e,
})?)
.map_err(|e| SignatureError::Verifiy {
msg: "Error in PKey::from_rsa",
source: e,
})?;
let rsa_pkey = pkey_temp.as_ref();
let mut signer =
Signer::new(MessageDigest::sha256(), rsa_pkey).map_err(|e| SignatureError::Sign {
msg: "Error creating Signer",
source: e,
})?;
signer
.set_rsa_padding(Padding::PKCS1_PSS)
.map_err(|e| SignatureError::Sign {
msg: "Error set_rsa_padding",
source: e,
})?;
signer
.set_rsa_mgf1_md(MessageDigest::sha256())
.map_err(|e| SignatureError::Sign {
msg: "Error set_rsa_mgf1_md",
source: e,
})?;
signer
.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)
.map_err(|e| SignatureError::Sign {
msg: "Error set_rsa_pss_saltlen",
source: e,
})?;
signer
.update(hashed.to_bytes())
.map_err(|e| SignatureError::Sign {
msg: "Error updating the signer",
source: e,
})?;
let signature = signer.sign_to_vec().map_err(|e| SignatureError::Sign {
msg: "Error verify_oneshot",
source: e,
})?;
Ok(ByteArray::from_bytes(&signature))
}