1use ed25519_dalek::{Signer, SigningKey as Ed25519SigningKey, VerifyingKey};
2use rand_core::OsRng;
3use x25519_dalek::{PublicKey as X25519PublicKey, StaticSecret};
4
5use crate::{
6 did::Did,
7 error::{MaError, Result},
8 multiformat::{public_key_multibase_decode, public_key_multibase_encode},
9};
10
11pub const ASSERTION_METHOD_KEY_TYPE: &str = "Multikey";
12pub const KEY_AGREEMENT_KEY_TYPE: &str = "Multikey";
13
14pub const X25519_PUB_CODEC: u64 = 0xec;
16pub const ED25519_PUB_CODEC: u64 = 0xed;
17pub const EDDSA_SIG_CODEC: u64 = 0xd0ed;
18
19#[derive(Clone)]
39pub struct SigningKey {
40 pub did: Did,
41 pub key_type: String,
42 signing_key: Ed25519SigningKey,
43 pub public_key_multibase: String,
44}
45
46impl SigningKey {
47 pub fn generate(did: Did) -> Result<Self> {
48 let signing_key = Ed25519SigningKey::generate(&mut OsRng);
49 let public_key_multibase =
50 public_key_multibase_encode(ED25519_PUB_CODEC, signing_key.verifying_key().as_bytes())?;
51
52 Ok(Self {
53 did,
54 key_type: ASSERTION_METHOD_KEY_TYPE.to_string(),
55 signing_key,
56 public_key_multibase,
57 })
58 }
59
60 pub fn sign(&self, data: &[u8]) -> Vec<u8> {
61 self.signing_key.sign(data).to_bytes().to_vec()
62 }
63
64 pub fn verifying_key(&self) -> VerifyingKey {
65 self.signing_key.verifying_key()
66 }
67
68 pub fn private_key_bytes(&self) -> [u8; ed25519_dalek::SECRET_KEY_LENGTH] {
69 self.signing_key.to_bytes()
70 }
71
72 pub fn from_private_key_bytes(
73 did: Did,
74 private_key: [u8; ed25519_dalek::SECRET_KEY_LENGTH],
75 ) -> Result<Self> {
76 let signing_key = Ed25519SigningKey::from_bytes(&private_key);
77 let public_key_multibase =
78 public_key_multibase_encode(ED25519_PUB_CODEC, signing_key.verifying_key().as_bytes())?;
79
80 Ok(Self {
81 did,
82 key_type: ASSERTION_METHOD_KEY_TYPE.to_string(),
83 signing_key,
84 public_key_multibase,
85 })
86 }
87
88 pub fn validate(&self) -> Result<()> {
89 Did::validate(&self.did.id())?;
90
91 if self.key_type != ASSERTION_METHOD_KEY_TYPE {
92 return Err(MaError::InvalidKeyType);
93 }
94
95 let (codec, key_bytes) = public_key_multibase_decode(&self.public_key_multibase)?;
96 if codec != ED25519_PUB_CODEC {
97 return Err(MaError::InvalidMulticodec {
98 expected: ED25519_PUB_CODEC,
99 actual: codec,
100 });
101 }
102
103 if key_bytes.len() != ed25519_dalek::PUBLIC_KEY_LENGTH {
104 return Err(MaError::InvalidKeyLength {
105 expected: ed25519_dalek::PUBLIC_KEY_LENGTH,
106 actual: key_bytes.len(),
107 });
108 }
109
110 Ok(())
111 }
112}
113
114#[derive(Clone)]
134pub struct EncryptionKey {
135 pub did: Did,
136 pub key_type: String,
137 private_key: StaticSecret,
138 pub public_key: X25519PublicKey,
139 pub public_key_multibase: String,
140}
141
142impl EncryptionKey {
143 pub fn generate(did: Did) -> Result<Self> {
144 let private_key = StaticSecret::random_from_rng(OsRng);
145 let public_key = X25519PublicKey::from(&private_key);
146 let public_key_multibase =
147 public_key_multibase_encode(X25519_PUB_CODEC, public_key.as_bytes())?;
148
149 Ok(Self {
150 did,
151 key_type: KEY_AGREEMENT_KEY_TYPE.to_string(),
152 private_key,
153 public_key,
154 public_key_multibase,
155 })
156 }
157
158 pub fn shared_secret(&self, other: &X25519PublicKey) -> [u8; 32] {
159 self.private_key.diffie_hellman(other).to_bytes()
160 }
161
162 pub fn private_key_bytes(&self) -> [u8; 32] {
163 self.private_key.to_bytes()
164 }
165
166 pub fn from_private_key_bytes(did: Did, private_key: [u8; 32]) -> Result<Self> {
167 let private_key = StaticSecret::from(private_key);
168 let public_key = X25519PublicKey::from(&private_key);
169 let public_key_multibase =
170 public_key_multibase_encode(X25519_PUB_CODEC, public_key.as_bytes())?;
171
172 Ok(Self {
173 did,
174 key_type: KEY_AGREEMENT_KEY_TYPE.to_string(),
175 private_key,
176 public_key,
177 public_key_multibase,
178 })
179 }
180
181 pub fn validate(&self) -> Result<()> {
182 Did::validate(&self.did.id())?;
183
184 if self.key_type != KEY_AGREEMENT_KEY_TYPE {
185 return Err(MaError::InvalidKeyType);
186 }
187
188 let (codec, key_bytes) = public_key_multibase_decode(&self.public_key_multibase)?;
189 if codec != X25519_PUB_CODEC {
190 return Err(MaError::InvalidMulticodec {
191 expected: X25519_PUB_CODEC,
192 actual: codec,
193 });
194 }
195
196 if key_bytes.len() != 32 {
197 return Err(MaError::InvalidKeyLength {
198 expected: 32,
199 actual: key_bytes.len(),
200 });
201 }
202
203 Ok(())
204 }
205}