p521/ecdsa.rs
1//! Elliptic Curve Digital Signature Algorithm (ECDSA)
2//!
3//! This module contains support for computing and verifying ECDSA signatures.
4//! To use it, you will need to enable one of the two following Cargo features:
5//!
6//! - `ecdsa-core`: provides only the [`Signature`] type (which represents an
7//! ECDSA/P-521 signature). Does not require the `arithmetic` feature. This is
8//! useful for 3rd-party crates which wish to use the `Signature` type for
9//! interoperability purposes (particularly in conjunction with the
10//! [`signature::Signer`] trait. Example use cases for this include other
11//! software implementations of ECDSA/P-521 and wrappers for cloud KMS
12//! services or hardware devices (HSM or crypto hardware wallet).
13//! - `ecdsa`: provides `ecdsa-core` features plus the [`SigningKey`] and
14//! [`VerifyingKey`] types which natively implement ECDSA/P-521 signing and
15//! verification.
16//!
17//! ## Signing/Verification Example
18//!
19#![cfg_attr(all(feature = "ecdsa", feature = "getrandom"), doc = "```")]
20#![cfg_attr(not(all(feature = "ecdsa", feature = "getrandom")), doc = "```ignore")]
21//! # fn main() -> Result<(), Box<dyn core::error::Error>> {
22//! // NOTE: requires the `ecdsa` and `getrandom` crate features are enabled
23//! use p521::{
24//! ecdsa::{SigningKey, Signature, signature::Signer},
25//! elliptic_curve::Generate,
26//! SecretKey,
27//! };
28//!
29//! // Signing
30//! let signing_key = SigningKey::generate(); // Serialize with `::to_bytes()`
31//! let verifying_key_bytes = signing_key.verifying_key().to_sec1_point(false); // 133-bytes
32//!
33//! let message = b"ECDSA proves knowledge of a secret number in the context of a single message";
34//! let signature: Signature = signing_key.sign(message);
35//!
36//! // Verification
37//! use p521::{Sec1Point, ecdsa::{VerifyingKey, signature::Verifier}};
38//!
39//! let verifying_key = VerifyingKey::from_sec1_bytes(verifying_key_bytes.as_ref())?;
40//! verifying_key.verify(message, &signature)?;
41//! # Ok(())
42//! # }
43//! ```
44
45pub use ecdsa_core::signature::{self, Error};
46
47use super::NistP521;
48use ecdsa_core::EcdsaCurve;
49
50/// ECDSA/P-521 signature (fixed-size)
51pub type Signature = ecdsa_core::Signature<NistP521>;
52
53/// ECDSA/P-521 signature (ASN.1 DER encoded)
54pub type DerSignature = ecdsa_core::der::Signature<NistP521>;
55
56impl EcdsaCurve for NistP521 {
57 const NORMALIZE_S: bool = false;
58}
59
60/// ECDSA/P-521 signing key
61#[cfg(feature = "ecdsa")]
62pub type SigningKey = ecdsa_core::SigningKey<NistP521>;
63
64/// ECDSA/P-521 verification key (i.e. public key)
65#[cfg(feature = "ecdsa")]
66pub type VerifyingKey = ecdsa_core::VerifyingKey<NistP521>;
67
68#[cfg(feature = "sha512")]
69impl ecdsa_core::hazmat::DigestAlgorithm for NistP521 {
70 type Digest = sha2::Sha512;
71}
72
73#[cfg(all(test, feature = "ecdsa"))]
74mod tests {
75 use crate::ecdsa::{Signature, SigningKey, signature::Signer};
76 use hex_literal::hex;
77
78 // Test vector from RFC 6979 Appendix 2.7 (NIST P-521 + SHA-512)
79 // <https://datatracker.ietf.org/doc/html/rfc6979#appendix-A.2.7>
80 // TODO(tarcieri): debug why this is failing
81 #[test]
82 fn rfc6979() {
83 let x = hex!(
84 "00FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538"
85 );
86 let signer = SigningKey::from_bytes(&x.into()).unwrap();
87 let signature: Signature = signer.sign(b"sample");
88 assert_eq!(
89 signature.to_bytes().as_slice(),
90 &hex!(
91 "00C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA"
92 "00617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A"
93 )
94 );
95 }
96
97 mod sign {
98 use crate::{NistP521, test_vectors::ecdsa::ECDSA_TEST_VECTORS};
99 ecdsa_core::new_signing_test!(NistP521, ECDSA_TEST_VECTORS);
100 }
101
102 mod verify {
103 use crate::{NistP521, test_vectors::ecdsa::ECDSA_TEST_VECTORS};
104 ecdsa_core::new_verification_test!(NistP521, ECDSA_TEST_VECTORS);
105 }
106
107 mod wycheproof {
108 use crate::NistP521;
109 ecdsa_core::new_wycheproof_test!(wycheproof, "wycheproof", NistP521);
110 }
111}