jwt_compact/alg/
eddsa_sodium.rs1use anyhow::format_err;
4use exonum_crypto::{
5 gen_keypair_from_seed, sign, verify, PublicKey, SecretKey, Seed, Signature, PUBLIC_KEY_LENGTH,
6 SEED_LENGTH, SIGNATURE_LENGTH,
7};
8
9use core::num::NonZeroUsize;
10
11use crate::{
12 alg::{SecretBytes, SigningKey, VerifyingKey},
13 alloc::Cow,
14 jwk::{JsonWebKey, JwkError, KeyType},
15 Algorithm, AlgorithmSignature, Renamed,
16};
17
18impl AlgorithmSignature for Signature {
19 const LENGTH: Option<NonZeroUsize> = NonZeroUsize::new(SIGNATURE_LENGTH);
20
21 fn try_from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
22 Ok(Self::from_slice(bytes).unwrap())
25 }
26
27 fn as_bytes(&self) -> Cow<'_, [u8]> {
28 Cow::Borrowed(self.as_ref())
29 }
30}
31
32#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
39#[cfg_attr(
40 docsrs,
41 doc(cfg(any(
42 feature = "exonum-crypto",
43 feature = "ed25519-dalek",
44 feature = "ed25519-compact"
45 )))
46)]
47pub struct Ed25519;
48
49impl Ed25519 {
50 pub fn with_specific_name() -> Renamed<Self> {
53 Renamed::new(Self, "Ed25519")
54 }
55}
56
57impl Algorithm for Ed25519 {
58 type SigningKey = SecretKey;
59 type VerifyingKey = PublicKey;
60 type Signature = Signature;
61
62 fn name(&self) -> Cow<'static, str> {
63 Cow::Borrowed("EdDSA")
64 }
65
66 fn sign(&self, signing_key: &Self::SigningKey, message: &[u8]) -> Self::Signature {
67 sign(message, signing_key)
68 }
69
70 fn verify_signature(
71 &self,
72 signature: &Self::Signature,
73 verifying_key: &Self::VerifyingKey,
74 message: &[u8],
75 ) -> bool {
76 verify(signature, message, verifying_key)
77 }
78}
79
80impl VerifyingKey<Ed25519> for PublicKey {
81 fn from_slice(raw: &[u8]) -> anyhow::Result<Self> {
82 Self::from_slice(raw).ok_or_else(|| format_err!("Invalid public key length"))
83 }
84
85 fn as_bytes(&self) -> Cow<'_, [u8]> {
86 Cow::Borrowed(self.as_ref())
87 }
88}
89
90impl SigningKey<Ed25519> for SecretKey {
91 fn from_slice(raw: &[u8]) -> anyhow::Result<Self> {
92 Self::from_slice(raw).ok_or_else(|| format_err!("Invalid secret key bytes"))
93 }
94
95 fn to_verifying_key(&self) -> PublicKey {
96 PublicKey::from_slice(&self[SEED_LENGTH..]).unwrap()
100 }
101
102 fn as_bytes(&self) -> SecretBytes<'_> {
103 SecretBytes::borrowed(&self[..])
104 }
105}
106
107impl<'a> From<&'a PublicKey> for JsonWebKey<'a> {
108 fn from(key: &'a PublicKey) -> JsonWebKey<'a> {
109 JsonWebKey::KeyPair {
110 curve: Cow::Borrowed("Ed25519"),
111 x: Cow::Borrowed(key.as_ref()),
112 secret: None,
113 }
114 }
115}
116
117impl TryFrom<&JsonWebKey<'_>> for PublicKey {
118 type Error = JwkError;
119
120 fn try_from(jwk: &JsonWebKey<'_>) -> Result<Self, Self::Error> {
121 let JsonWebKey::KeyPair { curve, x, .. } = jwk else {
122 return Err(JwkError::key_type(jwk, KeyType::KeyPair));
123 };
124
125 JsonWebKey::ensure_curve(curve, "Ed25519")?;
126 JsonWebKey::ensure_len("x", x, PUBLIC_KEY_LENGTH)?;
127 Ok(PublicKey::from_slice(x).unwrap())
128 }
130}
131
132impl<'a> From<&'a SecretKey> for JsonWebKey<'a> {
133 fn from(key: &'a SecretKey) -> JsonWebKey<'a> {
134 JsonWebKey::KeyPair {
135 curve: Cow::Borrowed("Ed25519"),
136 x: Cow::Borrowed(&key[SEED_LENGTH..]),
137 secret: Some(SecretBytes::borrowed(&key[..SEED_LENGTH])),
138 }
139 }
140}
141
142impl TryFrom<&JsonWebKey<'_>> for SecretKey {
143 type Error = JwkError;
144
145 fn try_from(jwk: &JsonWebKey<'_>) -> Result<Self, Self::Error> {
146 let JsonWebKey::KeyPair { secret, .. } = jwk else {
147 return Err(JwkError::key_type(jwk, KeyType::KeyPair));
148 };
149 let seed_bytes = secret.as_deref();
150 let seed_bytes = seed_bytes.ok_or_else(|| JwkError::NoField("d".to_owned()))?;
151
152 JsonWebKey::ensure_len("d", seed_bytes, SEED_LENGTH)?;
153 let seed = Seed::from_slice(seed_bytes).unwrap();
154 let (_, sk) = gen_keypair_from_seed(&seed);
155 jwk.ensure_key_match(sk)
156 }
157}