@@ -56,28 +56,58 @@ impl FromStr for Algorithm {
5656}
5757
5858/// The actual HS signing + encoding
59- fn sign_hmac ( alg : & ' static digest:: Algorithm , key : & [ u8 ] , signing_input : & str ) -> Result < String > {
60- let signing_key = hmac:: SigningKey :: new ( alg, key) ;
59+ fn sign_hmac < K : Key > (
60+ alg : & ' static digest:: Algorithm ,
61+ key : K ,
62+ signing_input : & str ,
63+ ) -> Result < String > {
64+ let signing_key = hmac:: SigningKey :: new ( alg, key. as_ref ( ) ) ;
6165 let digest = hmac:: sign ( & signing_key, signing_input. as_bytes ( ) ) ;
6266
6367 Ok ( base64:: encode_config :: < hmac:: Signature > ( & digest, base64:: URL_SAFE_NO_PAD ) )
6468}
6569
6670/// The actual ECDSA signing + encoding
67- fn sign_ecdsa ( alg : & ' static signature:: EcdsaSigningAlgorithm , key : & [ u8 ] , signing_input : & str ) -> Result < String > {
68- let signing_key = signature:: EcdsaKeyPair :: from_pkcs8 ( alg, untrusted:: Input :: from ( key) ) ?;
71+ fn sign_ecdsa < K : Key > (
72+ alg : & ' static signature:: EcdsaSigningAlgorithm ,
73+ key : K ,
74+ signing_input : & str ,
75+ ) -> Result < String > {
76+ let signing_key = match key. format ( ) {
77+ KeyFormat :: PKCS8 => {
78+ signature:: EcdsaKeyPair :: from_pkcs8 ( alg, untrusted:: Input :: from ( key. as_ref ( ) ) ) ?
79+ }
80+ _ => {
81+ return Err ( ErrorKind :: InvalidKeyFormat ) ?;
82+ }
83+ } ;
84+
6985 let rng = rand:: SystemRandom :: new ( ) ;
7086 let sig = signing_key. sign ( & rng, untrusted:: Input :: from ( signing_input. as_bytes ( ) ) ) ?;
7187 Ok ( base64:: encode_config ( & sig, base64:: URL_SAFE_NO_PAD ) )
7288}
7389
7490/// The actual RSA signing + encoding
7591/// Taken from Ring doc https://briansmith.org/rustdoc/ring/signature/index.html
76- fn sign_rsa ( alg : & ' static signature:: RsaEncoding , key : & [ u8 ] , signing_input : & str ) -> Result < String > {
77- let key_pair = Arc :: new (
78- signature:: RsaKeyPair :: from_der ( untrusted:: Input :: from ( key) )
79- . map_err ( |_| ErrorKind :: InvalidRsaKey ) ?,
80- ) ;
92+ fn sign_rsa < K : Key > (
93+ alg : & ' static signature:: RsaEncoding ,
94+ key : K ,
95+ signing_input : & str ,
96+ ) -> Result < String > {
97+ let key_bytes = untrusted:: Input :: from ( key. as_ref ( ) ) ;
98+ let key_pair = match key. format ( ) {
99+ KeyFormat :: DER => {
100+ signature:: RsaKeyPair :: from_der ( key_bytes) . map_err ( |_| ErrorKind :: InvalidRsaKey ) ?
101+ }
102+ KeyFormat :: PKCS8 => {
103+ signature:: RsaKeyPair :: from_pkcs8 ( key_bytes) . map_err ( |_| ErrorKind :: InvalidRsaKey ) ?
104+ }
105+ _ => {
106+ return Err ( ErrorKind :: InvalidKeyFormat ) ?;
107+ }
108+ } ;
109+
110+ let key_pair = Arc :: new ( key_pair) ;
81111 let mut signature = vec ! [ 0 ; key_pair. public_modulus_len( ) ] ;
82112 let rng = rand:: SystemRandom :: new ( ) ;
83113 key_pair
@@ -91,14 +121,18 @@ fn sign_rsa(alg: &'static signature::RsaEncoding, key: &[u8], signing_input: &st
91121/// the base64 url safe encoded of the result.
92122///
93123/// Only use this function if you want to do something other than JWT.
94- pub fn sign ( signing_input : & str , key : & [ u8 ] , algorithm : Algorithm ) -> Result < String > {
124+ pub fn sign < K : Key > ( signing_input : & str , key : K , algorithm : Algorithm ) -> Result < String > {
95125 match algorithm {
96126 Algorithm :: HS256 => sign_hmac ( & digest:: SHA256 , key, signing_input) ,
97127 Algorithm :: HS384 => sign_hmac ( & digest:: SHA384 , key, signing_input) ,
98128 Algorithm :: HS512 => sign_hmac ( & digest:: SHA512 , key, signing_input) ,
99129
100- Algorithm :: ES256 => sign_ecdsa ( & signature:: ECDSA_P256_SHA256_FIXED_SIGNING , key, signing_input) ,
101- Algorithm :: ES384 => sign_ecdsa ( & signature:: ECDSA_P384_SHA384_FIXED_SIGNING , key, signing_input) ,
130+ Algorithm :: ES256 => {
131+ sign_ecdsa ( & signature:: ECDSA_P256_SHA256_FIXED_SIGNING , key, signing_input)
132+ }
133+ Algorithm :: ES384 => {
134+ sign_ecdsa ( & signature:: ECDSA_P384_SHA384_FIXED_SIGNING , key, signing_input)
135+ }
102136
103137 Algorithm :: RS256 => sign_rsa ( & signature:: RSA_PKCS1_SHA256 , key, signing_input) ,
104138 Algorithm :: RS384 => sign_rsa ( & signature:: RSA_PKCS1_SHA384 , key, signing_input) ,
@@ -134,29 +168,149 @@ fn verify_ring(
134168pub fn verify (
135169 signature : & str ,
136170 signing_input : & str ,
137- key : & [ u8 ] ,
171+ public_key : & [ u8 ] ,
138172 algorithm : Algorithm ,
139173) -> Result < bool > {
140174 match algorithm {
141175 Algorithm :: HS256 | Algorithm :: HS384 | Algorithm :: HS512 => {
142176 // we just re-sign the data with the key and compare if they are equal
143- let signed = sign ( signing_input, key , algorithm) ?;
177+ let signed = sign ( signing_input, Hmac :: from ( & public_key ) , algorithm) ?;
144178 Ok ( verify_slices_are_equal ( signature. as_ref ( ) , signed. as_ref ( ) ) . is_ok ( ) )
145179 }
146180 Algorithm :: ES256 => {
147- verify_ring ( & signature:: ECDSA_P256_SHA256_FIXED , signature, signing_input, key )
181+ verify_ring ( & signature:: ECDSA_P256_SHA256_FIXED , signature, signing_input, public_key )
148182 }
149183 Algorithm :: ES384 => {
150- verify_ring ( & signature:: ECDSA_P384_SHA384_FIXED , signature, signing_input, key)
151- }
152- Algorithm :: RS256 => {
153- verify_ring ( & signature:: RSA_PKCS1_2048_8192_SHA256 , signature, signing_input, key)
154- }
155- Algorithm :: RS384 => {
156- verify_ring ( & signature:: RSA_PKCS1_2048_8192_SHA384 , signature, signing_input, key)
157- }
158- Algorithm :: RS512 => {
159- verify_ring ( & signature:: RSA_PKCS1_2048_8192_SHA512 , signature, signing_input, key)
184+ verify_ring ( & signature:: ECDSA_P384_SHA384_FIXED , signature, signing_input, public_key)
160185 }
186+ Algorithm :: RS256 => verify_ring (
187+ & signature:: RSA_PKCS1_2048_8192_SHA256 ,
188+ signature,
189+ signing_input,
190+ public_key,
191+ ) ,
192+ Algorithm :: RS384 => verify_ring (
193+ & signature:: RSA_PKCS1_2048_8192_SHA384 ,
194+ signature,
195+ signing_input,
196+ public_key,
197+ ) ,
198+ Algorithm :: RS512 => verify_ring (
199+ & signature:: RSA_PKCS1_2048_8192_SHA512 ,
200+ signature,
201+ signing_input,
202+ public_key,
203+ ) ,
204+ }
205+ }
206+
207+ /// The supported RSA key formats, see the documentation for ring::signature::RsaKeyPair
208+ /// for more information
209+ pub enum KeyFormat {
210+ /// An unencrypted PKCS#8-encoded key. Can be used with both ECDSA and RSA
211+ /// algorithms when signing. See ring for information.
212+ PKCS8 ,
213+ /// A binary DER-encoded ASN.1 key. Can only be used with RSA algorithms
214+ /// when signing. See ring for more information
215+ DER ,
216+ /// This is not a key format, but provided for convenience since HMAC is
217+ /// a supported signing algorithm.
218+ HMAC ,
219+ }
220+
221+ /// A tiny abstraction on top of raw key buffers to add key format
222+ /// information
223+ pub trait Key : AsRef < [ u8 ] > {
224+ /// The format of the key
225+ fn format ( & self ) -> KeyFormat ;
226+ }
227+
228+ /// This blanket implementation aligns with the key loading as of version 6.0.0
229+ // impl<T> Key for T
230+ // where
231+ // T: AsRef<[u8]>,
232+ // {
233+ // fn format(&self) -> KeyFormat {
234+ // KeyFormat::DER
235+ // }
236+ // }
237+
238+ /// A convenience wrapper for a key buffer as an unencrypted PKCS#8-encoded,
239+ /// see ring for more details
240+ pub struct Pkcs8 < ' a > {
241+ key_bytes : & ' a [ u8 ] ,
242+ }
243+
244+ impl < ' a > Key for Pkcs8 < ' a > {
245+ fn format ( & self ) -> KeyFormat {
246+ KeyFormat :: PKCS8
247+ }
248+ }
249+
250+ impl < ' a > AsRef < [ u8 ] > for Pkcs8 < ' a > {
251+ fn as_ref ( & self ) -> & [ u8 ] {
252+ self . key_bytes
253+ }
254+ }
255+
256+ impl < ' a , T > From < & ' a T > for Pkcs8 < ' a >
257+ where
258+ T : AsRef < [ u8 ] > ,
259+ {
260+ fn from ( key : & ' a T ) -> Self {
261+ Self { key_bytes : key. as_ref ( ) }
262+ }
263+ }
264+
265+ /// A convenience wrapper for a key buffer as a binary DER-encoded ASN.1 key,
266+ /// see ring for more details
267+ pub struct Der < ' a > {
268+ key_bytes : & ' a [ u8 ] ,
269+ }
270+
271+ impl < ' a > Key for Der < ' a > {
272+ fn format ( & self ) -> KeyFormat {
273+ KeyFormat :: DER
274+ }
275+ }
276+
277+ impl < ' a > AsRef < [ u8 ] > for Der < ' a > {
278+ fn as_ref ( & self ) -> & [ u8 ] {
279+ self . key_bytes
280+ }
281+ }
282+
283+ impl < ' a , T > From < & ' a T > for Der < ' a >
284+ where
285+ T : AsRef < [ u8 ] > ,
286+ {
287+ fn from ( key : & ' a T ) -> Self {
288+ Self { key_bytes : key. as_ref ( ) }
289+ }
290+ }
291+
292+ /// Convenience wrapper for an HMAC key
293+ pub struct Hmac < ' a > {
294+ key_bytes : & ' a [ u8 ] ,
295+ }
296+
297+ impl < ' a > Key for Hmac < ' a > {
298+ fn format ( & self ) -> KeyFormat {
299+ KeyFormat :: HMAC
300+ }
301+ }
302+
303+ impl < ' a > AsRef < [ u8 ] > for Hmac < ' a > {
304+ fn as_ref ( & self ) -> & [ u8 ] {
305+ self . key_bytes
306+ }
307+ }
308+
309+ impl < ' a , T > From < & ' a T > for Hmac < ' a >
310+ where
311+ T : AsRef < [ u8 ] > ,
312+ {
313+ fn from ( key : & ' a T ) -> Self {
314+ Self { key_bytes : key. as_ref ( ) }
161315 }
162316}
0 commit comments