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