@@ -6,7 +6,7 @@ use generic_array::ArrayLength;
66use rand:: { CryptoRng , RngCore , rngs:: OsRng } ;
77
88use crate :: {
9- NonceStore , TokenInput , TokenType , TruncatedTokenKeyId ,
9+ COLLISION_AVOIDANCE_ATTEMPTS , NonceStore , TokenInput , TokenType , TruncatedTokenKeyId ,
1010 auth:: authorize:: Token ,
1111 common:: errors:: { CreateKeypairError , IssueTokenResponseError , RedeemTokenError } ,
1212} ;
@@ -18,8 +18,12 @@ use super::{NK, TokenRequest, TokenResponse, public_key_to_token_key_id, truncat
1818#[ async_trait]
1919
2020pub trait IssuerKeyStore : Send + Sync {
21- /// Inserts a keypair with a given `truncated_token_key_id` into the key store.
22- async fn insert ( & self , truncated_token_key_id : TruncatedTokenKeyId , server : KeyPair ) ;
21+ /// Inserts a keypair with a given `truncated_token_key_id` into the key
22+ /// store, only if it does not collide with an existing
23+ /// `truncated_token_key_id`.
24+ ///
25+ /// Returns `true` if the key was inserted, `false` if a collision occurred.
26+ async fn insert ( & self , truncated_token_key_id : TruncatedTokenKeyId , server : KeyPair ) -> bool ;
2327 /// Returns a keypair with a given `truncated_token_key_id` from the key store.
2428 async fn get ( & self , truncated_token_key_id : & TruncatedTokenKeyId ) -> Option < KeyPair > ;
2529}
@@ -30,8 +34,8 @@ pub trait IssuerKeyStore: Send + Sync {
3034pub trait OriginKeyStore {
3135 /// Inserts a keypair with a given `truncated_token_key_id` into the key store.
3236 async fn insert ( & self , truncated_token_key_id : TruncatedTokenKeyId , server : PublicKey ) ;
33- /// Returns a keypair with a given `truncated_token_key_id` from the key store.
34- async fn get ( & self , truncated_token_key_id : & TruncatedTokenKeyId ) -> Option < PublicKey > ;
37+ /// Returns all public keys with a given `truncated_token_key_id` from the key store.
38+ async fn get ( & self , truncated_token_key_id : & TruncatedTokenKeyId ) -> Vec < PublicKey > ;
3539}
3640
3741/// Serializes a keypair into a DER-encoded PKCS#8 document.
@@ -64,14 +68,23 @@ impl IssuerServer {
6468 rng : & mut R ,
6569 key_store : & IKS ,
6670 ) -> Result < PublicKey , CreateKeypairError > {
67- let key_pair =
68- KeyPair :: generate ( rng, KEYSIZE_IN_BITS ) . map_err ( |_| CreateKeypairError :: SeedError ) ?;
69- let truncated_token_key_id =
70- truncate_token_key_id ( & public_key_to_token_key_id ( & key_pair. pk ) ) ;
71- key_store
72- . insert ( truncated_token_key_id, key_pair. clone ( ) )
73- . await ;
74- Ok ( key_pair. pk )
71+ for _ in 0 ..COLLISION_AVOIDANCE_ATTEMPTS {
72+ let key_pair = KeyPair :: generate ( rng, KEYSIZE_IN_BITS )
73+ . map_err ( |_| CreateKeypairError :: SeedError ) ?;
74+ let truncated_token_key_id =
75+ truncate_token_key_id ( & public_key_to_token_key_id ( & key_pair. pk ) ) ;
76+
77+ if key_store. get ( & truncated_token_key_id) . await . is_some ( ) {
78+ continue ;
79+ }
80+
81+ let public_key = key_pair. pk . clone ( ) ;
82+
83+ if key_store. insert ( truncated_token_key_id, key_pair) . await {
84+ return Ok ( public_key) ;
85+ }
86+ }
87+ Err ( CreateKeypairError :: CollisionExhausted )
7588 }
7689
7790 /// Issues a new token response.
@@ -152,17 +165,26 @@ impl OriginServer {
152165 * token. token_key_id ( ) ,
153166 ) ;
154167
155- let public_key = key_store
156- . get ( & truncate_token_key_id ( token. token_key_id ( ) ) )
157- . await
158- . ok_or ( RedeemTokenError :: KeyIdNotFound ) ?;
168+ let truncated_token_key_id = truncate_token_key_id ( token. token_key_id ( ) ) ;
169+ let public_keys = key_store. get ( & truncated_token_key_id) . await ;
170+ if public_keys. is_empty ( ) {
171+ return Err ( RedeemTokenError :: KeyIdNotFound ) ;
172+ }
159173
160174 let options = Options :: default ( ) ;
161175 let signature = Signature ( token. authenticator ( ) . to_vec ( ) ) ;
176+ let token_input_bytes = token_input. serialize ( ) ;
177+
178+ let verified = public_keys. iter ( ) . any ( |public_key| {
179+ signature
180+ . verify ( public_key, None , & token_input_bytes, & options)
181+ . is_ok ( )
182+ } ) ;
183+
184+ if !verified {
185+ return Err ( RedeemTokenError :: InvalidToken ) ;
186+ }
162187
163- signature
164- . verify ( & public_key, None , token_input. serialize ( ) , & options)
165- . map_err ( |_| RedeemTokenError :: InvalidToken ) ?;
166188 nonce_store. insert ( token. nonce ( ) ) . await ;
167189 Ok ( ( ) )
168190 }
0 commit comments