Skip to content

Commit

Permalink
Remove PKCS#7 padding when decrypting
Browse files Browse the repository at this point in the history
  • Loading branch information
dbrgn committed Apr 1, 2021
1 parent d2c7bea commit 8225ec2
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Possible log types:
- [added] New `to_hex_string` method on `RecipientKey`
- [removed] Removed `Into<String>` impl for `RecipientKey`, use `to_hex_string` method instead
- [changed] The `lookup_pubkey` function now returns a `PublicKey`, not a `String`
- [changed] `CryptoError` type has two new error variants: `BadNonce` and
- [changed] `CryptoError` type has two new error variants: `BadNonce`, `BadPadding` and
`DecryptionFailed`

### v0.14.1 (2021-03-27)
Expand Down
2 changes: 2 additions & 0 deletions src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ pub fn encrypt_raw(
}

/// Encrypt a message for the recipient.
///
/// The encrypted data will include PKCS#7 style random padding.
pub fn encrypt(
data: &[u8],
msgtype: MessageType,
Expand Down
4 changes: 4 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ pub enum CryptoError {
#[error("bad nonce")]
BadNonce,

/// Invalid PKCS#7 padding
#[error("invalid padding")]
BadPadding,

/// Decryption failed
#[error("decryption failed")]
DecryptionFailed,
Expand Down
55 changes: 51 additions & 4 deletions src/receive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,33 @@ impl IncomingMessage {
Ok(msg)
}

/// Decrypt the box using the specified keys.
/// Decrypt the box using the specified keys and remove padding.
///
/// The public key belongs to the sender in the `from` field. The private
/// key belongs to the gateway ID in the `to` field.
///
/// The PKCS#7 padding will be removed. If the padding is missing or
/// invalid, an [`CryptoError::BadPadding`] will be returned.
pub fn decrypt_box(
&self,
public_key: &PublicKey,
private_key: &SecretKey,
) -> Result<Vec<u8>, CryptoError> {
// Decode nonce
let nonce: Nonce = Nonce::from_slice(&self.nonce).ok_or(CryptoError::BadNonce)?;
box_::open(&self.box_data, &nonce, &public_key, &private_key)
.map_err(|_| CryptoError::DecryptionFailed)

// Decrypt bytes
let mut decrypted = box_::open(&self.box_data, &nonce, &public_key, &private_key)
.map_err(|_| CryptoError::DecryptionFailed)?;

// Remove PKCS#7 style padding
let padding_amount = decrypted.last().cloned().ok_or(CryptoError::BadPadding)? as usize;
if padding_amount >= decrypted.len() {
return Err(CryptoError::BadPadding);
}
decrypted.resize(decrypted.len() - padding_amount, 0);

Ok(decrypted)
}
}

Expand Down Expand Up @@ -103,7 +118,12 @@ mod tests {
message_id: "00112233".into(),
date: 0,
nonce: nonce.0.to_vec(),
box_data: box_::seal(&[1, 2, 42], &nonce, &b_pk, &a_sk),
box_data: box_::seal(
&[/* data */ 1, 2, 42, /* padding */ 3, 3, 3],
&nonce,
&b_pk,
&a_sk,
),
mac: vec![0],
nickname: None,
};
Expand Down Expand Up @@ -134,5 +154,32 @@ mod tests {
let err = msg.decrypt_box(&pk, &sk).unwrap_err();
assert_eq!(err, CryptoError::BadNonce);
}

#[test]
fn decrypt_bad_padding() {
let (a_pk, a_sk) = box_::gen_keypair();
let (b_pk, b_sk) = box_::gen_keypair();
let nonce = box_::gen_nonce();

let msg = IncomingMessage {
from: "AAAAAAAA".into(),
to: "*BBBBBBB".into(),
message_id: "00112233".into(),
date: 0,
nonce: nonce.0.to_vec(),
box_data: box_::seal(
&[/* data */ 1, 2, 42 /* no padding */],
&nonce,
&b_pk,
&a_sk,
),
mac: vec![0],
nickname: None,
};

// Bad padding
let err = msg.decrypt_box(&a_pk, &b_sk).unwrap_err();
assert_eq!(err, CryptoError::BadPadding);
}
}
}

0 comments on commit 8225ec2

Please sign in to comment.