Skip to main content

crypto_dispatch/algorithms/
p521.rs

1// SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2//
3// SPDX-License-Identifier: Apache-2.0
4
5#![allow(clippy::needless_return)]
6
7use crate::traits::SignatureAlgorithm;
8use crate::AlgorithmError;
9use crypto_core::Algorithm;
10use zeroize::Zeroizing;
11
12/// NIST P-521 (secp521r1) signature adapter.
13pub struct P521Algo;
14
15impl SignatureAlgorithm for P521Algo {
16    const ALG: Algorithm = Algorithm::P521;
17
18    fn generate_keypair() -> Result<(Vec<u8>, Zeroizing<Vec<u8>>), AlgorithmError> {
19        #[cfg(any(feature = "native", all(feature = "wasm", target_arch = "wasm32")))]
20        {
21            return crate::algorithms::KeypairResultExt::into_algorithm_keypair(
22                crypto_p521::generate_p521_keypair(),
23                Self::ALG,
24            );
25        }
26
27        #[cfg(not(any(feature = "native", all(feature = "wasm", target_arch = "wasm32"))))]
28        {
29            Err(AlgorithmError::UnsupportedAlgorithm(Self::ALG))
30        }
31    }
32
33    fn sign(secret: &[u8], msg: &[u8]) -> Result<Vec<u8>, AlgorithmError> {
34        #[cfg(any(feature = "native", all(feature = "wasm", target_arch = "wasm32")))]
35        {
36            return crypto_p521::sign_p521_der_prehash(secret, msg).map_err(AlgorithmError::from);
37        }
38
39        #[cfg(not(any(feature = "native", all(feature = "wasm", target_arch = "wasm32"))))]
40        {
41            let _ = (secret, msg);
42            Err(AlgorithmError::UnsupportedAlgorithm(Self::ALG))
43        }
44    }
45
46    fn verify(public: &[u8], msg: &[u8], sig: &[u8]) -> Result<(), AlgorithmError> {
47        #[cfg(any(feature = "native", all(feature = "wasm", target_arch = "wasm32")))]
48        {
49            return crypto_p521::verify_p521_der_prehash(sig, msg, public)
50                .map_err(|error| crate::algorithms::map_verify_error(Self::ALG, error));
51        }
52
53        #[cfg(not(any(feature = "native", all(feature = "wasm", target_arch = "wasm32"))))]
54        {
55            let _ = (public, msg, sig);
56            Err(AlgorithmError::UnsupportedAlgorithm(Self::ALG))
57        }
58    }
59}
60
61impl P521Algo {
62    /// Derive the P-521 ECDH shared secret; the returned value zeroizes on
63    /// drop and must be passed through a protocol KDF before key use.
64    pub fn derive_shared_secret(
65        secret_key: &[u8],
66        public_key: &[u8],
67    ) -> Result<Zeroizing<Vec<u8>>, AlgorithmError> {
68        #[cfg(any(feature = "native", all(feature = "wasm", target_arch = "wasm32")))]
69        {
70            return crypto_p521::derive_p521_shared_secret(secret_key, public_key)
71                .map_err(AlgorithmError::from);
72        }
73
74        #[cfg(not(any(feature = "native", all(feature = "wasm", target_arch = "wasm32"))))]
75        {
76            let _ = (secret_key, public_key);
77            Err(AlgorithmError::UnsupportedAlgorithm(Self::ALG))
78        }
79    }
80}