1use std::cell::RefCell;
22
23use rand::RngCore;
24use rand::SeedableRng;
25use rand_hc::Hc128Rng;
26use serde::Deserialize;
27use serde::Serialize;
28
29use super::keccak256;
30use super::signers;
31use super::PublicKey;
32use super::PublicKeyAddress;
33use super::SecretKey;
34use crate::dht::Did;
35use crate::error::Error;
36use crate::error::Result;
37
38thread_local! {
39 static KEY_RNG: RefCell<Hc128Rng> = RefCell::new(Hc128Rng::from_entropy());
40}
41
42fn public_key_transcript(algorithm: &str, raw_bytes: &[u8]) -> Vec<u8> {
43 let mut out = algorithm.as_bytes().to_vec();
44 out.push(0);
45 out.extend_from_slice(raw_bytes);
46 out
47}
48
49fn domain_separated_address(algorithm: &str, raw_bytes: &[u8]) -> PublicKeyAddress {
50 PublicKeyAddress::from_slice(&keccak256(&public_key_transcript(algorithm, raw_bytes))[12..])
51}
52
53#[derive(Deserialize, Serialize, Debug, Clone, Copy, Eq, PartialEq)]
55pub enum SignatureAlgorithm {
56 Secp256k1,
58 Eip191,
60 Bip137,
62 Secp256r1,
64 Ed25519,
66 Bls12381,
68}
69
70#[derive(Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
72pub enum VerificationPublicKey {
73 Secp256k1(PublicKey<33>),
75 Eip191(PublicKey<33>),
77 Bip137(PublicKey<33>),
79 Secp256r1(PublicKey<33>),
81 Ed25519(PublicKey<33>),
83 Bls12381(PublicKey<48>),
85}
86
87#[derive(Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
92pub enum AccountVerifier {
93 Recoverable {
95 algorithm: SignatureAlgorithm,
97 did: Did,
99 },
100 PublicKey(VerificationPublicKey),
102}
103
104#[derive(Deserialize, Serialize, Debug, Clone, Copy, Eq, PartialEq)]
106pub struct Ed25519SecretKey([u8; 32]);
107
108#[derive(Deserialize, Serialize, Debug, Clone, Copy, Eq, PartialEq)]
110pub enum SigningSecretKey {
111 Secp256k1(SecretKey),
113 Eip191(SecretKey),
115 Bip137(SecretKey),
117 Secp256r1(SecretKey),
119 Ed25519(Ed25519SecretKey),
121 Bls12381(SecretKey),
123}
124
125impl SignatureAlgorithm {
126 pub fn as_str(self) -> &'static str {
128 match self {
129 Self::Secp256k1 => "secp256k1",
130 Self::Eip191 => "eip191",
131 Self::Bip137 => "bip137",
132 Self::Secp256r1 => "secp256r1",
133 Self::Ed25519 => "ed25519",
134 Self::Bls12381 => "bls12-381",
135 }
136 }
137
138 pub fn is_recoverable(self) -> bool {
140 matches!(self, Self::Secp256k1 | Self::Eip191 | Self::Bip137)
141 }
142}
143
144impl VerificationPublicKey {
145 pub fn algorithm(&self) -> SignatureAlgorithm {
147 match self {
148 Self::Secp256k1(_) => SignatureAlgorithm::Secp256k1,
149 Self::Eip191(_) => SignatureAlgorithm::Eip191,
150 Self::Bip137(_) => SignatureAlgorithm::Bip137,
151 Self::Secp256r1(_) => SignatureAlgorithm::Secp256r1,
152 Self::Ed25519(_) => SignatureAlgorithm::Ed25519,
153 Self::Bls12381(_) => SignatureAlgorithm::Bls12381,
154 }
155 }
156
157 pub fn verify(&self, msg: &[u8], sig: impl AsRef<[u8]>) -> bool {
159 match self {
160 Self::Secp256k1(pk) => signers::secp256k1::verify(msg, &pk.address(), sig.as_ref()),
161 Self::Eip191(pk) => signers::eip191::verify(msg, &pk.address(), sig.as_ref()),
162 Self::Bip137(pk) => signers::bip137::verify(msg, &pk.address(), sig.as_ref()),
163 Self::Secp256r1(pk) => signers::secp256r1::verify(msg, &pk.address(), sig.as_ref(), pk),
164 Self::Ed25519(pk) => signers::ed25519::verify(msg, &pk.address(), sig.as_ref(), pk),
165 Self::Bls12381(pk) => {
166 let Ok(sig_data) = sig.as_ref().try_into() else {
167 return false;
168 };
169 signers::bls::verify(&[msg], &signers::bls::Signature(sig_data), &[*pk])
170 .unwrap_or(false)
171 }
172 }
173 }
174
175 pub fn raw_bytes(&self) -> &[u8] {
177 match self {
178 Self::Secp256k1(pk)
179 | Self::Eip191(pk)
180 | Self::Bip137(pk)
181 | Self::Secp256r1(pk)
182 | Self::Ed25519(pk) => &pk.0,
183 Self::Bls12381(pk) => &pk.0,
184 }
185 }
186
187 pub fn transcript_bytes(&self) -> Vec<u8> {
189 public_key_transcript(self.algorithm().as_str(), self.raw_bytes())
190 }
191
192 fn domain_separated_address(&self) -> PublicKeyAddress {
193 domain_separated_address(self.algorithm().as_str(), self.raw_bytes())
194 }
195
196 pub fn did(&self) -> Did {
198 match self {
199 Self::Secp256k1(pk) | Self::Eip191(pk) | Self::Bip137(pk) => pk.address().into(),
200 Self::Secp256r1(_) | Self::Ed25519(_) | Self::Bls12381(_) => {
201 self.domain_separated_address().into()
202 }
203 }
204 }
205}
206
207impl AccountVerifier {
208 pub fn from_account_parts(account_entity: &str, account_type: &str) -> Result<Self> {
210 match account_type {
211 "secp256k1" => Ok(Self::Recoverable {
212 algorithm: SignatureAlgorithm::Secp256k1,
213 did: account_entity.parse()?,
214 }),
215 "eip191" => Ok(Self::Recoverable {
216 algorithm: SignatureAlgorithm::Eip191,
217 did: account_entity.parse()?,
218 }),
219 "bip137" => Ok(Self::Recoverable {
220 algorithm: SignatureAlgorithm::Bip137,
221 did: account_entity.parse()?,
222 }),
223 "secp256r1" => {
224 let public_key = PublicKey::from_hex_string(account_entity)?;
225 let verifying_key = public_key.ct_try_into_secp256r1_pubkey();
226 if !bool::from(verifying_key.is_some()) || verifying_key.unwrap().is_err() {
227 return Err(Error::InvalidPublicKey);
228 }
229 Ok(Self::PublicKey(VerificationPublicKey::Secp256r1(
230 public_key,
231 )))
232 }
233 "ed25519" => Ok(Self::PublicKey(VerificationPublicKey::Ed25519(
234 PublicKey::try_from_b58t(account_entity)?,
235 ))),
236 "bls12-381" | "bls12381" => Ok(Self::PublicKey(VerificationPublicKey::Bls12381(
237 public_key_from_b58m_exact(account_entity)?,
238 ))),
239 _ => Err(Error::UnknownAccount),
240 }
241 }
242
243 pub fn algorithm(&self) -> SignatureAlgorithm {
245 match self {
246 Self::Recoverable { algorithm, .. } => *algorithm,
247 Self::PublicKey(public_key) => public_key.algorithm(),
248 }
249 }
250
251 pub fn verify(&self, msg: &[u8], sig: impl AsRef<[u8]>) -> bool {
253 match self {
254 Self::Recoverable {
255 algorithm: SignatureAlgorithm::Secp256k1,
256 did,
257 } => signers::secp256k1::verify(msg, &(*did).into(), sig.as_ref()),
258 Self::Recoverable {
259 algorithm: SignatureAlgorithm::Eip191,
260 did,
261 } => signers::eip191::verify(msg, &(*did).into(), sig.as_ref()),
262 Self::Recoverable {
263 algorithm: SignatureAlgorithm::Bip137,
264 did,
265 } => signers::bip137::verify(msg, &(*did).into(), sig.as_ref()),
266 Self::Recoverable { .. } => false,
267 Self::PublicKey(public_key) => public_key.verify(msg, sig.as_ref()),
268 }
269 }
270
271 pub fn verification_key_from_signature(
273 &self,
274 msg: &[u8],
275 sig: impl AsRef<[u8]>,
276 ) -> Result<VerificationPublicKey> {
277 match self {
278 Self::Recoverable {
279 algorithm: SignatureAlgorithm::Secp256k1,
280 ..
281 } => Ok(VerificationPublicKey::Secp256k1(
282 signers::secp256k1::recover(msg, sig.as_ref())?,
283 )),
284 Self::Recoverable {
285 algorithm: SignatureAlgorithm::Eip191,
286 ..
287 } => Ok(VerificationPublicKey::Eip191(signers::eip191::recover(
288 msg,
289 sig.as_ref(),
290 )?)),
291 Self::Recoverable {
292 algorithm: SignatureAlgorithm::Bip137,
293 ..
294 } => Ok(VerificationPublicKey::Bip137(signers::bip137::recover(
295 msg,
296 sig.as_ref(),
297 )?)),
298 Self::Recoverable { .. } => Err(Error::UnknownAccount),
299 Self::PublicKey(public_key) => Ok(public_key.clone()),
300 }
301 }
302}
303
304impl AccountVerifier {
305 pub fn did(&self) -> Did {
307 match self {
308 Self::Recoverable { did, .. } => *did,
309 Self::PublicKey(public_key) => public_key.did(),
310 }
311 }
312}
313
314impl Ed25519SecretKey {
315 pub fn random_with_rng(rng: &mut impl RngCore) -> Self {
317 let mut seed = [0u8; 32];
318 rng.fill_bytes(&mut seed);
319 Self(seed)
320 }
321
322 pub fn random() -> Self {
324 with_key_rng(Self::random_with_rng)
325 }
326
327 pub fn from_bytes(seed: [u8; 32]) -> Self {
329 Self(seed)
330 }
331
332 pub fn to_bytes(self) -> [u8; 32] {
334 self.0
335 }
336
337 pub fn as_bytes(&self) -> &[u8; 32] {
339 &self.0
340 }
341
342 pub fn public_key(&self) -> Result<PublicKey<33>> {
344 signers::ed25519::public_key(&self.0)
345 }
346
347 pub fn sign_raw(&self, msg: &[u8]) -> Result<[u8; 64]> {
349 signers::ed25519::sign(&self.0, msg)
350 }
351}
352
353impl SigningSecretKey {
354 pub fn sign_raw(&self, msg: &[u8]) -> Result<Vec<u8>> {
356 Ok(match self {
357 Self::Secp256k1(sk) => signers::secp256k1::sign_raw(*sk, msg).to_vec(),
358 Self::Eip191(sk) => signers::eip191::sign_raw(*sk, msg).to_vec(),
359 Self::Bip137(sk) => {
360 let signature = sk.sign_hash(&signers::bip137::magic_hash(msg));
361 let mut out = Vec::with_capacity(65);
362 out.push(signature[64] + 27);
363 out.extend_from_slice(&signature[..64]);
364 out
365 }
366 Self::Secp256r1(sk) => {
367 signers::secp256r1::sign(*sk, &signers::secp256r1::hash(msg))?.to_vec()
368 }
369 Self::Ed25519(sk) => sk.sign_raw(msg)?.to_vec(),
370 Self::Bls12381(sk) => signers::bls::sign(*sk, msg)?.0.to_vec(),
371 })
372 }
373
374 pub fn random_ed25519_with_rng(rng: &mut impl RngCore) -> Self {
376 Self::Ed25519(Ed25519SecretKey::random_with_rng(rng))
377 }
378
379 pub fn random_ed25519() -> Self {
381 Self::Ed25519(Ed25519SecretKey::random())
382 }
383
384 pub fn random_bls12381() -> Result<Self> {
386 signers::bls::random_sk().map(Self::Bls12381)
387 }
388
389 pub fn try_bls12381(secret_key: SecretKey) -> Result<Self> {
391 signers::bls::public_key(&secret_key)?;
392 Ok(Self::Bls12381(secret_key))
393 }
394}
395
396impl SigningSecretKey {
397 pub fn algorithm(&self) -> &'static str {
399 match self {
400 Self::Secp256k1(_) => SignatureAlgorithm::Secp256k1.as_str(),
401 Self::Eip191(_) => SignatureAlgorithm::Eip191.as_str(),
402 Self::Bip137(_) => SignatureAlgorithm::Bip137.as_str(),
403 Self::Secp256r1(_) => SignatureAlgorithm::Secp256r1.as_str(),
404 Self::Ed25519(_) => SignatureAlgorithm::Ed25519.as_str(),
405 Self::Bls12381(_) => SignatureAlgorithm::Bls12381.as_str(),
406 }
407 }
408
409 pub fn public_key(&self) -> Result<VerificationPublicKey> {
411 Ok(match self {
412 Self::Secp256k1(sk) => VerificationPublicKey::Secp256k1(sk.pubkey()),
413 Self::Eip191(sk) => VerificationPublicKey::Eip191(sk.pubkey()),
414 Self::Bip137(sk) => VerificationPublicKey::Bip137(sk.pubkey()),
415 Self::Secp256r1(sk) => VerificationPublicKey::Secp256r1(secp256r1_public_key(*sk)?),
416 Self::Ed25519(sk) => VerificationPublicKey::Ed25519(sk.public_key()?),
417 Self::Bls12381(sk) => VerificationPublicKey::Bls12381(signers::bls::public_key(sk)?),
418 })
419 }
420}
421
422fn secp256r1_public_key(secret_key: SecretKey) -> Result<PublicKey<33>> {
423 let sk_bytes: elliptic_curve::FieldBytes<p256::NistP256> = secret_key.into();
424 let signing_key = ecdsa::SigningKey::<p256::NistP256>::from_bytes(&sk_bytes)?;
425 let encoded = signing_key.verifying_key().to_encoded_point(false);
426 let uncompressed = encoded
427 .as_bytes()
428 .get(1..)
429 .ok_or(Error::PublicKeyBadFormat)?;
430 PublicKey::from_u8(uncompressed)
431}
432
433fn with_key_rng<R>(f: impl FnOnce(&mut Hc128Rng) -> R) -> R {
434 KEY_RNG.with(|rng| {
435 let mut rng = rng.borrow_mut();
436 f(&mut rng)
437 })
438}
439
440fn public_key_from_b58m_exact<const SIZE: usize>(value: &str) -> Result<PublicKey<SIZE>> {
441 let bytes = base58_monero::decode_check(value).map_err(|_| Error::PublicKeyBadFormat)?;
442 PublicKey::from_exact_u8(&bytes)
443}
444
445#[cfg(test)]
446mod tests {
447 use rand::SeedableRng;
448 use rand_hc::Hc128Rng;
449
450 use super::*;
451
452 #[test]
453 fn recoverable_account_verifier_verifies_and_recovers_key() {
454 let secret =
455 SecretKey::try_from("65860affb4b570dba06db294aa7c676f68e04a5bf2721243ad3cbc05a79c68c0")
456 .unwrap();
457 let did: Did = secret.address().into();
458 let reference = AccountVerifier::Recoverable {
459 algorithm: SignatureAlgorithm::Secp256k1,
460 did,
461 };
462 let msg = b"session proof";
463 let sig = secret.sign_raw(msg);
464
465 assert_eq!(reference.did(), did);
466 assert!(reference.verify(msg, sig));
467 assert_eq!(
468 reference.verification_key_from_signature(msg, sig).unwrap(),
469 VerificationPublicKey::Secp256k1(secret.pubkey())
470 );
471 }
472
473 #[test]
474 fn bip137_signing_secret_signs_and_recovers_key() {
475 let secret = SigningSecretKey::Bip137(
476 SecretKey::try_from("65860affb4b570dba06db294aa7c676f68e04a5bf2721243ad3cbc05a79c68c0")
477 .unwrap(),
478 );
479 let did = secret.public_key().unwrap().did();
480 let reference = AccountVerifier::Recoverable {
481 algorithm: SignatureAlgorithm::Bip137,
482 did,
483 };
484 let msg = b"bitcoin session proof";
485 let sig = secret.sign_raw(msg).unwrap();
486
487 assert_eq!(secret.algorithm(), "bip137");
488 assert!(reference.verify(msg, &sig));
489 assert_eq!(
490 reference
491 .verification_key_from_signature(msg, &sig)
492 .unwrap(),
493 secret.public_key().unwrap()
494 );
495 }
496
497 #[test]
498 fn bls_signing_secret_signs_and_verifies_key() {
499 let secret = SigningSecretKey::random_bls12381().unwrap();
500 let public_key = secret.public_key().unwrap();
501 let did = public_key.did();
502 let reference = AccountVerifier::PublicKey(public_key.clone());
503 let msg = b"bls session proof";
504 let sig = secret.sign_raw(msg).unwrap();
505
506 assert_eq!(secret.algorithm(), "bls12-381");
507 assert_eq!(reference.did(), did);
508 assert!(reference.verify(msg, &sig));
509 assert_eq!(
510 reference
511 .verification_key_from_signature(msg, &sig)
512 .unwrap(),
513 public_key
514 );
515
516 let VerificationPublicKey::Bls12381(pk) = public_key else {
517 unreachable!("random_bls12381 returns a BLS verification key");
518 };
519 let encoded = base58_monero::encode_check(&pk.0).unwrap();
520 assert_eq!(
521 AccountVerifier::from_account_parts(&encoded, "bls12-381").unwrap(),
522 AccountVerifier::PublicKey(VerificationPublicKey::Bls12381(pk))
523 );
524 }
525
526 #[test]
527 fn ed25519_signing_secret_signs_and_verifies_key() {
528 let secret = SigningSecretKey::random_ed25519();
529 let public_key = secret.public_key().unwrap();
530 let did = public_key.did();
531 let reference = AccountVerifier::PublicKey(public_key.clone());
532 let msg = b"ed25519 session proof";
533 let sig = secret.sign_raw(msg).unwrap();
534
535 assert_eq!(secret.algorithm(), "ed25519");
536 assert_eq!(reference.did(), did);
537 assert!(reference.verify(msg, &sig));
538 assert_eq!(
539 reference
540 .verification_key_from_signature(msg, &sig)
541 .unwrap(),
542 public_key
543 );
544
545 let VerificationPublicKey::Ed25519(pk) = public_key else {
546 unreachable!("random_ed25519 returns an Ed25519 verification key");
547 };
548 assert_eq!(
549 AccountVerifier::from_account_parts(&pk.to_base58_string().unwrap(), "ed25519")
550 .unwrap(),
551 AccountVerifier::PublicKey(VerificationPublicKey::Ed25519(pk))
552 );
553 }
554
555 #[test]
556 fn ed25519_random_with_rng_is_reproducible_for_same_seed() {
557 let mut rng_a = Hc128Rng::seed_from_u64(42);
558 let mut rng_b = Hc128Rng::seed_from_u64(42);
559
560 assert_eq!(
561 SigningSecretKey::random_ed25519_with_rng(&mut rng_a),
562 SigningSecretKey::random_ed25519_with_rng(&mut rng_b)
563 );
564 }
565
566 #[test]
567 fn explicit_verification_keys_domain_separate_dids() {
568 let pk = SecretKey::random().pubkey();
569 let secp = VerificationPublicKey::Secp256k1(pk);
570 let ed = VerificationPublicKey::Ed25519(pk);
571
572 let mut expected_transcript = b"ed25519\0".to_vec();
573 expected_transcript.extend_from_slice(&pk.0);
574
575 assert_eq!(ed.transcript_bytes(), expected_transcript);
576 assert_ne!(secp.did(), ed.did());
577 assert_eq!(ed.did(), AccountVerifier::PublicKey(ed.clone()).did());
578 }
579
580 #[test]
581 fn secp256r1_secret_derives_p256_public_key() {
582 let secret = SigningSecretKey::Secp256r1(
583 SecretKey::try_from("2544acda37415a476d42312969926dc48e529867036cec71922d4177ea9c1038")
584 .unwrap(),
585 );
586 let expected = PublicKey::<33>::from_hex_string(
587 "17a6afd392fcbe4ac9270a599a9c5732c4f838ce35ea2234d389d8f0c367f3f5dcab906352e27289002c7f2c96039ddce7c1b5aad8b87ba94984d4c8b4f95702",
588 )
589 .unwrap();
590
591 assert_eq!(
592 secret.public_key().unwrap(),
593 VerificationPublicKey::Secp256r1(expected)
594 );
595 }
596}