Skip to content

Commit 2696bf2

Browse files
feat: more expressive errors (#44)
* more expressive errors * address review comments
1 parent c6be7b0 commit 2696bf2

File tree

14 files changed

+338
-101
lines changed

14 files changed

+338
-101
lines changed

src/amortized_tokens/request.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ impl<CS: PrivateCipherSuite> AmortizedBatchTokenRequest<CS> {
101101
) -> Result<(AmortizedBatchTokenRequest<CS>, TokenState<CS>), IssueTokenRequestError> {
102102
let challenge_digest = challenge
103103
.digest()
104-
.map_err(|_| IssueTokenRequestError::InvalidTokenChallenge)?;
104+
.map_err(|source| IssueTokenRequestError::InvalidTokenChallenge { source })?;
105105

106106
let token_key_id = public_key_to_token_key_id::<CS>(&public_key);
107107

@@ -125,16 +125,21 @@ impl<CS: PrivateCipherSuite> AmortizedBatchTokenRequest<CS> {
125125
token_key_id,
126126
);
127127

128-
let blind = VoprfClient::<CS>::blind(&token_input.serialize(), &mut OsRng)
129-
.map_err(|_| IssueTokenRequestError::BlindingError)?;
128+
let blind = VoprfClient::<CS>::blind(&token_input.serialize(), &mut OsRng).map_err(
129+
|source| IssueTokenRequestError::BlindingError {
130+
source: source.into(),
131+
},
132+
)?;
130133

131134
#[cfg(feature = "kat")]
132135
let blind = if _blinds.is_some() {
133136
VoprfClient::<CS>::deterministic_blind_unchecked(
134137
&token_input.serialize(),
135138
*blinds_iter.next().unwrap(),
136139
)
137-
.map_err(|_| IssueTokenRequestError::BlindingError)?
140+
.map_err(|source| IssueTokenRequestError::BlindingError {
141+
source: source.into(),
142+
})?
138143
} else {
139144
blind
140145
};

src/amortized_tokens/response.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ impl<CS: PrivateCipherSuite> AmortizedBatchTokenResponse<CS> {
5252
/// valid `TokenResponse`.
5353
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, SerializationError> {
5454
let mut bytes = bytes;
55-
Self::tls_deserialize(&mut bytes).map_err(|_| SerializationError::InvalidData)
55+
Self::tls_deserialize(&mut bytes)
56+
.map_err(|source| SerializationError::InvalidData { source })
5657
}
5758

5859
/// Issue a token.
@@ -64,15 +65,30 @@ impl<CS: PrivateCipherSuite> AmortizedBatchTokenResponse<CS> {
6465
token_state: &TokenState<CS>,
6566
) -> Result<Vec<AmortizedToken<CS>>, IssueTokenError> {
6667
let mut evaluated_elements = Vec::new();
67-
for element in self.evaluated_elements.iter() {
68-
let evaluated_element =
69-
EvaluationElement::<CS>::deserialize(&element.evaluated_element)
70-
.map_err(|_| IssueTokenError::InvalidTokenResponse)?;
68+
let default_token_type = token_state
69+
.token_inputs
70+
.first()
71+
.map(|token_input| token_input.token_type)
72+
.unwrap_or_else(CS::token_type);
73+
for (index, element) in self.evaluated_elements.iter().enumerate() {
74+
let token_type = token_state
75+
.token_inputs
76+
.get(index)
77+
.map(|token_input| token_input.token_type)
78+
.unwrap_or(default_token_type);
79+
let evaluated_element = EvaluationElement::<CS>::deserialize(
80+
&element.evaluated_element,
81+
)
82+
.map_err(|source| IssueTokenError::InvalidEvaluationElement { token_type, source })?;
7183
evaluated_elements.push(evaluated_element);
7284
}
7385

74-
let proof = Proof::deserialize(&self.evaluated_proof)
75-
.map_err(|_| IssueTokenError::InvalidTokenResponse)?;
86+
let proof = Proof::deserialize(&self.evaluated_proof).map_err(|source| {
87+
IssueTokenError::InvalidProof {
88+
token_type: default_token_type,
89+
source,
90+
}
91+
})?;
7692

7793
let client_batch_finalize_result = VoprfClient::batch_finalize(
7894
&token_state
@@ -85,9 +101,15 @@ impl<CS: PrivateCipherSuite> AmortizedBatchTokenResponse<CS> {
85101
&proof,
86102
token_state.public_key,
87103
)
88-
.map_err(|_| IssueTokenError::InvalidTokenResponse)?
104+
.map_err(|source| IssueTokenError::BatchFinalizationFailed {
105+
token_type: default_token_type,
106+
source,
107+
})?
89108
.collect::<Result<Vec<_>>>()
90-
.map_err(|_| IssueTokenError::InvalidTokenResponse)?;
109+
.map_err(|source| IssueTokenError::BatchFinalizationFailed {
110+
token_type: default_token_type,
111+
source,
112+
})?;
91113

92114
let mut tokens = Vec::new();
93115

src/amortized_tokens/server.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ impl<CS: PrivateCipherSuite> Server<CS> {
3030
<CS::Group as Group>::Scalar: Send + Sync,
3131
<CS::Group as Group>::Elem: Send + Sync,
3232
{
33-
VoprfServer::<CS>::new_from_seed(seed, info).map_err(|_| CreateKeypairError::SeedError)
33+
VoprfServer::<CS>::new_from_seed(seed, info)
34+
.map_err(|source| CreateKeypairError::SeedError { source })
3435
}
3536

3637
/// Create a new server. The new server does not contain any key material.
@@ -103,7 +104,10 @@ impl<CS: PrivateCipherSuite> Server<CS> {
103104
token_request: AmortizedBatchTokenRequest<CS>,
104105
) -> Result<AmortizedBatchTokenResponse<CS>, IssueTokenResponseError> {
105106
if token_request.token_type != CS::token_type() {
106-
return Err(IssueTokenResponseError::InvalidTokenType);
107+
return Err(IssueTokenResponseError::InvalidTokenType {
108+
expected: CS::token_type(),
109+
found: token_request.token_type,
110+
});
107111
}
108112
let server = key_store
109113
.get(&token_request.truncated_token_key_id)
@@ -113,7 +117,7 @@ impl<CS: PrivateCipherSuite> Server<CS> {
113117
let mut blinded_elements = Vec::new();
114118
for element in token_request.blinded_elements.iter() {
115119
let blinded_element = BlindedElement::<CS>::deserialize(&element.blinded_element)
116-
.map_err(|_| IssueTokenResponseError::InvalidTokenRequest)?;
120+
.map_err(|source| IssueTokenResponseError::InvalidBlindedMessage { source })?;
117121
blinded_elements.push(blinded_element);
118122
}
119123

@@ -122,7 +126,7 @@ impl<CS: PrivateCipherSuite> Server<CS> {
122126
.collect::<Vec<_>>();
123127
let VoprfServerBatchEvaluateFinishResult { messages, proof } = server
124128
.batch_blind_evaluate_finish(&mut OsRng, blinded_elements.iter(), &prepared_elements)
125-
.map_err(|_| IssueTokenResponseError::InvalidTokenRequest)?;
129+
.map_err(|source| IssueTokenResponseError::BlindEvaluationFailed { source })?;
126130

127131
let evaluated_elements = messages
128132
.map(|m| super::EvaluatedElement {
@@ -149,18 +153,26 @@ impl<CS: PrivateCipherSuite> Server<CS> {
149153
nonce_store: &NS,
150154
token: AmortizedToken<CS>,
151155
) -> Result<(), RedeemTokenError> {
152-
if token.token_type() != CS::token_type() {
153-
return Err(RedeemTokenError::InvalidToken);
156+
let token_type = token.token_type();
157+
if token_type != CS::token_type() {
158+
return Err(RedeemTokenError::TokenTypeMismatch {
159+
expected: CS::token_type(),
160+
found: token_type,
161+
});
154162
}
155163
let auth_len = <<CS::Hash as OutputSizeUser>::OutputSize as Unsigned>::USIZE;
156-
if token.authenticator().len() != auth_len {
157-
return Err(RedeemTokenError::InvalidToken);
164+
let authenticator_len = token.authenticator().len();
165+
if authenticator_len != auth_len {
166+
return Err(RedeemTokenError::InvalidAuthenticatorLength {
167+
expected: auth_len,
168+
found: authenticator_len,
169+
});
158170
}
159171
if nonce_store.exists(&token.nonce()).await {
160172
return Err(RedeemTokenError::DoubleSpending);
161173
}
162174
let token_input = TokenInput {
163-
token_type: token.token_type(),
175+
token_type,
164176
nonce: token.nonce(),
165177
challenge_digest: *token.challenge_digest(),
166178
token_key_id: *token.token_key_id(),
@@ -171,13 +183,16 @@ impl<CS: PrivateCipherSuite> Server<CS> {
171183
.ok_or(RedeemTokenError::KeyIdNotFound)?;
172184
let token_authenticator = server
173185
.evaluate(&token_input.serialize())
174-
.map_err(|_| RedeemTokenError::InvalidToken)?
186+
.map_err(|source| RedeemTokenError::AuthenticatorDerivationFailed {
187+
token_type,
188+
source,
189+
})?
175190
.to_vec();
176191
if token.authenticator() == token_authenticator {
177192
nonce_store.insert(token.nonce()).await;
178193
Ok(())
179194
} else {
180-
Err(RedeemTokenError::InvalidToken)
195+
Err(RedeemTokenError::AuthenticatorMismatch { token_type })
181196
}
182197
}
183198

@@ -193,7 +208,7 @@ impl<CS: PrivateCipherSuite> Server<CS> {
193208
<CS::Group as Group>::Elem: Send + Sync,
194209
{
195210
let server = VoprfServer::<CS>::new_with_key(private_key)
196-
.map_err(|_| CreateKeypairError::SeedError)?;
211+
.map_err(|source| CreateKeypairError::SeedError { source })?;
197212
let public_key = server.get_public_key();
198213
let token_key_id = public_key_to_token_key_id::<CS>(&server.get_public_key());
199214
key_store

src/auth/authenticate.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl TokenChallenge {
136136
}
137137

138138
/// An error that occurred during serialization or deserialization.
139-
#[derive(Error, Debug)]
139+
#[derive(PartialEq, Eq, Error, Debug)]
140140
pub enum SerializationError {
141141
#[error("Invalid TokenChallenge")]
142142
/// Invalid TokenChallenge
@@ -174,7 +174,7 @@ pub fn build_www_authenticate_header(
174174
}
175175

176176
/// Building error for the `Authorization` header values
177-
#[derive(Error, Debug)]
177+
#[derive(PartialEq, Eq, Error, Debug)]
178178
pub enum BuildError {
179179
#[error("Invalid TokenChallenge")]
180180
/// Invalid TokenChallenge

src/auth/authorize.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub fn build_authorization_header<Nk: ArrayLength>(
149149
}
150150

151151
/// Building error for the `Authorization` header values
152-
#[derive(Error, Debug)]
152+
#[derive(PartialEq, Eq, Error, Debug)]
153153
pub enum BuildError {
154154
#[error("Invalid token")]
155155
/// Invalid token
@@ -172,7 +172,7 @@ pub fn parse_authorization_header<Nk: ArrayLength>(
172172
}
173173

174174
/// Parsing error for the `WWW-Authenticate` header values
175-
#[derive(Error, Debug)]
175+
#[derive(PartialEq, Eq, Error, Debug)]
176176
pub enum ParseError {
177177
#[error("Invalid token")]
178178
/// Invalid token

0 commit comments

Comments
 (0)