pub struct SigningKey(/* private fields */);Expand description
A DSTU 4145 private key. Signing needs no RNG (see the module doc) - only key generation from
external entropy is the caller’s concern, same posture as hazmat::kalyna_ccm’s nonce
(docs/DECISIONS.md D-40): this module takes d as given rather than generating it.
Implementations§
Source§impl SigningKey
impl SigningKey
Sourcepub fn from_bytes(d: &[u8; 21]) -> Option<Self>
pub fn from_bytes(d: &[u8; 21]) -> Option<Self>
Builds a signing key from a big-endian 21-byte scalar. Returns None if d is zero or
not less than the curve order n - both invalid private keys, rejected here rather than
left to silently misbehave later (hazmat::dstu4145::scalar::Scalar::from_be_bytes itself
does not validate, by its own documented convention).
Sourcepub fn generate() -> Result<Self, RandomError>
pub fn generate() -> Result<Self, RandomError>
Generates a fresh signing key from the OS CSPRNG - libsodium’s crypto_sign_keypair()
equivalent (its public-key half is Self::verifying_key). d is drawn via rejection
sampling, uniform over [1, n), never a modulo reduction - n is not a power of two, so
candidate mod n would bias small residues (docs/TASKS.md T-122). n’s top byte is 0x04
(hazmat::dstu4145::curve163::order’s own doc comment: n is a 163-bit value inside 21
bytes/168 bits), so masking each candidate’s top byte down to its low 3 bits (0x07) keeps
the rejection rate near 50% instead of over 90% for an unmasked 168-bit draw. The
range/nonzero check itself goes through Scalar::from_candidate_bytes’s constant-time
comparison, not a branching >=, so evaluating one candidate adds no data-dependent-branch
timing signal beyond the draw count every rejection-sampling scheme inherently has.
§Errors
Returns crate::randombytes::RandomError if the OS CSPRNG fails while drawing a
candidate.
Sourcepub fn to_bytes(&self) -> [u8; 21]
pub fn to_bytes(&self) -> [u8; 21]
Returns d’s big-endian 21-byte encoding, so a generated key can be persisted (e.g.
uacrypt sign-keygen, docs/TASKS.md T-124) and later reloaded via Self::from_bytes. The
caller becomes responsible for zeroizing the returned array once done with it - the same
convention hazmat::dstu4145::scalar::Scalar::to_be_bytes and
VerifyingKey::to_uncompressed_bytes already have (this module has no wrapper type for a
bare byte array to hang a Drop impl off of).
pub fn verifying_key(&self) -> VerifyingKey
Sourcepub fn sign(&self, message: &[u8]) -> Signature
pub fn sign(&self, message: &[u8]) -> Signature
Signs message, hashing it with Kupyna-256 and deriving the ephemeral nonce
deterministically (see the module doc, docs/DECISIONS.md D-46). A thin wrapper over
Self::sign_digest - see that method, and the module doc’s T-113 note, for signing a
message too large to hold in memory whole.
Sourcepub fn sign_digest(&self, digest: &[u8; 32]) -> Signature
pub fn sign_digest(&self, digest: &[u8; 32]) -> Signature
Signs an already-computed 32-byte Kupyna-256 digest directly - for messages hashed
incrementally via hazmat::kupyna::Kupyna256Hasher rather than held whole in memory (see
the module doc’s T-113 note). The hazmat-level degenerate rejections (F_e == 0, r == 0,
s == 0, each ~2^-163) are retried here with the next nonce-derivation counter rather
than surfaced to the caller - safe to retry because the nonce is re-derived, not reused.