payment_id: PaymentId,
) -> Self {
let payment_id = Some(payment_id);
- let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, payment_id);
+ let derivation_material = MetadataMaterial::new(nonce, expanded_key, payment_id);
let metadata = Metadata::Derived(derivation_material);
Self {
offer,
secp_ctx: &'b Secp256k1<$secp_context>, payment_id: PaymentId
) -> Self {
let payment_id = Some(payment_id);
- let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, payment_id);
+ let derivation_material = MetadataMaterial::new(nonce, expanded_key, payment_id);
let metadata = Metadata::DerivedSigningPubkey(derivation_material);
Self {
offer,
tlv_stream.2.payer_id = $self.payer_id.as_ref();
}
- let (derived_metadata, derived_keys) = metadata.derive_from(tlv_stream, $self.secp_ctx);
+ let (derived_metadata, derived_keys) =
+ metadata.derive_from(IV_BYTES, tlv_stream, $self.secp_ctx);
metadata = derived_metadata;
keys = derived_keys;
if let Some(keys) = keys {
node_id: PublicKey, expanded_key: &ExpandedKey, nonce: Nonce,
secp_ctx: &'a Secp256k1<$secp_context>
) -> Self {
- let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, None);
+ let derivation_material = MetadataMaterial::new(nonce, expanded_key, None);
let metadata = Metadata::DerivedSigningPubkey(derivation_material);
Self {
offer: OfferContents {
// Either replace the signing pubkey with the derived pubkey or include the metadata
// for verification. In the former case, the blinded paths must include
// `OffersContext::InvoiceRequest` instead.
- let (derived_metadata, keys) = metadata.derive_from(tlv_stream, $self.secp_ctx);
+ let (derived_metadata, keys) =
+ metadata.derive_from(IV_BYTES, tlv_stream, $self.secp_ctx);
match keys {
Some(keys) => $self.offer.signing_pubkey = Some(keys.public_key()),
None => $self.offer.metadata = Some(derived_metadata),
}
let payment_id = Some(payment_id);
- let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, payment_id);
+ let derivation_material = MetadataMaterial::new(nonce, expanded_key, payment_id);
let metadata = Metadata::DerivedSigningPubkey(derivation_material);
Ok(Self {
refund: RefundContents {
tlv_stream.2.payer_id = None;
}
- let (derived_metadata, keys) = metadata.derive_from(tlv_stream, $self.secp_ctx);
+ let (derived_metadata, keys) =
+ metadata.derive_from(IV_BYTES, tlv_stream, $self.secp_ctx);
metadata = derived_metadata;
if let Some(keys) = keys {
$self.refund.payer_id = keys.public_key();
}
pub fn derive_from<W: Writeable, T: secp256k1::Signing>(
- self, tlv_stream: W, secp_ctx: Option<&Secp256k1<T>>
+ self, iv_bytes: &[u8; IV_LEN], tlv_stream: W, secp_ctx: Option<&Secp256k1<T>>
) -> (Self, Option<Keypair>) {
match self {
Metadata::Bytes(_) => (self, None),
Metadata::RecipientData(_) => { debug_assert!(false); (self, None) },
Metadata::PayerData(_) => { debug_assert!(false); (self, None) },
- Metadata::Derived(mut metadata_material) => {
- tlv_stream.write(&mut metadata_material.hmac).unwrap();
- (Metadata::Bytes(metadata_material.derive_metadata()), None)
+ Metadata::Derived(metadata_material) => {
+ (Metadata::Bytes(metadata_material.derive_metadata(iv_bytes, tlv_stream)), None)
},
- Metadata::DerivedSigningPubkey(mut metadata_material) => {
- tlv_stream.write(&mut metadata_material.hmac).unwrap();
+ Metadata::DerivedSigningPubkey(metadata_material) => {
let secp_ctx = secp_ctx.unwrap();
- let (metadata, keys) = metadata_material.derive_metadata_and_keys(secp_ctx);
+ let (metadata, keys) =
+ metadata_material.derive_metadata_and_keys(iv_bytes, tlv_stream, secp_ctx);
(Metadata::Bytes(metadata), Some(keys))
},
}
}
impl MetadataMaterial {
- pub fn new(
- nonce: Nonce, expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN],
- payment_id: Option<PaymentId>
- ) -> Self {
+ pub fn new(nonce: Nonce, expanded_key: &ExpandedKey, payment_id: Option<PaymentId>) -> Self {
// Encrypt payment_id
let encrypted_payment_id = payment_id.map(|payment_id| {
expanded_key.crypt_for_offer(payment_id.0, nonce)
Self {
nonce,
- hmac: expanded_key.hmac_for_offer(nonce, iv_bytes),
+ hmac: expanded_key.hmac_for_offer(),
encrypted_payment_id,
}
}
- fn derive_metadata(mut self) -> Vec<u8> {
+ fn derive_metadata<W: Writeable>(mut self, iv_bytes: &[u8; IV_LEN], tlv_stream: W) -> Vec<u8> {
+ self.hmac.input(iv_bytes);
+ self.hmac.input(&self.nonce.0);
+ tlv_stream.write(&mut self.hmac).unwrap();
+
self.hmac.input(DERIVED_METADATA_HMAC_INPUT);
self.maybe_include_encrypted_payment_id();
bytes
}
- fn derive_metadata_and_keys<T: secp256k1::Signing>(
- mut self, secp_ctx: &Secp256k1<T>
+ fn derive_metadata_and_keys<W: Writeable, T: secp256k1::Signing>(
+ mut self, iv_bytes: &[u8; IV_LEN], tlv_stream: W, secp_ctx: &Secp256k1<T>
) -> (Vec<u8>, Keypair) {
+ self.hmac.input(iv_bytes);
+ self.hmac.input(&self.nonce.0);
+ tlv_stream.write(&mut self.hmac).unwrap();
+
self.hmac.input(DERIVED_METADATA_AND_KEYS_HMAC_INPUT);
self.maybe_include_encrypted_payment_id();
pub(super) fn derive_keys(nonce: Nonce, expanded_key: &ExpandedKey) -> Keypair {
const IV_BYTES: &[u8; IV_LEN] = b"LDK Invoice ~~~~";
+ let mut hmac = expanded_key.hmac_for_offer();
+ hmac.input(IV_BYTES);
+ hmac.input(&nonce.0);
+
let secp_ctx = Secp256k1::new();
- let hmac = Hmac::from_engine(expanded_key.hmac_for_offer(nonce, IV_BYTES));
- let privkey = SecretKey::from_slice(hmac.as_byte_array()).unwrap();
+ let privkey = SecretKey::from_slice(Hmac::from_engine(hmac).as_byte_array()).unwrap();
Keypair::from_secret_key(&secp_ctx, &privkey)
}
Ok(nonce) => nonce,
Err(_) => return Err(()),
};
- let mut hmac = expanded_key.hmac_for_offer(nonce, iv_bytes);
+ let mut hmac = expanded_key.hmac_for_offer();
+ hmac.input(iv_bytes);
+ hmac.input(&nonce.0);
for record in tlv_stream {
hmac.input(record.record_bytes);