1use const_oid::AssociatedOid;
4use elliptic_curve::sec1::ToEncodedPoint;
5use signature::rand_core::OsRng;
6
7use crate::{PublicKeyAlgorithm, Signature};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum EcdsaAlgorithm {
12 P256,
14}
15
16impl EcdsaAlgorithm {
17 pub(crate) fn random(&self) -> EcdsaSigningKey {
18 match self {
19 EcdsaAlgorithm::P256 => {
20 EcdsaSigningKey::P256(::elliptic_curve::SecretKey::random(&mut OsRng))
21 }
22 }
23 }
24}
25
26pub(crate) enum EcdsaSigningKey {
29 P256(::elliptic_curve::SecretKey<p256::NistP256>),
30}
31
32impl signature::Signer<Signature> for EcdsaSigningKey {
33 fn try_sign(&self, msg: &[u8]) -> Result<Signature, ::ecdsa::Error> {
34 match self {
35 EcdsaSigningKey::P256(key) => {
36 let signature = <::ecdsa::SigningKey<p256::NistP256> as signature::Signer<
37 ::ecdsa::Signature<p256::NistP256>,
38 >>::sign(&key.into(), msg);
39 let bytes = signature.to_vec();
40 Ok(Signature(bytes))
41 }
42 }
43 }
44}
45
46impl pkcs8::EncodePrivateKey for EcdsaSigningKey {
47 fn to_pkcs8_der(&self) -> pkcs8::Result<der::SecretDocument> {
48 match self {
49 EcdsaSigningKey::P256(key) => key.to_pkcs8_der(),
50 }
51 }
52}
53
54impl crate::SigningKeyAlgorithm for EcdsaSigningKey {
55 fn as_jwk(&self) -> crate::jwk::Jwk {
56 match self {
57 EcdsaSigningKey::P256(key) => key.public_key().to_jwk().into(),
58 }
59 }
60
61 fn public_key(&self) -> crate::PublicKey {
62 match self {
63 EcdsaSigningKey::P256(key) => Box::new(EcdsaPublicKey::from(key.public_key())).into(),
64 }
65 }
66
67 fn try_sign_digest(&self, digest: sha2::Sha256) -> Result<Signature, ecdsa::Error> {
68 match self {
69 EcdsaSigningKey::P256(key) => {
70 let signature = <::ecdsa::SigningKey<p256::NistP256> as signature::DigestSigner<
71 sha2::Sha256,
72 ::ecdsa::Signature<p256::NistP256>,
73 >>::try_sign_digest(&key.into(), digest)?;
74 let bytes = signature.to_vec();
75 Ok(Signature(bytes))
76 }
77 }
78 }
79
80 fn algorithm(&self) -> pkcs8::AlgorithmIdentifier {
81 match self {
82 EcdsaSigningKey::P256(_) => pkcs8::AlgorithmIdentifier {
83 oid: const_oid::db::rfc5912::ECDSA_WITH_SHA_256,
84 parameters: None,
85 },
86 }
87 }
88
89 fn kind(&self) -> crate::SignatureKind {
90 match self {
91 EcdsaSigningKey::P256(_) => crate::SignatureKind::Ecdsa(crate::EcdsaAlgorithm::P256),
92 }
93 }
94}
95
96impl EcdsaSigningKey {
97 pub(crate) fn from_pkcs8_pem(
98 data: &str,
99 algorithm: EcdsaAlgorithm,
100 ) -> Result<Self, pkcs8::Error> {
101 use pkcs8::DecodePrivateKey;
102 match algorithm {
103 EcdsaAlgorithm::P256 => Ok(EcdsaSigningKey::P256(
104 ::elliptic_curve::SecretKey::from_pkcs8_pem(data)?,
105 )),
106 }
107 }
108}
109
110enum EcdsaPublicKey {
111 P256(elliptic_curve::PublicKey<p256::NistP256>),
112}
113
114impl From<elliptic_curve::PublicKey<p256::NistP256>> for EcdsaPublicKey {
115 fn from(value: elliptic_curve::PublicKey<p256::NistP256>) -> Self {
116 EcdsaPublicKey::P256(value)
117 }
118}
119
120impl PublicKeyAlgorithm for EcdsaPublicKey {
121 fn as_jwk(&self) -> crate::jwk::Jwk {
122 match self {
123 EcdsaPublicKey::P256(key) => key.to_jwk().into(),
124 }
125 }
126
127 fn algorithm(&self) -> pkcs8::AlgorithmIdentifier {
128 match self {
129 EcdsaPublicKey::P256(_) => pkcs8::AlgorithmIdentifier {
130 oid: const_oid::db::rfc5912::ID_EC_PUBLIC_KEY,
131 parameters: Some((&p256::NistP256::OID).into()),
132 },
133 }
134 }
135
136 fn as_bytes(&self) -> Vec<u8> {
137 match self {
138 EcdsaPublicKey::P256(key) => key.to_encoded_point(false).as_ref().into(),
139 }
140 }
141}