wamu_core/
wrappers.rs

1//! Convenience wrappers around core sub-protocols.
2
3use 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
11/// Given random bytes and an identity provider, returns the verifying key and a signature of the random bytes.
12///
13/// **NOTE:** random bytes are prefixed with a predefined phrase before signing.
14pub 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
22/// Given random bytes, a verifying key for the sending party, a signature of the random bytes and
23/// a list of verifying keys for the other parties,
24/// returns an ok result for a valid request or an appropriate error result for an invalid request.
25///
26/// **NOTE:** random bytes are prefixed with a predefined phrase before signing.
27pub 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        // Sender must be a verified party.
35        Err(Error::UnauthorizedParty)
36    } else {
37        // Signature must be valid.
38        Ok(crypto::verify_signature(
39            verifying_key,
40            &utils::prefix_message_bytes(random_bytes),
41            signature,
42        )?)
43    }
44}
45
46/// Given a "command", an identity authenticated request payload and a list of verifying keys for the other parties,
47/// returns an ok result with a challenge fragment for initiating an identity challenge for a valid request
48/// or an appropriate error result for an invalid request.s
49pub 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        // Command doesn't match request payload.
56        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        // Generates identity provider.
72        let identity_provider = MockECDSAIdentityProvider::generate();
73
74        // Sets the random bytes.
75        let random_bytes = b"random";
76
77        // Generates verifying key and random bytes signature.
78        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            // Valid request from a verified party should be ok.
83            (vec![identity_provider.verifying_key()], &signature, Ok(())),
84            // Request from an unverified party should fail.
85            (vec![], &signature, Err(Error::UnauthorizedParty)),
86            // Request with an invalid signature should fail.
87            (
88                vec![identity_provider.verifying_key()],
89                &identity_provider.sign(b"Hello, world!"),
90                Err(Error::Crypto(CryptoError::InvalidSignature)),
91            ),
92        ] {
93            // Verifies random bytes signature using verifying key.
94            let result = verify_request_with_signature(
95                random_bytes,
96                &verifying_key,
97                signature_to_verify,
98                &verified_parties,
99            );
100
101            // Verifies expected result.
102            assert_eq!(result, expected_result);
103        }
104    }
105}