did_method_plc/
keypair.rs

1use crate::multicodec::MultiEncoded;
2use crate::PLCError;
3use ecdsa::elliptic_curve::sec1::ToEncodedPoint;
4use ecdsa::signature::{SignerMut, Verifier};
5use serde::{Deserialize, Serialize};
6#[cfg(feature = "jwt")]
7use jwt::{SigningAlgorithm, VerifyingAlgorithm};
8#[cfg(feature = "jwt")]
9use base64::Engine;
10
11pub enum BlessedAlgorithm {
12    P256,
13    K256,
14}
15
16impl BlessedAlgorithm {
17    pub fn codec(&self) -> u64 {
18        match self {
19            Self::P256 => 0x1200,
20            Self::K256 => 0xe7,
21        }
22    }
23
24    pub fn prefix(&self) -> [u8; 2] {
25        match self {
26            Self::P256 => [0x80, 0x24],
27            Self::K256 => [0xe7, 0x01],
28        }
29    }
30}
31
32impl From<u64> for BlessedAlgorithm {
33    fn from(value: u64) -> Self {
34        match value {
35            0x1200 => Self::P256,
36            0xe7 => Self::K256,
37            _ => panic!("Unknown algorithm"),
38        }
39    }
40}
41
42#[derive(Clone, Serialize, Deserialize)]
43pub struct Keypair {
44    pub public: Option<Vec<u8>>,
45    pub secret: Option<Vec<u8>>,
46    pub codec: u64,
47}
48
49impl Keypair {
50    pub fn generate(algo: BlessedAlgorithm) -> Self {
51        match algo {
52            BlessedAlgorithm::P256 => {
53                let sk = p256::ecdsa::SigningKey::random(&mut rand::thread_rng());
54                let vk = sk.verifying_key();
55                Keypair {
56                    public: Some(vk.to_sec1_bytes().to_vec()),
57                    secret: Some(sk.to_bytes().to_vec()),
58                    codec: algo.codec(),
59                }
60            }
61            BlessedAlgorithm::K256 => {
62                let sk = k256::ecdsa::SigningKey::random(&mut rand::thread_rng());
63                let vk = sk.verifying_key();
64                Keypair {
65                    public: Some(vk.to_sec1_bytes().to_vec()),
66                    secret: Some(sk.to_bytes().to_vec()),
67                    codec: algo.codec(),
68                }
69            }
70        }
71    }
72
73    pub fn from_value(value: serde_json::Value) -> Result<Self, PLCError> {
74        let keypair: Keypair =
75            serde_json::from_value(value).map_err(|e| PLCError::Other(e.into()))?;
76        Ok(keypair)
77    }
78
79    pub fn from_did_key(key: &str) -> Result<Self, PLCError> {
80        if !key.starts_with("did:key:") {
81            return Err(PLCError::InvalidKey);
82        }
83        let key = key.split_at(8).1;
84        let (_base, data) = multibase::decode(key).map_err(|_| PLCError::InvalidKey)?;
85        let decoded_result =
86            MultiEncoded::new(data.as_slice()).map_err(|_| PLCError::InvalidKey)?;
87
88        Ok(Keypair {
89            public: Some(decoded_result.data().to_vec()),
90            secret: None,
91            codec: decoded_result.codec(),
92        })
93    }
94
95    pub fn to_did_key(&self) -> Result<String, PLCError> {
96        if self.public.is_none() {
97            return Err(PLCError::InvalidKey);
98        }
99        let algo = BlessedAlgorithm::from(self.codec);
100
101        match algo {
102            BlessedAlgorithm::P256 => {
103                let pk = p256::PublicKey::from_sec1_bytes(self.public.as_ref().unwrap().as_slice())
104                    .map_err(|e| PLCError::Other(e.into()))?;
105                let key = multibase::encode(
106                    multibase::Base::Base58Btc,
107                    [
108                        algo.prefix().to_vec(),
109                        pk.to_encoded_point(true).as_bytes().to_vec(),
110                    ]
111                    .concat(),
112                );
113                Ok(format!("did:key:{}", key))
114            }
115            BlessedAlgorithm::K256 => {
116                let pk = k256::PublicKey::from_sec1_bytes(self.public.as_ref().unwrap().as_slice())
117                    .map_err(|e| PLCError::Other(e.into()))?;
118                let vk = k256::ecdsa::VerifyingKey::from(pk);
119                let key = multibase::encode(
120                    multibase::Base::Base58Btc,
121                    [algo.prefix().to_vec(), vk.to_sec1_bytes().to_vec()].concat(),
122                );
123                Ok(format!("did:key:{}", key))
124            }
125        }
126    }
127
128    pub fn from_private_key(key: &str) -> Result<Self, PLCError> {
129        let (_base, data) = multibase::decode(key).map_err(|e| PLCError::Other(e.into()))?;
130        let decoded_result =
131            MultiEncoded::new(data.as_slice()).map_err(|e| PLCError::Other(e.into()))?;
132
133        match decoded_result.codec() {
134            0xe7 => {
135                // Secp256k1
136                let sk = k256::ecdsa::SigningKey::from_bytes(decoded_result.data().into())
137                    .map_err(|e| PLCError::Other(e.into()))?;
138                let vk = sk.verifying_key();
139                Ok(Keypair {
140                    public: Some(vk.to_sec1_bytes().to_vec()),
141                    secret: Some(decoded_result.data().to_vec()),
142                    codec: decoded_result.codec(),
143                })
144            }
145            0x1200 => {
146                // P-256
147                let sk = p256::ecdsa::SigningKey::from_bytes(decoded_result.data().into())
148                    .map_err(|e| PLCError::Other(e.into()))?;
149                let vk = sk.verifying_key();
150                Ok(Keypair {
151                    public: Some(vk.to_sec1_bytes().to_vec()),
152                    secret: Some(decoded_result.data().to_vec()),
153                    codec: decoded_result.codec(),
154                })
155            }
156            _ => Err(PLCError::MalformedKey),
157        }
158    }
159
160    pub fn to_private_key(&self) -> Result<String, PLCError> {
161        if self.secret.is_none() {
162            return Err(PLCError::InvalidKey);
163        }
164        let algo = BlessedAlgorithm::from(self.codec);
165        match algo {
166            BlessedAlgorithm::P256 => {
167                let key = multibase::encode(
168                    multibase::Base::Base58Btc,
169                    [algo.prefix().to_vec(), self.secret.clone().unwrap()].concat(),
170                );
171                Ok(key)
172            }
173            BlessedAlgorithm::K256 => {
174                let key = multibase::encode(
175                    multibase::Base::Base58Btc,
176                    [algo.prefix().to_vec(), self.secret.clone().unwrap()].concat(),
177                );
178                Ok(key)
179            }
180        }
181    }
182
183    pub fn verify(&self, msg: &[u8], sig: &[u8]) -> Result<bool, PLCError> {
184        match self.codec {
185            0xe7 => {
186                // Secp256k1
187                let vk = k256::ecdsa::VerifyingKey::from_sec1_bytes(
188                    self.public.as_ref().unwrap().as_slice(),
189                )
190                .map_err(|_| PLCError::InvalidKey)?;
191                let sig = k256::ecdsa::Signature::from_slice(sig.into())
192                    .map_err(|_| PLCError::InvalidSignature)?;
193                if vk.verify(&msg, &sig).is_ok() {
194                    return Ok(true);
195                }
196            }
197            0x1200 => {
198                // P-256
199                let vk = p256::ecdsa::VerifyingKey::from_sec1_bytes(
200                    self.public.as_ref().unwrap().as_slice(),
201                )
202                .map_err(|_| PLCError::InvalidKey)?;
203                let sig = p256::ecdsa::Signature::from_slice(sig.into())
204                    .map_err(|_| PLCError::InvalidSignature)?;
205                if vk.verify(&msg, &sig).is_ok() {
206                    return Ok(true);
207                }
208            }
209            _ => (),
210        }
211        Ok(false)
212    }
213
214    pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, PLCError> {
215        match self.codec {
216            0xe7 => {
217                // Secp256k1
218                let mut sk = k256::ecdsa::SigningKey::from_bytes(
219                    self.secret.as_ref().unwrap().as_slice().into(),
220                )
221                .map_err(|e| PLCError::Other(e.into()))?;
222                let sig: k256::ecdsa::Signature = sk.sign(&msg);
223                Ok(sig.to_bytes().to_vec())
224            }
225            0x1200 => {
226                // P-256
227                let mut sk = p256::ecdsa::SigningKey::from_bytes(
228                    self.secret.as_ref().unwrap().as_slice().into(),
229                )
230                    .map_err(|e| PLCError::Other(e.into()))?;
231                let sig: p256::ecdsa::Signature = sk.sign(&msg);
232                match sig.normalize_s() {
233                    Some(sig) => Ok(sig.to_bytes().to_vec()),
234                    None => {
235                        Ok(sig.to_bytes().to_vec())
236                    }
237                }
238            }
239            _ => Err(PLCError::InvalidKey),
240        }
241    }
242}
243
244#[cfg(feature = "jwt")]
245impl SigningAlgorithm for Keypair {
246    fn sign(&self, header: &str, claims: &str) -> Result<String, jwt::Error> {
247        let mut msg = vec![];
248        msg.extend_from_slice(header.as_bytes());
249        msg.extend_from_slice(b".");
250        msg.extend_from_slice(claims.as_bytes());
251        let sig = self.sign(msg.as_slice()).map_err(|_| jwt::Error::InvalidSignature)?;
252        let engine = base64::engine::general_purpose::STANDARD;
253        Ok(engine.encode(sig))
254    }
255
256    fn algorithm_type(&self) -> jwt::AlgorithmType {
257        match BlessedAlgorithm::from(self.codec) {
258            BlessedAlgorithm::P256 => jwt::AlgorithmType::Es256,
259            BlessedAlgorithm::K256 => jwt::AlgorithmType::None
260        }
261    }
262}
263
264#[cfg(feature = "jwt")]
265impl VerifyingAlgorithm for Keypair {
266    fn algorithm_type(&self) -> jwt::AlgorithmType {
267        match BlessedAlgorithm::from(self.codec) {
268            BlessedAlgorithm::P256 => jwt::AlgorithmType::Es256,
269            BlessedAlgorithm::K256 => jwt::AlgorithmType::None
270        }
271    }
272
273    fn verify_bytes(&self, header: &str, claims: &str, signature: &[u8]) -> Result<bool, jwt::Error> {
274        let engine = base64::engine::general_purpose::STANDARD;
275        let signature = engine.decode(signature).map_err(|_| jwt::Error::InvalidSignature)?;
276        let mut msg = vec![];
277        msg.extend_from_slice(header.as_bytes());
278        msg.extend_from_slice(b".");
279        msg.extend_from_slice(claims.as_bytes());
280        self.verify(msg.as_slice(), signature.as_slice()).map_err(|_| jwt::Error::InvalidSignature)
281    }
282}
283
284#[cfg(test)]
285mod test {
286    use super::*;
287
288    #[test]
289    fn test_keypair_p256() {
290        let keypair = Keypair::generate(BlessedAlgorithm::P256);
291        assert!(keypair.public.is_some());
292        assert!(keypair.secret.is_some());
293        assert_eq!(keypair.codec, 0x1200);
294        assert!(keypair.to_did_key().unwrap().starts_with("did:key:zDn"));
295    }
296
297    #[test]
298    fn test_keypair_k256() {
299        let keypair = Keypair::generate(BlessedAlgorithm::K256);
300        assert!(keypair.public.is_some());
301        assert!(keypair.secret.is_some());
302        assert_eq!(keypair.codec, 0xe7);
303        assert!(keypair.to_did_key().unwrap().starts_with("did:key:zQ3s"));
304    }
305
306    #[test]
307    fn test_keypair_from_did_key_p256() {
308        let orig_keypair = Keypair::generate(BlessedAlgorithm::P256);
309        let did_key = orig_keypair.to_did_key().unwrap();
310        let keypair = Keypair::from_did_key(&did_key).unwrap();
311        assert_eq!(
312            keypair.to_did_key().unwrap(),
313            orig_keypair.to_did_key().unwrap()
314        );
315        assert_eq!(keypair.codec, orig_keypair.codec);
316    }
317
318    #[test]
319    fn test_keypair_from_did_key_k256() {
320        let orig_keypair = Keypair::generate(BlessedAlgorithm::K256);
321        let did_key = orig_keypair.to_did_key().unwrap();
322        let keypair = Keypair::from_did_key(&did_key).unwrap();
323        assert_eq!(
324            keypair.to_did_key().unwrap(),
325            orig_keypair.to_did_key().unwrap()
326        );
327        assert_eq!(keypair.codec, orig_keypair.codec);
328    }
329
330    #[test]
331    fn test_keypair_to_did_key() {
332        let keypair =
333            Keypair::from_did_key("did:key:zQ3shhCGUqDKjStzuDxPkTxN6ujddP4RkEKJJouJGRRkaLGbg");
334        assert!(keypair.is_ok());
335        assert_eq!(
336            keypair.unwrap().to_did_key().unwrap(),
337            "did:key:zQ3shhCGUqDKjStzuDxPkTxN6ujddP4RkEKJJouJGRRkaLGbg"
338        );
339    }
340
341    #[test]
342    fn test_keypair_from_private_key_p256() {
343        let orig_keypair = Keypair::generate(BlessedAlgorithm::P256);
344        let private_key = orig_keypair.to_private_key().unwrap();
345        let keypair = Keypair::from_private_key(&private_key).unwrap();
346        assert_eq!(
347            keypair.to_did_key().unwrap(),
348            orig_keypair.to_did_key().unwrap()
349        );
350        assert_eq!(keypair.codec, orig_keypair.codec);
351    }
352
353    #[test]
354    fn test_keypair_from_private_key_k256() {
355        let orig_keypair = Keypair::generate(BlessedAlgorithm::K256);
356        let private_key = orig_keypair.to_private_key().unwrap();
357        let keypair = Keypair::from_private_key(&private_key).unwrap();
358        assert_eq!(
359            keypair.to_did_key().unwrap(),
360            orig_keypair.to_did_key().unwrap()
361        );
362        assert_eq!(keypair.codec, orig_keypair.codec);
363    }
364
365    #[test]
366    fn test_keypair_to_private_key_p256() {
367        let orig_keypair = Keypair::generate(BlessedAlgorithm::P256);
368        let private_key = orig_keypair.to_private_key().unwrap();
369        let keypair = Keypair::from_private_key(&private_key).unwrap();
370        assert_eq!(orig_keypair.secret.unwrap(), keypair.secret.unwrap());
371    }
372
373    #[test]
374    fn test_keypair_to_private_key_k256() {
375        let orig_keypair = Keypair::generate(BlessedAlgorithm::K256);
376        let private_key = orig_keypair.to_private_key().unwrap();
377        let keypair = Keypair::from_private_key(&private_key).unwrap();
378        assert_eq!(orig_keypair.secret.unwrap(), keypair.secret.unwrap());
379    }
380
381    #[cfg(feature = "jwt")]
382    #[test]
383    fn test_keypair_jwt() {
384        let keypair = Keypair::generate(BlessedAlgorithm::P256);
385        let header = "{\"alg\":\"ES256\",\"typ\":\"JWT\"}";
386        let claims = "{\"iss\":\"me\"}";
387        let sig = SigningAlgorithm::sign(&keypair, header, claims);
388        assert!(sig.is_ok(), "JWT should be signed correctly: {:?}", sig.err().unwrap());
389
390        let sig = sig.unwrap();
391        let res = keypair.verify_bytes(header, claims, sig.as_bytes());
392        assert!(res.is_ok(), "JWT sig should be valid: {:?}", res.err().unwrap());
393    }
394}