-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Delete verbose serde impl where macros do
Almost all of the replaced field serializers have serde impls so macros just work.
- Loading branch information
Showing
3 changed files
with
250 additions
and
267 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
use core::fmt; | ||
|
||
use hpke::Kem; | ||
use hpke::{aead::ChaCha20Poly1305, kem::SecpK256HkdfSha256}; | ||
use hpke::{kdf::HkdfSha256, rand_core::OsRng}; | ||
|
||
pub const PADDED_MESSAGE_BYTES: usize = 7168; // 7KB | ||
pub const INFO_A: &[u8] = b"Payjoin v2 Message A"; | ||
pub const INFO_B: &[u8] = b"Payjoin v2 Message B"; | ||
|
||
#[derive(Clone, PartialEq, Eq)] | ||
pub struct HpkeSecretKey(pub <SecpK256HkdfSha256 as hpke::Kem>::PrivateKey); | ||
|
||
impl core::fmt::Debug for HpkeSecretKey { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
use hpke::Serializable; | ||
write!(f, "SecpHpkeSecretKey") | ||
} | ||
} | ||
|
||
impl serde::Serialize for HpkeSecretKey { | ||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
where | ||
S: serde::Serializer, | ||
{ | ||
use hpke::Serializable; | ||
serializer.serialize_bytes(&self.0.to_bytes().to_vec()) | ||
} | ||
} | ||
|
||
impl<'de> serde::Deserialize<'de> for HpkeSecretKey { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
D: serde::Deserializer<'de>, | ||
{ | ||
use hpke::Deserializable; | ||
let bytes = Vec::<u8>::deserialize(deserializer)?; | ||
Ok(HpkeSecretKey(<SecpK256HkdfSha256 as hpke::Kem>::PrivateKey::from_bytes(&bytes).map_err(|_| serde::de::Error::custom("Invalid secret key"))?)) | ||
} | ||
} | ||
|
||
#[derive(Clone, PartialEq, Eq)] | ||
pub struct HpkePublicKey(pub <SecpK256HkdfSha256 as hpke::Kem>::PublicKey); | ||
|
||
impl core::fmt::Debug for HpkePublicKey { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "SecpHpkePublicKey({:?})", self.0) | ||
} | ||
} | ||
|
||
impl serde::Serialize for HpkePublicKey { | ||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
where | ||
S: serde::Serializer, | ||
{ | ||
use hpke::Serializable; | ||
serializer.serialize_bytes(&self.0.to_bytes().to_vec()) | ||
} | ||
} | ||
|
||
impl<'de> serde::Deserialize<'de> for HpkePublicKey { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
D: serde::Deserializer<'de>, | ||
{ | ||
use hpke::Deserializable; | ||
let bytes = Vec::<u8>::deserialize(deserializer)?; | ||
Ok(HpkePublicKey(<SecpK256HkdfSha256 as hpke::Kem>::PublicKey::from_bytes(&bytes).map_err(|_| serde::de::Error::custom("Invalid public key"))?)) | ||
} | ||
} | ||
|
||
#[cfg(feature = "send")] | ||
pub fn encrypt_message_a_hpke( | ||
plaintext: Vec<u8>, | ||
e_sec: &HpkeSecretKey, | ||
rs: &HpkePublicKey, | ||
) -> Result<Vec<u8>, HpkeError> { | ||
use hpke::{OpModeS, Serializable}; | ||
|
||
let pk = <SecpK256HkdfSha256 as hpke::Kem>::sk_to_pk(&e_sec.0); | ||
let (encapsulated_key, mut encryption_context) = hpke::setup_sender::< | ||
ChaCha20Poly1305, | ||
HkdfSha256, | ||
SecpK256HkdfSha256, | ||
_, | ||
>(&OpModeS::Auth((e_sec.0.clone(), pk.clone())), &rs.0, INFO_A, &mut OsRng)?; | ||
let aad = pk.to_bytes().to_vec(); | ||
let ciphertext: Vec<u8> = encryption_context.seal(&plaintext, &aad)?; | ||
let mut message_a = encapsulated_key.to_bytes().to_vec(); | ||
message_a.extend(&aad); | ||
message_a.extend(&ciphertext); | ||
//TODO let message_a = pad(&mut message_a).expect("TODO: handle error"); | ||
Ok(message_a.to_vec()) | ||
} | ||
|
||
#[cfg(feature = "receive")] | ||
pub fn decrypt_message_a_hpke( | ||
message_a: &[u8], | ||
s: HpkeSecretKey, | ||
) -> Result<(Vec<u8>, <SecpK256HkdfSha256 as hpke::Kem>::EncappedKey), HpkeError> { | ||
use hpke::{OpModeR, Deserializable}; | ||
// Extract the encapsulated key (65 bytes) | ||
let enc = message_a.get(..65).ok_or(HpkeError::PayloadTooShort)?; | ||
let enc = <SecpK256HkdfSha256 as hpke::Kem>::EncappedKey::from_bytes(enc)?; | ||
|
||
// Extract the sender's public key (AAD, 65 bytes) | ||
let aad = message_a.get(65..130).ok_or(HpkeError::PayloadTooShort)?; | ||
let pk_s = <SecpK256HkdfSha256 as hpke::Kem>::PublicKey::from_bytes(aad)?; | ||
|
||
let mut decryption_ctx = hpke::setup_receiver::< | ||
ChaCha20Poly1305, | ||
HkdfSha256, | ||
SecpK256HkdfSha256, | ||
>(&OpModeR::Auth(pk_s), &s.0, &enc, INFO_A)?; | ||
|
||
// The ciphertext is the remainder of the message | ||
let ciphertext = message_a.get(130..).ok_or(HpkeError::PayloadTooShort)?; | ||
let plaintext = decryption_ctx.open(ciphertext, aad)?; | ||
|
||
Ok((plaintext, enc)) | ||
} | ||
|
||
// #[cfg(feature = "receive")] | ||
// pub fn encrypt_message_b(raw_msg: &mut Vec<u8>, re_pub: PublicKey) -> Result<Vec<u8>, HpkeError> { | ||
// // let message b = [pubkey/AD][nonce][authentication tag][ciphertext] | ||
// let secp = Secp256k1::new(); | ||
// let (e_sec, e_pub) = secp.generate_keypair(&mut OsRng); | ||
// let ee = SharedSecret::new(&re_pub, &e_sec); | ||
// let cipher = ChaCha20Poly1305::new_from_slice(&ee.secret_bytes()) | ||
// .map_err(|_| HpkeError::InvalidKeyLength)?; | ||
// let nonce = Nonce::from_slice(&[0u8; 12]); // key es encrypts only 1 message so 0 is unique | ||
// let aad = &e_pub.serialize(); | ||
// let msg = pad(raw_msg)?; | ||
// let payload = Payload { msg, aad }; | ||
// let c_t = cipher.encrypt(nonce, payload)?; | ||
// let mut message_b = e_pub.serialize().to_vec(); | ||
// message_b.extend(&nonce[..]); | ||
// message_b.extend(&c_t[..]); | ||
// Ok(message_b) | ||
// } | ||
|
||
#[cfg(feature = "receive")] | ||
pub fn encrypt_message_b_hpke( | ||
plaintext: Vec<u8>, | ||
s_pair: (HpkeSecretKey, HpkePublicKey), | ||
re_pub: &HpkePublicKey, | ||
) -> Result<Vec<u8>, HpkeError> { | ||
use hpke::{OpModeS, Serializable}; | ||
|
||
let (encapsulated_key, mut encryption_context) = hpke::setup_sender::< | ||
ChaCha20Poly1305, | ||
HkdfSha256, | ||
SecpK256HkdfSha256, | ||
_, | ||
>(&OpModeS::Auth((s_pair.0.0, s_pair.1.0.clone())), &re_pub.0, INFO_B, &mut OsRng)?; | ||
let aad = s_pair.1.0.to_bytes().to_vec(); | ||
let ciphertext: Vec<u8> = encryption_context.seal(&plaintext, &aad)?; | ||
let mut message_b = encapsulated_key.to_bytes().to_vec(); | ||
println!("message_b encapped_key: {:?}", message_b); | ||
message_b.extend(&aad); | ||
message_b.extend(&ciphertext); | ||
//let message_b = pad(&mut message_b).expect("TODO: handle error"); | ||
Ok(message_b.to_vec()) | ||
} | ||
|
||
#[cfg(feature = "send")] | ||
pub fn decrypt_message_b_hpke( | ||
message_b: &[u8], | ||
s: HpkeSecretKey, | ||
) -> Result<Vec<u8>, HpkeError> { | ||
use hpke::{OpModeR, Deserializable, Serializable}; | ||
|
||
let enc = message_b.get(..65).ok_or(HpkeError::PayloadTooShort)?; | ||
println!("message_b enc: {:?}", enc); | ||
let enc = <SecpK256HkdfSha256 as hpke::Kem>::EncappedKey::from_bytes(&enc).unwrap(); | ||
let aad = message_b.get(65..130).ok_or(HpkeError::PayloadTooShort)?; | ||
let pk_s = <SecpK256HkdfSha256 as hpke::Kem>::PublicKey::from_bytes(aad).unwrap(); | ||
let mut decryption_ctx = hpke::setup_receiver::< | ||
ChaCha20Poly1305, | ||
HkdfSha256, | ||
SecpK256HkdfSha256, | ||
>(&OpModeR::Auth(pk_s), &s.0, &enc, INFO_B)?; | ||
|
||
let plaintext = decryption_ctx.open(message_b.get(130..).ok_or(HpkeError::PayloadTooShort)?, &aad)?; | ||
Ok(plaintext) | ||
} | ||
|
||
fn pad(msg: &mut Vec<u8>) -> Result<&[u8], HpkeError> { | ||
if msg.len() > PADDED_MESSAGE_BYTES { | ||
return Err(HpkeError::PayloadTooLarge); | ||
} | ||
while msg.len() < PADDED_MESSAGE_BYTES { | ||
msg.push(0); | ||
} | ||
Ok(msg) | ||
} | ||
|
||
/// Error from de/encrypting a v2 Hybrid Public Key Encryption payload. | ||
#[derive(Debug)] | ||
pub enum HpkeError { | ||
Hpke(hpke::HpkeError), | ||
InvalidKeyLength, | ||
PayloadTooLarge, | ||
PayloadTooShort, | ||
} | ||
|
||
impl From<hpke::HpkeError> for HpkeError { | ||
fn from(value: hpke::HpkeError) -> Self { Self::Hpke(value) } | ||
} | ||
|
||
impl fmt::Display for HpkeError { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
use HpkeError::*; | ||
|
||
match &self { | ||
Hpke(e) => e.fmt(f), | ||
InvalidKeyLength => write!(f, "Invalid Length"), | ||
PayloadTooLarge => | ||
write!(f, "Payload too large, max size is {} bytes", PADDED_MESSAGE_BYTES), | ||
PayloadTooShort => write!(f, "Payload too small"), | ||
} | ||
} | ||
} | ||
|
||
impl std::error::Error for HpkeError { | ||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { | ||
use HpkeError::*; | ||
|
||
match &self { | ||
Hpke(e) => Some(e), | ||
InvalidKeyLength | PayloadTooLarge | PayloadTooShort => None, | ||
} | ||
} | ||
} |
Oops, something went wrong.