Move amount_decryption into EncryptedAmount::decrypt

This commit is contained in:
Luke Parker
2024-04-22 01:36:43 -04:00
parent d2a27dc1e5
commit a1d1de0c9c
4 changed files with 32 additions and 30 deletions

View File

@@ -189,7 +189,7 @@ impl Bulletproof {
self.write_core(w, |points, w| write_vec(write_point, points, w))
}
/// Serialize the Bulletproof(+) to a Vec<u8>.
/// Serialize the Bulletproof(+) to a `Vec<u8>`.
pub fn serialize(&self) -> Vec<u8> {
let mut serialized = vec![];
self.write(&mut serialized).unwrap();

View File

@@ -10,7 +10,7 @@ use curve25519_dalek::{
};
use crate::{
hash, hash_to_scalar, serialize::write_varint, ringct::EncryptedAmount, transaction::Input,
hash, hash_to_scalar, serialize::write_varint, Commitment, ringct::EncryptedAmount, transaction::Input,
};
pub mod extra;
@@ -94,15 +94,20 @@ pub(crate) fn commitment_mask(shared_key: Scalar) -> Scalar {
hash_to_scalar(&mask)
}
pub(crate) fn amount_encryption(amount: u64, key: Scalar) -> [u8; 8] {
pub(crate) fn compact_amount_encryption(amount: u64, key: Scalar) -> [u8; 8] {
let mut amount_mask = b"amount".to_vec();
amount_mask.extend(key.to_bytes());
(amount ^ u64::from_le_bytes(hash(&amount_mask)[.. 8].try_into().unwrap())).to_le_bytes()
}
// TODO: Move this under EncryptedAmount?
fn amount_decryption(amount: &EncryptedAmount, key: Scalar) -> (Scalar, u64) {
match amount {
impl EncryptedAmount {
/// Decrypt an EncryptedAmount into the Commitment it encrypts.
///
/// The caller must verify the decrypted Commitment matches with the actual Commitment used
/// within in the Monero protocol.
pub fn decrypt(&self, key: Scalar) -> Commitment {
match self {
// TODO: Add a test vector for this
EncryptedAmount::Original { mask, amount } => {
let mask_shared_sec = hash(key.as_bytes());
let mask =
@@ -114,14 +119,15 @@ fn amount_decryption(amount: &EncryptedAmount, key: Scalar) -> (Scalar, u64) {
// d2b from rctTypes.cpp
let amount = u64::from_le_bytes(amount_scalar.to_bytes()[0 .. 8].try_into().unwrap());
(mask, amount)
Commitment::new(mask, amount)
}
EncryptedAmount::Compact { amount } => (
EncryptedAmount::Compact { amount } => Commitment::new(
commitment_mask(key),
u64::from_le_bytes(amount_encryption(u64::from_le_bytes(*amount), key)),
u64::from_le_bytes(compact_amount_encryption(u64::from_le_bytes(*amount), key)),
),
}
}
}
/// The private view key and public spend key, enabling scanning transactions.
#[derive(Clone, Zeroize, ZeroizeOnDrop)]

View File

@@ -17,9 +17,7 @@ use crate::{
transaction::{Input, Timelock, Transaction},
block::Block,
rpc::{RpcError, RpcConnection, Rpc},
wallet::{
PaymentId, Extra, address::SubaddressIndex, Scanner, uniqueness, shared_key, amount_decryption,
},
wallet::{PaymentId, Extra, address::SubaddressIndex, Scanner, uniqueness, shared_key},
};
/// An absolute output ID, defined as its transaction hash and output index.
@@ -427,15 +425,13 @@ impl Scanner {
commitment.amount = amount;
// Regular transaction
} else {
let (mask, amount) = match tx.rct_signatures.base.encrypted_amounts.get(o) {
Some(amount) => amount_decryption(amount, shared_key),
commitment = match tx.rct_signatures.base.encrypted_amounts.get(o) {
Some(amount) => amount.decrypt(shared_key),
// This should never happen, yet it may be possible with miner transactions?
// Using get just decreases the possibility of a panic and lets us move on in that case
None => break,
};
// Rebuild the commitment to verify it
commitment = Commitment::new(mask, amount);
// If this is a malicious commitment, move to the next output
// Any other R value will calculate to a different spend key and are therefore ignorable
if Some(&commitment.calculate()) != tx.rct_signatures.base.commitments.get(o) {

View File

@@ -39,7 +39,7 @@ use crate::{
wallet::{
address::{Network, AddressSpec, MoneroAddress},
ViewPair, SpendableOutput, Decoys, PaymentId, ExtraField, Extra, key_image_sort, uniqueness,
shared_key, commitment_mask, amount_encryption,
shared_key, commitment_mask, compact_amount_encryption,
extra::{ARBITRARY_DATA_MARKER, MAX_ARBITRARY_DATA_SIZE},
},
};
@@ -92,7 +92,7 @@ impl SendOutput {
view_tag,
dest: ((&shared_key * ED25519_BASEPOINT_TABLE) + output.0.spend),
commitment: Commitment::new(commitment_mask(shared_key), output.1),
amount: amount_encryption(output.1, shared_key),
amount: compact_amount_encryption(output.1, shared_key),
},
payment_id,
)
@@ -936,7 +936,7 @@ impl Eventuality {
return false;
}
// TODO: Remove this when the following for loop is updated
// TODO: Remove this if/when the following for loop is updated to support older TXs
assert!(
rct_type.compact_encrypted_amounts(),
"created an Eventuality for a very old RctType we don't support proving for"