1use crate::crypto::{Random32Bytes, Signature, VerifyingKey};
4use crate::errors::{Error, IdentityAuthedRequestError};
5use crate::identity_authed_request;
6use crate::identity_challenge;
7use crate::payloads::IdentityAuthedRequestPayload;
8use crate::traits::IdentityProvider;
9use crate::{crypto, utils};
10
11pub fn initiate_request_with_signature(
15 random_bytes: &[u8],
16 identity_provider: &impl IdentityProvider,
17) -> (VerifyingKey, Signature) {
18 let signature = identity_provider.sign(&utils::prefix_message_bytes(random_bytes));
19 (identity_provider.verifying_key(), signature)
20}
21
22pub fn verify_request_with_signature(
28 random_bytes: &[u8],
29 verifying_key: &VerifyingKey,
30 signature: &Signature,
31 verified_parties: &[VerifyingKey],
32) -> Result<(), Error> {
33 if !verified_parties.contains(verifying_key) {
34 Err(Error::UnauthorizedParty)
36 } else {
37 Ok(crypto::verify_signature(
39 verifying_key,
40 &utils::prefix_message_bytes(random_bytes),
41 signature,
42 )?)
43 }
44}
45
46pub fn verify_identity_authed_request_and_initiate_challenge(
50 command: &str,
51 request: &IdentityAuthedRequestPayload,
52 verified_parties: &[VerifyingKey],
53) -> Result<Random32Bytes, IdentityAuthedRequestError> {
54 if command != request.command {
55 Err(IdentityAuthedRequestError::CommandMismatch)
57 } else {
58 identity_authed_request::verify(request, verified_parties)?;
59 Ok(identity_challenge::initiate())
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use crate::errors::CryptoError;
67 use crate::test_utils::MockECDSAIdentityProvider;
68
69 #[test]
70 fn initiate_and_verify_request_with_signature_works() {
71 let identity_provider = MockECDSAIdentityProvider::generate();
73
74 let random_bytes = b"random";
76
77 let (verifying_key, signature) =
79 initiate_request_with_signature(random_bytes, &identity_provider);
80
81 for (verified_parties, signature_to_verify, expected_result) in [
82 (vec![identity_provider.verifying_key()], &signature, Ok(())),
84 (vec![], &signature, Err(Error::UnauthorizedParty)),
86 (
88 vec![identity_provider.verifying_key()],
89 &identity_provider.sign(b"Hello, world!"),
90 Err(Error::Crypto(CryptoError::InvalidSignature)),
91 ),
92 ] {
93 let result = verify_request_with_signature(
95 random_bytes,
96 &verifying_key,
97 signature_to_verify,
98 &verified_parties,
99 );
100
101 assert_eq!(result, expected_result);
103 }
104 }
105}