Skip to main content

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}