#![cfg_attr(all(feature = "dsa", feature = "getrandom"), doc = "```")]
#![cfg_attr(not(all(feature = "dsa", feature = "getrandom")), doc = "```ignore")]
#[cfg(feature = "arithmetic")]
mod signing;
#[cfg(feature = "arithmetic")]
mod verifying;
#[cfg(feature = "der")]
mod der;
#[cfg(feature = "der")]
pub use der::Signature as DerSignature;
pub use signature;
#[cfg(feature = "arithmetic")]
pub use self::{signing::SigningKey, verifying::VerifyingKey};
use crate::{Array, FieldBytes, FieldBytesSize, NonZeroScalar, Sm2};
use core::{
fmt::{self, Debug},
ops::Add,
};
use signature::{Error, Result, SignatureEncoding};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "pkcs8")]
use crate::pkcs8::{
AlgorithmIdentifierRef, ObjectIdentifier, der::AnyRef, spki::AssociatedAlgorithmIdentifier,
};
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
use crate::pkcs8::{
der::{self as der_core, asn1::BitString},
spki::SignatureBitStringEncoding,
};
pub type SignatureSize = <FieldBytesSize as Add>::Output;
pub type SignatureBytes = Array<u8, SignatureSize>;
type ScalarValue = elliptic_curve::ScalarValue<Sm2>;
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Signature {
r: ScalarValue,
s: ScalarValue,
}
impl Signature {
pub const BYTE_SIZE: usize = 64;
pub fn from_bytes(bytes: &SignatureBytes) -> Result<Self> {
let (r_bytes, s_bytes) = bytes.split_at(Self::BYTE_SIZE / 2);
let r = ScalarValue::from_slice(r_bytes).map_err(|_| Error::new())?;
let s = ScalarValue::from_slice(s_bytes).map_err(|_| Error::new())?;
if r.is_zero().into() || s.is_zero().into() {
return Err(Error::new());
}
Ok(Self { r, s })
}
pub fn from_slice(bytes: &[u8]) -> Result<Self> {
SignatureBytes::try_from(bytes)
.map_err(|_| Error::new())?
.try_into()
}
#[inline]
pub fn from_scalars(r: impl Into<FieldBytes>, s: impl Into<FieldBytes>) -> Result<Self> {
Self::try_from(r.into().concat(s.into()).as_slice())
}
#[cfg(feature = "der")]
pub fn from_der(bytes: &[u8]) -> Result<Self> {
DerSignature::try_from(bytes).and_then(Self::try_from)
}
pub fn to_bytes(&self) -> SignatureBytes {
let mut ret = SignatureBytes::default();
let (r_bytes, s_bytes) = ret.split_at_mut(Self::BYTE_SIZE / 2);
r_bytes.copy_from_slice(&self.r.to_bytes());
s_bytes.copy_from_slice(&self.s.to_bytes());
ret
}
pub fn r_bytes(&self) -> FieldBytes {
self.r.to_bytes()
}
pub fn s_bytes(&self) -> FieldBytes {
self.s.to_bytes()
}
#[cfg(feature = "der")]
pub fn to_der(&self) -> DerSignature {
DerSignature::from_components(&self.r_bytes(), &self.s_bytes()).expect("DER encoding error")
}
#[cfg(feature = "alloc")]
pub fn to_vec(&self) -> Vec<u8> {
self.to_bytes().to_vec()
}
}
#[cfg(feature = "arithmetic")]
impl Signature {
pub fn r(&self) -> NonZeroScalar {
NonZeroScalar::new(self.r.into()).unwrap()
}
pub fn s(&self) -> NonZeroScalar {
NonZeroScalar::new(self.s.into()).unwrap()
}
pub fn split_scalars(&self) -> (NonZeroScalar, NonZeroScalar) {
(self.r(), self.s())
}
}
impl Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "sm2::dsa::Signature(")?;
for byte in self.to_bytes() {
write!(f, "{byte:02X}")?;
}
write!(f, ")")
}
}
impl From<Signature> for SignatureBytes {
fn from(signature: Signature) -> SignatureBytes {
signature.to_bytes()
}
}
impl From<&Signature> for SignatureBytes {
fn from(signature: &Signature) -> SignatureBytes {
signature.to_bytes()
}
}
impl SignatureEncoding for Signature {
type Repr = SignatureBytes;
fn to_bytes(&self) -> Self::Repr {
self.into()
}
fn encoded_len(&self) -> usize {
Self::BYTE_SIZE
}
}
impl TryFrom<SignatureBytes> for Signature {
type Error = Error;
fn try_from(signature: SignatureBytes) -> Result<Signature> {
Signature::from_bytes(&signature)
}
}
impl TryFrom<&SignatureBytes> for Signature {
type Error = Error;
fn try_from(signature: &SignatureBytes) -> Result<Signature> {
Signature::from_bytes(signature)
}
}
impl TryFrom<&[u8]> for Signature {
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Signature> {
Signature::from_slice(bytes)
}
}
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
impl SignatureBitStringEncoding for Signature {
fn to_bitstring(&self) -> der_core::Result<BitString> {
BitString::new(0, self.to_vec())
}
}
#[cfg(feature = "pkcs8")]
impl AssociatedAlgorithmIdentifier for Signature {
type Params = AnyRef<'static>;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = AlgorithmIdentifierRef {
oid: ObjectIdentifier::new_unwrap("1.2.156.10197.1.501"),
parameters: None,
};
}