use crate::crypto::{Random32Bytes, Signature, VerifyingKey};
use crate::errors::{Error, IdentityAuthedRequestError};
use crate::identity_authed_request;
use crate::identity_challenge;
use crate::payloads::IdentityAuthedRequestPayload;
use crate::traits::IdentityProvider;
use crate::{crypto, utils};
pub fn initiate_request_with_signature(
random_bytes: &[u8],
identity_provider: &impl IdentityProvider,
) -> (VerifyingKey, Signature) {
let signature = identity_provider.sign(&utils::prefix_message_bytes(random_bytes));
(identity_provider.verifying_key(), signature)
}
pub fn verify_request_with_signature(
random_bytes: &[u8],
verifying_key: &VerifyingKey,
signature: &Signature,
verified_parties: &[VerifyingKey],
) -> Result<(), Error> {
if !verified_parties.contains(verifying_key) {
Err(Error::UnauthorizedParty)
} else {
Ok(crypto::verify_signature(
verifying_key,
&utils::prefix_message_bytes(random_bytes),
signature,
)?)
}
}
pub fn verify_identity_authed_request_and_initiate_challenge(
command: &str,
request: &IdentityAuthedRequestPayload,
verified_parties: &[VerifyingKey],
) -> Result<Random32Bytes, IdentityAuthedRequestError> {
if command != request.command {
Err(IdentityAuthedRequestError::CommandMismatch)
} else {
identity_authed_request::verify(request, verified_parties)?;
Ok(identity_challenge::initiate())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::errors::CryptoError;
use crate::test_utils::MockECDSAIdentityProvider;
#[test]
fn initiate_and_verify_request_with_signature_works() {
let identity_provider = MockECDSAIdentityProvider::generate();
let random_bytes = b"random";
let (verifying_key, signature) =
initiate_request_with_signature(random_bytes, &identity_provider);
for (verified_parties, signature_to_verify, expected_result) in [
(vec![identity_provider.verifying_key()], &signature, Ok(())),
(vec![], &signature, Err(Error::UnauthorizedParty)),
(
vec![identity_provider.verifying_key()],
&identity_provider.sign(b"Hello, world!"),
Err(Error::Crypto(CryptoError::InvalidSignature)),
),
] {
let result = verify_request_with_signature(
random_bytes,
&verifying_key,
signature_to_verify,
&verified_parties,
);
assert_eq!(result, expected_result);
}
}
}