Skip to content

Commit

Permalink
Refactor out a shared compute authenticated sender and computer desti…
Browse files Browse the repository at this point in the history
…nation function (#3275)

* Refactor compute authenticated sender memo and compute destination memo.
Add new AuthenticatedSenderWithData and DestinationWithData memo types per MCIP#60

Clean up match statement and add new memo with data types to sample paykit memo handler

Removing with data types due to discussion on mcip/60

Update dependencies to get cd to pass

Update dependencies to get cd to pass

* Refactor compute authenticated sender memo and compute destination memo.
Add new AuthenticatedSenderWithData and DestinationWithData memo types per MCIP#60

Clean up match statement and add new memo with data types to sample paykit memo handler

Removing with data types due to discussion on mcip/60

Update dependencies to get cd to pass

Update dependencies to get cd to pass
  • Loading branch information
wjuan-mob authored and NotGyro committed Apr 7, 2023
1 parent be4fd13 commit 7651276
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 121 deletions.
44 changes: 22 additions & 22 deletions fog/sample-paykit/src/cached_tx_data/memo_handler.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2018-2022 The MobileCoin Foundation
// Copyright (c) 2018-2023 The MobileCoin Foundation

//! A memo handler object which processes memos, for use in integration tests
Expand Down Expand Up @@ -86,7 +86,7 @@ impl MemoHandler {
Err(MemoHandlerError::UnknownSender)
}
}
MemoType::AuthenticatedSenderWithPaymentRequestId(memo) => {
MemoType::AuthenticatedSenderWithPaymentIntentId(memo) => {
if let Some(addr) = self.contacts.get(&memo.sender_address_hash()) {
if bool::from(memo.validate(
addr,
Expand All @@ -101,26 +101,7 @@ impl MemoHandler {
Err(MemoHandlerError::UnknownSender)
}
}
MemoType::Destination(_) => {
if subaddress_matches_tx_out(account_key, CHANGE_SUBADDRESS_INDEX, tx_out)? {
Ok(Some(memo_type))
} else {
Err(MemoHandlerError::FailedSubaddressValidation)
}
}
MemoType::GiftCodeCancellation(_) => {
// TODO: Add Gift Code Memo Validation
Ok(Some(memo_type))
}
MemoType::GiftCodeFunding(_) => {
// TODO: Add Gift Code Memo Validation
Ok(Some(memo_type))
}
MemoType::GiftCodeSender(_) => {
// TODO: Add Gift Code Validation
Ok(Some(memo_type))
}
MemoType::AuthenticatedSenderWithPaymentIntentId(memo) => {
MemoType::AuthenticatedSenderWithPaymentRequestId(memo) => {
if let Some(addr) = self.contacts.get(&memo.sender_address_hash()) {
if bool::from(memo.validate(
addr,
Expand All @@ -135,6 +116,13 @@ impl MemoHandler {
Err(MemoHandlerError::UnknownSender)
}
}
MemoType::Destination(_) => {
if subaddress_matches_tx_out(account_key, CHANGE_SUBADDRESS_INDEX, tx_out)? {
Ok(Some(memo_type))
} else {
Err(MemoHandlerError::FailedSubaddressValidation)
}
}
MemoType::DestinationWithPaymentRequestId(_) => {
if subaddress_matches_tx_out(account_key, CHANGE_SUBADDRESS_INDEX, tx_out)? {
Ok(Some(memo_type))
Expand All @@ -156,6 +144,18 @@ impl MemoHandler {
Err(MemoHandlerError::FailedSubaddressValidation)
}
}
MemoType::GiftCodeCancellation(_) => {
// TODO: Add Gift Code Memo Validation
Ok(Some(memo_type))
}
MemoType::GiftCodeFunding(_) => {
// TODO: Add Gift Code Memo Validation
Ok(Some(memo_type))
}
MemoType::GiftCodeSender(_) => {
// TODO: Add Gift Code Validation
Ok(Some(memo_type))
}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions transaction/extra/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ mod tx_out_gift_code;
mod unsigned_tx;

pub use memo::{
AuthenticatedSenderMemo, AuthenticatedSenderWithPaymentIntentIdMemo,
AuthenticatedSenderWithPaymentRequestIdMemo, BurnRedemptionMemo, DefragmentationMemo,
DefragmentationMemoError, DestinationMemo, DestinationMemoError,
DestinationWithPaymentIntentIdMemo, DestinationWithPaymentRequestIdMemo,
compute_authenticated_sender_memo, compute_destination_memo, AuthenticatedSenderMemo,
AuthenticatedSenderWithPaymentIntentIdMemo, AuthenticatedSenderWithPaymentRequestIdMemo,
BurnRedemptionMemo, DefragmentationMemo, DefragmentationMemoError, DestinationMemo,
DestinationMemoError, DestinationWithPaymentIntentIdMemo, DestinationWithPaymentRequestIdMemo,
GiftCodeCancellationMemo, GiftCodeFundingMemo, GiftCodeSenderMemo, MemoDecodingError, MemoType,
RegisteredMemoType, SenderMemoCredential, UnusedMemo,
};
Expand Down
35 changes: 33 additions & 2 deletions transaction/extra/src/memo/authenticated_common.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2018-2022 The MobileCoin Foundation
// Copyright (c) 2018-2023 The MobileCoin Foundation

//! HMAC code shared by all category 0x01 memos.
//!
Expand All @@ -7,10 +7,14 @@
use hmac::{Hmac, Mac};
use mc_account_keys::{PublicAddress, ShortAddressHash};
use mc_crypto_keys::{CompressedRistrettoPublic, KexReusablePrivate, RistrettoPrivate};
use mc_crypto_keys::{
CompressedRistrettoPublic, KexReusablePrivate, RistrettoPrivate, RistrettoPublic,
};
use sha2::Sha512;
use subtle::{Choice, ConstantTimeEq};

use crate::SenderMemoCredential;

type HmacSha512 = Hmac<Sha512>;

/// Shared code for memo types in category 0x01, whose last 16 bytes is an HMAC
Expand Down Expand Up @@ -70,3 +74,30 @@ pub fn validate_authenticated_sender(
result &= expected_hmac.ct_eq(&found_hmac);
result
}

/// Shared code for creation of an authenticated sender memo with additional
/// data
pub fn compute_authenticated_sender_memo(
memo_type_bytes: [u8; 2],
cred: &SenderMemoCredential,
receiving_subaddress_view_public_key: &RistrettoPublic,
tx_out_public_key: &CompressedRistrettoPublic,
data: &[u8],
) -> [u8; 64] {
let mut memo_data = [0u8; 64];
memo_data[..16].copy_from_slice(cred.address_hash.as_ref());
memo_data[16..48].copy_from_slice(data);

let shared_secret = cred
.subaddress_spend_private_key
.key_exchange(receiving_subaddress_view_public_key);

let hmac_value = compute_category1_hmac(
shared_secret.as_ref(),
tx_out_public_key,
memo_type_bytes,
&memo_data,
);
memo_data[48..].copy_from_slice(&hmac_value);
memo_data
}
27 changes: 9 additions & 18 deletions transaction/extra/src/memo/authenticated_sender.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
// Copyright (c) 2018-2022 The MobileCoin Foundation
// Copyright (c) 2018-2023 The MobileCoin Foundation

//! Object for 0x0100 Authenticated Sender memo type
//!
//! This was proposed for standardization in mobilecoinfoundation/mcips/pull/4
use super::{
authenticated_common::{compute_category1_hmac, validate_authenticated_sender},
authenticated_common::{compute_authenticated_sender_memo, validate_authenticated_sender},
credential::SenderMemoCredential,
RegisteredMemoType,
};
use crate::impl_memo_type_conversions;
use mc_account_keys::{PublicAddress, ShortAddressHash};
use mc_crypto_keys::{
CompressedRistrettoPublic, KexReusablePrivate, RistrettoPrivate, RistrettoPublic,
};
use mc_crypto_keys::{CompressedRistrettoPublic, RistrettoPrivate, RistrettoPublic};
use subtle::Choice;

/// A memo that the sender writes to convey their identity in an authenticated
Expand Down Expand Up @@ -55,21 +53,14 @@ impl AuthenticatedSenderMemo {
// [0-16) address hash
// [16-48) unused
// [48-64) HMAC

let mut memo_data = [0u8; 64];
memo_data[..16].copy_from_slice(cred.address_hash.as_ref());

let shared_secret = cred
.subaddress_spend_private_key
.key_exchange(receiving_subaddress_view_public_key);

let hmac_value = compute_category1_hmac(
shared_secret.as_ref(),
tx_out_public_key,
let data = [0u8; (48 - 16)];
let memo_data = compute_authenticated_sender_memo(
Self::MEMO_TYPE_BYTES,
&memo_data,
cred,
receiving_subaddress_view_public_key,
tx_out_public_key,
&data,
);
memo_data[48..].copy_from_slice(&hmac_value);

Self { memo_data }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
// Copyright (c) 2018-2022 The MobileCoin Foundation
// Copyright (c) 2018-2023 The MobileCoin Foundation

//! Object for 0x0102 Authenticated Sender With Payment Intent Id memo type
//!
//! This was proposed for standardization in mobilecoinfoundation/mcips/pull/54
use super::{
authenticated_common::{compute_category1_hmac, validate_authenticated_sender},
authenticated_common::{compute_authenticated_sender_memo, validate_authenticated_sender},
credential::SenderMemoCredential,
RegisteredMemoType,
};
use crate::impl_memo_type_conversions;
use mc_account_keys::{PublicAddress, ShortAddressHash};
use mc_crypto_keys::{
CompressedRistrettoPublic, KexReusablePrivate, RistrettoPrivate, RistrettoPublic,
};
use mc_crypto_keys::{CompressedRistrettoPublic, RistrettoPrivate, RistrettoPublic};
use subtle::Choice;

/// A memo that the sender writes to convey their identity in an authenticated
Expand Down Expand Up @@ -62,21 +60,16 @@ impl AuthenticatedSenderWithPaymentIntentIdMemo {
// [24-48) unused
// [48-64) HMAC

let mut memo_data = [0u8; 64];
memo_data[..16].copy_from_slice(cred.address_hash.as_ref());
memo_data[16..24].copy_from_slice(&payment_intent_id.to_be_bytes());

let shared_secret = cred
.subaddress_spend_private_key
.key_exchange(receiving_subaddress_view_public_key);
let mut data = [0u8; (48 - 16)];
data[0..8].copy_from_slice(&payment_intent_id.to_be_bytes());

let hmac_value = compute_category1_hmac(
shared_secret.as_ref(),
tx_out_public_key,
let memo_data = compute_authenticated_sender_memo(
Self::MEMO_TYPE_BYTES,
&memo_data,
cred,
receiving_subaddress_view_public_key,
tx_out_public_key,
&data,
);
memo_data[48..].copy_from_slice(&hmac_value);

Self { memo_data }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
// Copyright (c) 2018-2022 The MobileCoin Foundation
// Copyright (c) 2018-2023 The MobileCoin Foundation

//! Object for 0x0101 Authenticated Sender With Payment Request Id memo type
//!
//! This was proposed for standardization in mobilecoinfoundation/mcips/pull/4
use super::{
authenticated_common::{compute_category1_hmac, validate_authenticated_sender},
authenticated_common::{compute_authenticated_sender_memo, validate_authenticated_sender},
credential::SenderMemoCredential,
RegisteredMemoType,
};
use crate::impl_memo_type_conversions;
use mc_account_keys::{PublicAddress, ShortAddressHash};
use mc_crypto_keys::{
CompressedRistrettoPublic, KexReusablePrivate, RistrettoPrivate, RistrettoPublic,
};
use mc_crypto_keys::{CompressedRistrettoPublic, RistrettoPrivate, RistrettoPublic};
use subtle::Choice;

/// A memo that the sender writes to convey their identity in an authenticated
Expand Down Expand Up @@ -60,21 +58,15 @@ impl AuthenticatedSenderWithPaymentRequestIdMemo {
// [24-48) unused
// [48-64) HMAC

let mut memo_data = [0u8; 64];
memo_data[..16].copy_from_slice(cred.address_hash.as_ref());
memo_data[16..24].copy_from_slice(&payment_request_id.to_be_bytes());

let shared_secret = cred
.subaddress_spend_private_key
.key_exchange(receiving_subaddress_view_public_key);

let hmac_value = compute_category1_hmac(
shared_secret.as_ref(),
tx_out_public_key,
let mut data = [0u8; (48 - 16)];
data[0..8].copy_from_slice(&payment_request_id.to_be_bytes());
let memo_data = compute_authenticated_sender_memo(
Self::MEMO_TYPE_BYTES,
&memo_data,
cred,
receiving_subaddress_view_public_key,
tx_out_public_key,
&data,
);
memo_data[48..].copy_from_slice(&hmac_value);

Self { memo_data }
}
Expand Down
34 changes: 27 additions & 7 deletions transaction/extra/src/memo/destination.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2018-2022 The MobileCoin Foundation
// Copyright (c) 2018-2023 The MobileCoin Foundation

//! Object for 0x0200 Destination memo type
//!
Expand Down Expand Up @@ -141,12 +141,14 @@ impl From<&[u8; 64]> for DestinationMemo {

impl From<DestinationMemo> for [u8; 64] {
fn from(src: DestinationMemo) -> [u8; 64] {
let mut memo_data = [0u8; 64];
memo_data[0..16].copy_from_slice(src.address_hash.as_ref());
memo_data[16..24].copy_from_slice(&src.fee.to_be_bytes());
memo_data[16] = src.num_recipients;
memo_data[24..32].copy_from_slice(&src.total_outlay.to_be_bytes());
memo_data
let data = [0u8; 32];
compute_destination_memo(
src.address_hash,
src.fee,
src.num_recipients,
src.total_outlay,
data,
)
}
}

Expand All @@ -157,4 +159,22 @@ pub enum DestinationMemoError {
FeeTooLarge,
}

/// Shared code for creation of an destination memo with additional
/// data
pub fn compute_destination_memo(
address_hash: ShortAddressHash,
fee: u64,
num_recipients: u8,
total_outlay: u64,
data: [u8; 32],
) -> [u8; 64] {
let mut memo_data = [0u8; 64];
memo_data[0..16].copy_from_slice(address_hash.as_ref());
memo_data[16..24].copy_from_slice(&fee.to_be_bytes());
memo_data[16] = num_recipients;
memo_data[24..32].copy_from_slice(&total_outlay.to_be_bytes());
memo_data[32..64].copy_from_slice(&data);
memo_data
}

impl_memo_type_conversions! { DestinationMemo }
20 changes: 11 additions & 9 deletions transaction/extra/src/memo/destination_with_payment_intent_id.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (c) 2018-2022 The MobileCoin Foundation
// Copyright (c) 2018-2023 The MobileCoin Foundation

//! Object for 0x0204 Destination With Payment Intent Id memo type
//!
//! This was proposed for standardization in mobilecoinfoundation/mcips/pull/54
use super::{DestinationMemoError, RegisteredMemoType};
use super::{compute_destination_memo, DestinationMemoError, RegisteredMemoType};
use crate::impl_memo_type_conversions;
use mc_account_keys::ShortAddressHash;

Expand Down Expand Up @@ -165,13 +165,15 @@ impl From<&[u8; 64]> for DestinationWithPaymentIntentIdMemo {

impl From<DestinationWithPaymentIntentIdMemo> for [u8; 64] {
fn from(src: DestinationWithPaymentIntentIdMemo) -> [u8; 64] {
let mut memo_data = [0u8; 64];
memo_data[0..16].copy_from_slice(src.address_hash.as_ref());
memo_data[16..24].copy_from_slice(&src.fee.to_be_bytes());
memo_data[16] = src.num_recipients;
memo_data[24..32].copy_from_slice(&src.total_outlay.to_be_bytes());
memo_data[32..40].copy_from_slice(&src.payment_intent_id.to_be_bytes());
memo_data
let mut data = [0u8; 32];
data[0..8].copy_from_slice(&src.payment_intent_id.to_be_bytes());
compute_destination_memo(
src.address_hash,
src.fee,
src.num_recipients,
src.total_outlay,
data,
)
}
}

Expand Down
Loading

0 comments on commit 7651276

Please sign in to comment.