extern crate alloc;
#[cfg(feature = "std")]
use sm2::dsa::signature::hazmat::RandomizedPrehashSigner;
#[cfg(feature = "std")]
use sm2::dsa::signature::RandomizedSigner;
#[cfg(feature = "std")]
use sm2::dsa::SigningKey;
use sm2::dsa::VerifyingKey;
use super::hash::MdType;
#[cfg(feature = "std")]
use super::rng::{CryptoRng, DynCryptoRng};
use super::rsa_ecdsa;
use super::sm2_raw;
use crate::crypto::CryptoError;
pub const ECDSA_MAX_LEN: usize = 256;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PkType {
SM2,
Rsa,
Eckey,
Ecdsa,
}
enum PkInner {
#[cfg(feature = "std")]
Sm2Sign {
key: SigningKey,
scalar: [u8; 32],
},
Sm2Verify(VerifyingKey),
#[cfg(feature = "std")]
RsaSign(rsa::RsaPrivateKey),
RsaVerify(rsa::RsaPublicKey),
#[cfg(feature = "std")]
EcdsaSign(p256::ecdsa::SigningKey),
EcdsaVerify(p256::ecdsa::VerifyingKey),
}
pub struct Pk {
inner: PkInner,
}
impl Pk {
pub fn pk_type(&self) -> PkType {
match &self.inner {
#[cfg(feature = "std")]
PkInner::Sm2Sign { .. } => PkType::SM2,
PkInner::Sm2Verify(_) => PkType::SM2,
#[cfg(feature = "std")]
PkInner::RsaSign(_) => PkType::Rsa,
PkInner::RsaVerify(_) => PkType::Rsa,
#[cfg(feature = "std")]
PkInner::EcdsaSign(_) => PkType::Ecdsa,
PkInner::EcdsaVerify(_) => PkType::Ecdsa,
}
}
pub fn len(&self) -> usize {
match &self.inner {
#[cfg(feature = "std")]
PkInner::Sm2Sign { .. } | PkInner::EcdsaSign(_) => 256,
PkInner::Sm2Verify(_) | PkInner::EcdsaVerify(_) => 256,
#[cfg(feature = "std")]
PkInner::RsaSign(k) => rsa_ecdsa::rsa_key_bits(k),
PkInner::RsaVerify(k) => rsa_ecdsa::rsa_pub_key_bits(k),
}
}
#[cfg(feature = "std")]
pub fn sm2_sign(
&mut self,
md: MdType,
msg: &[u8],
sig: &mut [u8],
rng: &mut dyn CryptoRng,
) -> Result<usize, CryptoError> {
if md != MdType::SM3 {
return Err(CryptoError::UnsupportedAlgorithm);
}
let signing_key = match &self.inner {
PkInner::Sm2Sign { key, .. } => key,
_ => return Err(CryptoError::InvalidKey),
};
let mut drng = DynCryptoRng(rng);
let sig_obj = signing_key
.try_sign_with_rng(&mut drng, msg)
.map_err(|_| CryptoError::InternalError)?;
let der_bytes = sig_obj.to_der();
let der = der_bytes.as_bytes();
if der.len() > sig.len() {
return Err(CryptoError::InvalidLength);
}
sig[..der.len()].copy_from_slice(der);
Ok(der.len())
}
pub fn sm2_verify(&mut self, md: MdType, msg: &[u8], sig: &[u8]) -> Result<(), CryptoError> {
if md != MdType::SM3 {
return Err(CryptoError::UnsupportedAlgorithm);
}
let verifying_key = match &self.inner {
PkInner::Sm2Verify(k) => k,
_ => return Err(CryptoError::InvalidKey),
};
sm2_raw::verify_message_with_key(verifying_key, msg, sig)
}
#[cfg(feature = "std")]
pub fn sign(
&mut self,
md: MdType,
digest: &[u8],
sig: &mut [u8],
rng: &mut dyn CryptoRng,
) -> Result<usize, CryptoError> {
let digest: [u8; 32] = digest
.try_into()
.map_err(|_| CryptoError::InvalidLength)?;
let out = match &self.inner {
PkInner::Sm2Sign { key, .. } => {
if md != MdType::SM3 {
return Err(CryptoError::UnsupportedAlgorithm);
}
let mut drng = DynCryptoRng(rng);
let sig_obj = key
.sign_prehash_with_rng(&mut drng, &digest)
.map_err(|_| CryptoError::InternalError)?;
sig_obj.to_der().as_bytes().to_vec()
}
PkInner::RsaSign(key) => {
if md != MdType::Sha256 {
return Err(CryptoError::UnsupportedAlgorithm);
}
rsa_ecdsa::rsa_sign_digest(key, &digest, rng)?
}
PkInner::EcdsaSign(key) => {
if md != MdType::Sha256 {
return Err(CryptoError::UnsupportedAlgorithm);
}
rsa_ecdsa::ecdsa_sign_digest(key, &digest, rng)?
}
_ => return Err(CryptoError::InvalidKey),
};
if out.len() > sig.len() {
return Err(CryptoError::InvalidLength);
}
sig[..out.len()].copy_from_slice(&out);
Ok(out.len())
}
pub fn verify(&mut self, md: MdType, digest: &[u8], sig: &[u8]) -> Result<(), CryptoError> {
let digest: [u8; 32] = digest
.try_into()
.map_err(|_| CryptoError::InvalidLength)?;
match &self.inner {
PkInner::Sm2Verify(k) => {
if md != MdType::SM3 {
return Err(CryptoError::UnsupportedAlgorithm);
}
sm2_raw::verify_digest_with_key(k, &digest, sig)
}
PkInner::RsaVerify(k) => {
if md != MdType::Sha256 {
return Err(CryptoError::UnsupportedAlgorithm);
}
rsa_ecdsa::rsa_verify_digest(k, &digest, sig)
}
PkInner::EcdsaVerify(k) => {
if md != MdType::Sha256 {
return Err(CryptoError::UnsupportedAlgorithm);
}
rsa_ecdsa::ecdsa_verify_digest(k, &digest, sig)
}
#[cfg(feature = "std")]
_ => Err(CryptoError::InvalidKey),
}
}
}
impl Pk {
#[cfg(feature = "std")]
pub(crate) fn from_signing_scalar(scalar: [u8; 32]) -> Result<Self, CryptoError> {
let key = sm2_raw::signing_key_from_scalar(&scalar)?;
Ok(Self {
inner: PkInner::Sm2Sign { key, scalar },
})
}
pub(crate) fn from_verifying_key(key: VerifyingKey) -> Self {
Self {
inner: PkInner::Sm2Verify(key),
}
}
#[cfg(feature = "std")]
pub(crate) fn from_rsa_sign(key: rsa::RsaPrivateKey) -> Self {
Self {
inner: PkInner::RsaSign(key),
}
}
pub(crate) fn from_rsa_verify(key: rsa::RsaPublicKey) -> Self {
Self {
inner: PkInner::RsaVerify(key),
}
}
#[cfg(feature = "std")]
pub(crate) fn from_ecdsa_sign(key: p256::ecdsa::SigningKey) -> Self {
Self {
inner: PkInner::EcdsaSign(key),
}
}
pub(crate) fn from_ecdsa_verify(key: p256::ecdsa::VerifyingKey) -> Self {
Self {
inner: PkInner::EcdsaVerify(key),
}
}
#[cfg(feature = "std")]
#[allow(dead_code)]
pub(crate) fn secret_scalar32(&self) -> Result<[u8; 32], CryptoError> {
match &self.inner {
PkInner::Sm2Sign { scalar, .. } => Ok(*scalar),
_ => Err(CryptoError::InvalidKey),
}
}
}