jwt_compact_preview/alg/
es256k.rs1use rand_core::{CryptoRng, RngCore};
2use secp256k1::{All, Message, PublicKey, Secp256k1, SecretKey, Signature};
3use sha2::{
4 digest::{generic_array::typenum::U32, Digest},
5 Sha256,
6};
7use std::{borrow::Cow, marker::PhantomData};
8
9use crate::{Algorithm, AlgorithmSignature};
10
11impl AlgorithmSignature for Signature {
12 fn try_from_slice(slice: &[u8]) -> anyhow::Result<Self> {
13 Signature::from_compact(slice).map_err(Into::into)
14 }
15
16 fn as_bytes(&self) -> Cow<[u8]> {
17 Cow::Owned(self.serialize_compact()[..].to_vec())
18 }
19}
20
21#[derive(Debug, Copy, Clone, Eq, PartialEq)]
23pub struct Es256kVerifyingKey(PublicKey);
24
25impl AsRef<PublicKey> for Es256kVerifyingKey {
26 fn as_ref(&self) -> &PublicKey {
27 &self.0
28 }
29}
30
31impl Es256kVerifyingKey {
32 pub fn from_slice(raw: &[u8]) -> anyhow::Result<Es256kVerifyingKey> {
34 Ok(Es256kVerifyingKey(PublicKey::from_slice(raw)?))
35 }
36
37 pub fn as_bytes(&self) -> Cow<[u8]> {
39 Cow::Owned(self.as_ref().serialize().to_vec())
40 }
41}
42
43#[derive(Debug)]
45pub struct Es256kSigningKey(SecretKey);
46
47impl AsRef<SecretKey> for Es256kSigningKey {
48 fn as_ref(&self) -> &SecretKey {
49 &self.0
50 }
51}
52
53impl Es256kSigningKey {
54 pub fn from_slice(raw: &[u8]) -> anyhow::Result<Es256kSigningKey> {
56 Ok(Es256kSigningKey(SecretKey::from_slice(raw)?))
57 }
58
59 pub fn to_verifying_key(&self) -> PublicKey {
61 PublicKey::from_secret_key(&Secp256k1::new(), &self.0)
62 }
63}
64
65#[derive(Debug)]
74pub struct Es256k<D = Sha256> {
75 context: Secp256k1<All>,
76 _digest: PhantomData<D>,
77}
78
79impl<D> Default for Es256k<D>
80where
81 D: Digest<OutputSize = U32> + Default,
82{
83 fn default() -> Self {
84 Es256k {
85 context: Secp256k1::new(),
86 _digest: PhantomData,
87 }
88 }
89}
90
91impl<D> Es256k<D>
92where
93 D: Digest<OutputSize = U32> + Default,
94{
95 pub fn new(context: Secp256k1<All>) -> Self {
99 Es256k {
100 context,
101 _digest: PhantomData,
102 }
103 }
104}
105
106impl<D> Algorithm for Es256k<D>
107where
108 D: Digest<OutputSize = U32> + Default,
109{
110 type SigningKey = Es256kSigningKey;
111 type VerifyingKey = Es256kVerifyingKey;
112 type Signature = Signature;
113
114 fn name(&self) -> Cow<'static, str> {
115 Cow::Borrowed("ES256K")
116 }
117
118 fn sign(&self, signing_key: &Self::SigningKey, message: &[u8]) -> Self::Signature {
119 let mut digest = D::default();
120 digest.update(message);
121 let message = Message::from_slice(&digest.finalize())
122 .expect("failed to convert message to the correct form");
123
124 self.context.sign(&message, signing_key.as_ref())
125 }
126
127 fn verify_signature(
128 &self,
129 signature: &Self::Signature,
130 verifying_key: &Self::VerifyingKey,
131 message: &[u8],
132 ) -> bool {
133 let mut digest = D::default();
134 digest.update(message);
135 let message = Message::from_slice(&digest.finalize())
136 .expect("failed to convert message to the correct form");
137
138 self.context
139 .verify(&message, signature, verifying_key.as_ref())
140 .is_ok()
141 }
142}
143
144impl Es256k {
145 pub fn generate<R: CryptoRng + RngCore>(
147 &self,
148 rng: &mut R,
149 ) -> (Es256kSigningKey, Es256kVerifyingKey) {
150 let signing_key = loop {
151 let mut bytes: [u8; secp256k1::constants::SECRET_KEY_SIZE];
152 rng.fill_bytes(&mut bytes);
153 if let Ok(key) = SecretKey::from_slice(&bytes) {
154 break Es256kSigningKey(key);
155 }
156 };
157 let verifying_key = Es256kVerifyingKey(signing_key.to_verifying_key());
158 (signing_key, verifying_key)
159 }
160}