Skip to main content

xdid_method_key/keys/
p384.rs

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