Skip to content

Commit

Permalink
[WIP] try using body array arg for pad plaintext
Browse files Browse the repository at this point in the history
  • Loading branch information
benalleng committed Feb 21, 2025
1 parent f92af6c commit a03fa73
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 41 deletions.
81 changes: 59 additions & 22 deletions payjoin/src/hpke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl<'de> serde::Deserialize<'de> for HpkePublicKey {

/// Message A is sent from the sender to the receiver containing an Original PSBT payload
pub fn encrypt_message_a(
body: &[u8; PADDED_PLAINTEXT_A_LENGTH],
body: [u8; PADDED_PLAINTEXT_A_LENGTH],
reply_pk: &HpkePublicKey,
receiver_pk: &HpkePublicKey,
) -> Result<Vec<u8>, HpkeError> {
Expand All @@ -181,6 +181,8 @@ pub fn encrypt_message_a(
INFO_A,
&mut OsRng,
)?;
let mut body = body;
pad_plaintext_a(&mut body)?;
let mut plaintext = compressed_bytes_from_pubkey(reply_pk).to_vec();
plaintext.extend(body);
let ciphertext = encryption_context.seal(&plaintext, &[])?;
Expand Down Expand Up @@ -220,7 +222,7 @@ pub fn decrypt_message_a(

/// Message B is sent from the receiver to the sender containing a Payjoin PSBT payload or an error
pub fn encrypt_message_b(
plaintext: &[u8; PADDED_PLAINTEXT_B_LENGTH],
mut body: [u8; PADDED_PLAINTEXT_B_LENGTH],
receiver_keypair: &HpkeKeyPair,
sender_pk: &HpkePublicKey,
) -> Result<Vec<u8>, HpkeError> {
Expand All @@ -234,6 +236,7 @@ pub fn encrypt_message_b(
INFO_B,
&mut OsRng,
)?;
let plaintext = pad_plaintext_b(&mut body)?;
let ciphertext = encryption_context.seal(plaintext, &[])?;
let mut message_b = ellswift_bytes_from_encapped_key(&encapsulated_key)?.to_vec();
message_b.extend(&ciphertext);
Expand All @@ -257,6 +260,48 @@ pub fn decrypt_message_b(
Ok(plaintext)
}

fn pad_plaintext_a(
msg: &mut [u8; PADDED_PLAINTEXT_A_LENGTH],
) -> Result<&[u8; PADDED_PLAINTEXT_A_LENGTH], HpkeError> {
if msg.len() > PADDED_PLAINTEXT_A_LENGTH {
return Err(HpkeError::PayloadTooLarge {
actual: msg.len(),
max: PADDED_PLAINTEXT_A_LENGTH,
});
}
let len_to_copy = msg.len().min(PADDED_PLAINTEXT_A_LENGTH);

let mut temp = [0; PADDED_PLAINTEXT_A_LENGTH];
temp[..len_to_copy].copy_from_slice(&msg[..len_to_copy]);

msg.fill(0);

msg[..len_to_copy].copy_from_slice(&temp[..len_to_copy]);

Ok(msg)
}

fn pad_plaintext_b(
msg: &mut [u8; PADDED_PLAINTEXT_B_LENGTH],
) -> Result<&[u8; PADDED_PLAINTEXT_B_LENGTH], HpkeError> {
if msg.len() > PADDED_PLAINTEXT_B_LENGTH {
return Err(HpkeError::PayloadTooLarge {
actual: msg.len(),
max: PADDED_PLAINTEXT_B_LENGTH,
});
}
let len_to_copy = msg.len().min(PADDED_PLAINTEXT_B_LENGTH);

let mut temp = [0; PADDED_PLAINTEXT_B_LENGTH];
temp[..len_to_copy].copy_from_slice(&msg[..len_to_copy]);

msg.fill(0);

msg[..len_to_copy].copy_from_slice(&temp[..len_to_copy]);

Ok(msg)
}

/// Error from de/encrypting a v2 Hybrid Public Key Encryption payload.
#[derive(Debug, PartialEq)]
pub enum HpkeError {
Expand Down Expand Up @@ -319,12 +364,9 @@ mod test {
let reply_keypair = HpkeKeyPair::gen_keypair();
let receiver_keypair = HpkeKeyPair::gen_keypair();

let message_a = encrypt_message_a(
&plaintext,
reply_keypair.public_key(),
receiver_keypair.public_key(),
)
.expect("encryption should work");
let message_a =
encrypt_message_a(plaintext, reply_keypair.public_key(), receiver_keypair.public_key())
.expect("encryption should work");
assert_eq!(message_a.len(), PADDED_MESSAGE_BYTES);

let decrypted = decrypt_message_a(&message_a, receiver_keypair.secret_key().clone())
Expand All @@ -336,12 +378,9 @@ mod test {

// ensure full plaintext round trips
plaintext[PADDED_PLAINTEXT_A_LENGTH - 1] = 42;
let message_a = encrypt_message_a(
&plaintext,
reply_keypair.public_key(),
receiver_keypair.public_key(),
)
.expect("encryption should work");
let message_a =
encrypt_message_a(plaintext, reply_keypair.public_key(), receiver_keypair.public_key())
.expect("encryption should work");

let decrypted = decrypt_message_a(&message_a, receiver_keypair.secret_key().clone())
.expect("decryption should work");
Expand Down Expand Up @@ -376,9 +415,8 @@ mod test {
let reply_keypair = HpkeKeyPair::gen_keypair();
let receiver_keypair = HpkeKeyPair::gen_keypair();

let message_b =
encrypt_message_b(&plaintext, &receiver_keypair, reply_keypair.public_key())
.expect("encryption should work");
let message_b = encrypt_message_b(plaintext, &receiver_keypair, reply_keypair.public_key())
.expect("encryption should work");

assert_eq!(message_b.len(), PADDED_MESSAGE_BYTES);

Expand All @@ -393,9 +431,8 @@ mod test {
assert_eq!(decrypted, plaintext.to_vec());

plaintext[PADDED_PLAINTEXT_B_LENGTH - 1] = 42;
let message_b =
encrypt_message_b(&plaintext, &receiver_keypair, reply_keypair.public_key())
.expect("encryption should work");
let message_b = encrypt_message_b(plaintext, &receiver_keypair, reply_keypair.public_key())
.expect("encryption should work");

assert_eq!(message_b.len(), PADDED_MESSAGE_BYTES);

Expand Down Expand Up @@ -466,15 +503,15 @@ mod test {

let plaintext_a = [0u8; PADDED_PLAINTEXT_A_LENGTH];
let message_a = encrypt_message_a(
&plaintext_a,
plaintext_a,
reply_keypair.public_key(),
receiver_keypair.public_key(),
)
.expect("encryption should work");

let plaintext_b = [0u8; PADDED_PLAINTEXT_B_LENGTH];
let message_b =
encrypt_message_b(&plaintext_b, &receiver_keypair, sender_keypair.public_key())
encrypt_message_b(plaintext_b, &receiver_keypair, sender_keypair.public_key())
.expect("encryption should work");

messages_a.push(message_a);
Expand Down
12 changes: 3 additions & 9 deletions payjoin/src/receive/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::{
v1, ImplementationError, InternalPayloadError, JsonError, OutputSubstitutionError,
ReplyableError, SelectionError,
};
use crate::hpke::{decrypt_message_a, encrypt_message_b, HpkeError, HpkeKeyPair, HpkePublicKey};
use crate::hpke::{decrypt_message_a, encrypt_message_b, HpkeKeyPair, HpkePublicKey};
use crate::ohttp::{ohttp_decapsulate, ohttp_encapsulate, OhttpEncapsulationError, OhttpKeys};
use crate::receive::{parse_payload, InputPair};
use crate::uri::ShortId;
Expand Down Expand Up @@ -505,14 +505,8 @@ impl PayjoinProposal {
.map_err(|e| ReplyableError::Implementation(e.into()))?;
payjoin_bytes.resize(PADDED_PLAINTEXT_B_LENGTH, 0);

body = encrypt_message_b(
&payjoin_bytes.clone().try_into().map_err(|_| HpkeError::PayloadTooLarge {
actual: payjoin_bytes.len(),
max: PADDED_PLAINTEXT_B_LENGTH,
})?,
&self.context.s,
e,
)?;
body =
encrypt_message_b(payjoin_bytes.clone().try_into().unwrap(), &self.context.s, e)?;
method = "POST";
} else {
// Prepare v2 wrapped and backwards-compatible v1 payload
Expand Down
13 changes: 3 additions & 10 deletions payjoin/src/send/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ use url::Url;

use super::error::BuildSenderError;
use super::*;
use crate::hpke::{
decrypt_message_b, encrypt_message_a, HpkeError, HpkeSecretKey, PADDED_PLAINTEXT_A_LENGTH,
};
use crate::hpke::{decrypt_message_b, encrypt_message_a, HpkeSecretKey, PADDED_PLAINTEXT_A_LENGTH};
use crate::ohttp::{ohttp_decapsulate, ohttp_encapsulate};
use crate::send::v1;
use crate::uri::{ShortId, UrlExt};
Expand Down Expand Up @@ -161,12 +159,7 @@ impl Sender {

let hpke_ctx = HpkeContext::new(rs, &self.reply_key);
let body = encrypt_message_a(
&plaintext.clone().try_into().map_err(|_| {
InternalCreateRequestError::Hpke(HpkeError::PayloadTooLarge {
actual: plaintext.len(),
max: PADDED_PLAINTEXT_A_LENGTH,
})
})?,
plaintext.clone().try_into().unwrap(),
&hpke_ctx.reply_pair.public_key().clone(),
&hpke_ctx.receiver.clone(),
)
Expand Down Expand Up @@ -274,7 +267,7 @@ impl V2GetContext {
.join(&subdir.to_string())
.map_err(|e| InternalCreateRequestError::Url(e.into()))?;
let body = encrypt_message_a(
&[0; PADDED_PLAINTEXT_A_LENGTH],
[0; PADDED_PLAINTEXT_A_LENGTH],
&self.hpke_ctx.reply_pair.public_key().clone(),
&self.hpke_ctx.receiver.clone(),
)
Expand Down

0 comments on commit a03fa73

Please sign in to comment.