refactor: add AEAD prove/verify + tag methods (#415)

* refactor: add prove/verify + tag methods

* Update components/aead/src/aes_gcm/mod.rs

Co-authored-by: dan <themighty1@users.noreply.github.com>

---------

Co-authored-by: dan <themighty1@users.noreply.github.com>
This commit is contained in:
sinu.eth
2024-01-17 15:32:02 -08:00
committed by GitHub
parent c4bf57fdbf
commit 84bd7966fe
2 changed files with 152 additions and 66 deletions

View File

@@ -163,6 +163,27 @@ impl MpcAesGcm {
Ok(tag)
}
/// Splits off the tag from the end of the payload and verifies it.
async fn _verify_tag(
&mut self,
explicit_nonce: Vec<u8>,
payload: &mut Vec<u8>,
aad: Vec<u8>,
) -> Result<(), AeadError> {
let purported_tag = payload.split_off(payload.len() - AES_GCM_TAG_LEN);
let tag = self
.compute_tag(explicit_nonce, payload.clone(), aad)
.await?;
// Reject if tag is incorrect.
if tag != purported_tag {
return Err(AeadError::CorruptedTag);
}
Ok(())
}
}
#[async_trait]
@@ -180,6 +201,7 @@ impl Aead for MpcAesGcm {
Ok(())
}
#[cfg_attr(feature = "tracing", tracing::instrument(level = "info", err))]
async fn decode_key_private(&mut self) -> Result<(), AeadError> {
self.aes_ctr
.decode_key_private()
@@ -187,6 +209,7 @@ impl Aead for MpcAesGcm {
.map_err(AeadError::from)
}
#[cfg_attr(feature = "tracing", tracing::instrument(level = "info", err))]
async fn decode_key_blind(&mut self) -> Result<(), AeadError> {
self.aes_ctr
.decode_key_blind()
@@ -198,7 +221,10 @@ impl Aead for MpcAesGcm {
self.aes_ctr.set_transcript_id(id)
}
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", err, ret))]
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(plaintext), err)
)]
async fn encrypt_public(
&mut self,
explicit_nonce: Vec<u8>,
@@ -220,7 +246,10 @@ impl Aead for MpcAesGcm {
Ok(payload)
}
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", err, ret))]
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(plaintext), err)
)]
async fn encrypt_private(
&mut self,
explicit_nonce: Vec<u8>,
@@ -242,7 +271,7 @@ impl Aead for MpcAesGcm {
Ok(payload)
}
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", err, ret))]
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", err))]
async fn encrypt_blind(
&mut self,
explicit_nonce: Vec<u8>,
@@ -264,118 +293,133 @@ impl Aead for MpcAesGcm {
Ok(payload)
}
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", err, ret))]
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(payload), err)
)]
async fn decrypt_public(
&mut self,
explicit_nonce: Vec<u8>,
mut ciphertext: Vec<u8>,
mut payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<Vec<u8>, AeadError> {
let purported_tag = ciphertext.split_off(ciphertext.len() - AES_GCM_TAG_LEN);
let tag = self
.compute_tag(explicit_nonce.clone(), ciphertext.clone(), aad)
self._verify_tag(explicit_nonce.clone(), &mut payload, aad)
.await?;
// Reject if tag is incorrect
if tag != purported_tag {
return Err(AeadError::CorruptedTag);
}
self.aes_ctr
.decrypt_public(explicit_nonce, ciphertext)
.decrypt_public(explicit_nonce, payload)
.map_err(AeadError::from)
.await
}
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", err, ret))]
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(payload), err)
)]
async fn decrypt_private(
&mut self,
explicit_nonce: Vec<u8>,
mut ciphertext: Vec<u8>,
mut payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<Vec<u8>, AeadError> {
let purported_tag = ciphertext.split_off(ciphertext.len() - AES_GCM_TAG_LEN);
let tag = self
.compute_tag(explicit_nonce.clone(), ciphertext.clone(), aad)
self._verify_tag(explicit_nonce.clone(), &mut payload, aad)
.await?;
// Reject if tag is incorrect
if tag != purported_tag {
return Err(AeadError::CorruptedTag);
}
self.aes_ctr
.decrypt_private(explicit_nonce, ciphertext)
.decrypt_private(explicit_nonce, payload)
.map_err(AeadError::from)
.await
}
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", err, ret))]
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(payload), err)
)]
async fn decrypt_blind(
&mut self,
explicit_nonce: Vec<u8>,
mut ciphertext: Vec<u8>,
mut payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<(), AeadError> {
let purported_tag = ciphertext.split_off(ciphertext.len() - AES_GCM_TAG_LEN);
let tag = self
.compute_tag(explicit_nonce.clone(), ciphertext.clone(), aad)
self._verify_tag(explicit_nonce.clone(), &mut payload, aad)
.await?;
// Reject if tag is incorrect
if tag != purported_tag {
return Err(AeadError::CorruptedTag);
}
self.aes_ctr
.decrypt_blind(explicit_nonce, ciphertext)
.decrypt_blind(explicit_nonce, payload)
.map_err(AeadError::from)
.await
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(payload), err)
)]
async fn verify_tag(
&mut self,
explicit_nonce: Vec<u8>,
mut ciphertext: Vec<u8>,
mut payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<(), AeadError> {
let purported_tag = ciphertext.split_off(ciphertext.len() - AES_GCM_TAG_LEN);
let tag = self
.compute_tag(explicit_nonce.clone(), ciphertext, aad)
.await?;
// Reject if tag is incorrect
if tag == purported_tag {
Ok(())
} else {
Err(AeadError::CorruptedTag)
}
self._verify_tag(explicit_nonce.clone(), &mut payload, aad)
.await
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(payload), err)
)]
async fn prove_plaintext(
&mut self,
explicit_nonce: Vec<u8>,
mut ciphertext: Vec<u8>,
mut payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<Vec<u8>, AeadError> {
ciphertext.truncate(ciphertext.len() - AES_GCM_TAG_LEN);
self._verify_tag(explicit_nonce.clone(), &mut payload, aad)
.await?;
self.prove_plaintext_no_tag(explicit_nonce, payload).await
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(ciphertext), err)
)]
async fn prove_plaintext_no_tag(
&mut self,
explicit_nonce: Vec<u8>,
ciphertext: Vec<u8>,
) -> Result<Vec<u8>, AeadError> {
self.aes_ctr
.prove_plaintext(explicit_nonce, ciphertext)
.map_err(AeadError::from)
.await
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(payload), err)
)]
async fn verify_plaintext(
&mut self,
explicit_nonce: Vec<u8>,
mut ciphertext: Vec<u8>,
mut payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<(), AeadError> {
ciphertext.truncate(ciphertext.len() - AES_GCM_TAG_LEN);
self._verify_tag(explicit_nonce.clone(), &mut payload, aad)
.await?;
self.verify_plaintext_no_tag(explicit_nonce, payload).await
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(ciphertext), err)
)]
async fn verify_plaintext_no_tag(
&mut self,
explicit_nonce: Vec<u8>,
ciphertext: Vec<u8>,
) -> Result<(), AeadError> {
self.aes_ctr
.verify_plaintext(explicit_nonce, ciphertext)
.map_err(AeadError::from)

View File

@@ -114,12 +114,12 @@ pub trait Aead: Send {
/// This method checks the authenticity of the ciphertext, tag and additional data.
///
/// * `explicit_nonce` - The explicit nonce to use for decryption.
/// * `ciphertext` - The ciphertext and tag to authenticate and decrypt.
/// * `payload` - The ciphertext and tag to authenticate and decrypt.
/// * `aad` - Additional authenticated data.
async fn decrypt_public(
&mut self,
explicit_nonce: Vec<u8>,
ciphertext: Vec<u8>,
payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<Vec<u8>, AeadError>;
@@ -128,12 +128,12 @@ pub trait Aead: Send {
/// This method checks the authenticity of the ciphertext, tag and additional data.
///
/// * `explicit_nonce` - The explicit nonce to use for decryption.
/// * `ciphertext` - The ciphertext and tag to authenticate and decrypt.
/// * `payload` - The ciphertext and tag to authenticate and decrypt.
/// * `aad` - Additional authenticated data.
async fn decrypt_private(
&mut self,
explicit_nonce: Vec<u8>,
ciphertext: Vec<u8>,
payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<Vec<u8>, AeadError>;
@@ -142,12 +142,12 @@ pub trait Aead: Send {
/// This method checks the authenticity of the ciphertext, tag and additional data.
///
/// * `explicit_nonce` - The explicit nonce to use for decryption.
/// * `ciphertext` - The ciphertext and tag to authenticate and decrypt.
/// * `payload` - The ciphertext and tag to authenticate and decrypt.
/// * `aad` - Additional authenticated data.
async fn decrypt_blind(
&mut self,
explicit_nonce: Vec<u8>,
ciphertext: Vec<u8>,
payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<(), AeadError>;
@@ -156,12 +156,12 @@ pub trait Aead: Send {
/// This method checks the authenticity of the ciphertext, tag and additional data.
///
/// * `explicit_nonce` - The explicit nonce to use for decryption.
/// * `ciphertext` - The ciphertext and tag to authenticate and decrypt.
/// * `payload` - The ciphertext and tag to authenticate and decrypt.
/// * `aad` - Additional authenticated data.
async fn verify_tag(
&mut self,
explicit_nonce: Vec<u8>,
ciphertext: Vec<u8>,
payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<(), AeadError>;
@@ -176,8 +176,32 @@ pub trait Aead: Send {
/// # Arguments
///
/// * `explicit_nonce`: The explicit nonce to use for the keystream.
/// * `ciphertext`: The ciphertext to decrypt and prove.
/// * `payload`: The ciphertext and tag to decrypt and prove.
/// * `aad`: Additional authenticated data.
async fn prove_plaintext(
&mut self,
explicit_nonce: Vec<u8>,
payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<Vec<u8>, AeadError>;
/// Locally decrypts the provided ciphertext and then proves in ZK to the other party(s) that the
/// plaintext is correct.
///
/// Returns the plaintext.
///
/// This method requires this party to know the encryption key, which can be achieved by calling
/// the `decode_key_private` method.
///
/// # WARNING
///
/// This method does not verify the tag of the ciphertext. Only use this if you know what you're doing.
///
/// # Arguments
///
/// * `explicit_nonce`: The explicit nonce to use for the keystream.
/// * `ciphertext`: The ciphertext to decrypt and prove.
async fn prove_plaintext_no_tag(
&mut self,
explicit_nonce: Vec<u8>,
ciphertext: Vec<u8>,
@@ -188,8 +212,26 @@ pub trait Aead: Send {
/// # Arguments
///
/// * `explicit_nonce`: The explicit nonce to use for the keystream.
/// * `ciphertext`: The ciphertext to verify.
/// * `payload`: The ciphertext and tag to verify.
/// * `aad`: Additional authenticated data.
async fn verify_plaintext(
&mut self,
explicit_nonce: Vec<u8>,
payload: Vec<u8>,
aad: Vec<u8>,
) -> Result<(), AeadError>;
/// Verifies the other party(s) can prove they know a plaintext which encrypts to the given ciphertext.
///
/// # WARNING
///
/// This method does not verify the tag of the ciphertext. Only use this if you know what you're doing.
///
/// # Arguments
///
/// * `explicit_nonce`: The explicit nonce to use for the keystream.
/// * `ciphertext`: The ciphertext to verify.
async fn verify_plaintext_no_tag(
&mut self,
explicit_nonce: Vec<u8>,
ciphertext: Vec<u8>,