xdid_method_key/keys/
p384.rs1use jose_jwk::Jwk;
2use p256::{
3 elliptic_curve::{rand_core::OsRng, zeroize::Zeroizing},
4 pkcs8::{DecodePrivateKey, LineEnding},
5};
6use p384::{
7 SecretKey,
8 elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint},
9 pkcs8::EncodePrivateKey,
10};
11use ring::{
12 rand::SystemRandom,
13 signature::{ECDSA_P384_SHA384_ASN1_SIGNING, EcdsaKeyPair},
14};
15
16use super::{DidKeyPair, KeyParser, Multicodec, PublicKey, Signer, WithMulticodec};
17
18#[derive(Clone, PartialEq, Eq)]
19pub struct P384KeyPair(SecretKey);
20
21impl DidKeyPair for P384KeyPair {
22 fn generate() -> Self {
23 let mut rng = OsRng;
24 let secret = SecretKey::random(&mut rng);
25 Self(secret)
26 }
27
28 fn public(&self) -> impl PublicKey {
29 P384PublicKey(self.0.public_key())
30 }
31
32 fn to_pkcs8_pem(&self) -> anyhow::Result<Zeroizing<String>> {
33 let pem = self.0.to_pkcs8_pem(LineEnding::LF)?;
34 Ok(pem)
35 }
36 fn from_pkcs8_pem(pem: &str) -> anyhow::Result<Self> {
37 let key = SecretKey::from_pkcs8_pem(pem)?;
38 Ok(Self(key))
39 }
40}
41
42impl Signer for P384KeyPair {
43 fn sign(&self, message: &[u8]) -> anyhow::Result<Vec<u8>> {
44 let rng = SystemRandom::new();
45
46 let signer = EcdsaKeyPair::from_private_key_and_public_key(
47 &ECDSA_P384_SHA384_ASN1_SIGNING,
48 &self.0.to_bytes(),
49 &self.0.public_key().to_sec1_bytes(),
50 &rng,
51 )
52 .map_err(|_| anyhow::anyhow!("failed to create key pair from private key"))?;
53
54 signer
55 .sign(&rng, message)
56 .map(|v| v.as_ref().to_vec())
57 .map_err(|_| anyhow::anyhow!("signing failed"))
58 }
59}
60
61#[derive(Clone, PartialEq, Eq)]
62struct P384PublicKey(p384::PublicKey);
63
64impl PublicKey for P384PublicKey {
65 fn to_sec1_bytes(&self) -> Box<[u8]> {
66 self.0.to_sec1_bytes()
67 }
68 fn to_encoded_point_bytes(&self) -> Box<[u8]> {
69 self.0.to_encoded_point(true).as_bytes().into()
70 }
71
72 fn to_jwk(&self) -> Jwk {
73 let jwk_str = self.0.to_jwk_string();
74 serde_json::from_str(&jwk_str).expect("p384 crate guarantees valid JWK")
75 }
76}
77
78impl WithMulticodec for P384PublicKey {
79 fn codec(&self) -> Box<dyn Multicodec> {
80 Box::new(P384Codec)
81 }
82}
83
84pub(crate) struct P384KeyParser;
85
86impl KeyParser for P384KeyParser {
87 fn parse(&self, public_key: Vec<u8>) -> Result<Box<dyn PublicKey>, crate::parser::ParseError> {
88 let point = p384::EncodedPoint::from_bytes(public_key)
89 .map_err(|_| crate::parser::ParseError::InvalidPublicKey)?;
90 let key = p384::PublicKey::from_encoded_point(&point)
91 .into_option()
92 .ok_or(crate::parser::ParseError::InvalidPublicKey)?;
93 Ok(Box::new(P384PublicKey(key)))
94 }
95}
96
97impl WithMulticodec for P384KeyParser {
98 fn codec(&self) -> Box<dyn Multicodec> {
99 Box::new(P384Codec)
100 }
101}
102
103struct P384Codec;
104
105impl Multicodec for P384Codec {
106 fn code_u64(&self) -> u64 {
107 0x1201
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use ring::signature::{ECDSA_P384_SHA384_ASN1, VerificationAlgorithm};
114
115 use crate::parser::DidKeyParser;
116
117 use super::*;
118
119 #[test]
120 fn test_display() {
121 let pair = P384KeyPair::generate();
122 let did = pair.public().to_did();
123
124 let did_str = did.to_string();
125 println!("{did_str}");
126 assert!(did_str.starts_with("did:key:z82"));
127 }
128
129 #[test]
130 fn test_jwk() {
131 let pair = P384KeyPair::generate();
132 let _ = pair.public().to_jwk();
133 }
134
135 #[test]
136 fn test_parse() {
137 let pair = P384KeyPair::generate();
138 let did = pair.public().to_did();
139
140 let parser = DidKeyParser::default();
141 let _ = parser.parse(&did).expect("parse should succeed");
142 }
143
144 #[test]
145 fn test_sign() {
146 let pair = P384KeyPair::generate();
147
148 let msg = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
149 let signature = pair.sign(&msg).expect("signing should succeed");
150
151 assert!(
152 ECDSA_P384_SHA384_ASN1
153 .verify(
154 pair.public().to_sec1_bytes().as_ref().into(),
155 msg.as_slice().into(),
156 signature.as_slice().into()
157 )
158 .is_ok()
159 );
160 }
161}