Amarula.Protocol.AppState.Mutation (amarula v0.1.0)

View Source

App-state MAC + value crypto, ported from Baileys (pre-WASM chat-utils.ts): generateMac / generateSnapshotMac / generatePatchMac and the AES-256-CBC value decrypt. Pure given the expanded Amarula.Protocol.AppState.Keys.

The record value blob is iv(16) ++ ciphertext ++ mac(32); we verify the value MAC then AES-CBC-decrypt into a SyncActionData proto.

Summary

Functions

Decrypt a record value blob (iv ++ ciphertext, the 32-byte value MAC already split off) with the value encryption key. Returns the plaintext SyncActionData bytes.

Value MAC: HMAC-SHA512(value_mac_key, opByte ++ key_id ++ data ++ len8)[0..32], where len8 is 8 bytes carrying byte_size(opByte ++ key_id) in its last byte. operation is :set | :remove.

Patch MAC: HMAC-SHA256(patch_mac_key, snapshot_mac ++ value_macs ++ u64be(version) ++ name).

Snapshot MAC: HMAC-SHA256(snapshot_mac_key, lthash ++ u64be(version) ++ name).

Functions

decrypt_value(arg, value_encryption_key)

@spec decrypt_value(binary(), binary()) :: binary()

Decrypt a record value blob (iv ++ ciphertext, the 32-byte value MAC already split off) with the value encryption key. Returns the plaintext SyncActionData bytes.

generate_mac(operation, data, key_id, value_mac_key)

@spec generate_mac(:set | :remove, binary(), binary(), binary()) :: binary()

Value MAC: HMAC-SHA512(value_mac_key, opByte ++ key_id ++ data ++ len8)[0..32], where len8 is 8 bytes carrying byte_size(opByte ++ key_id) in its last byte. operation is :set | :remove.

generate_patch_mac(snapshot_mac, value_macs, version, name, patch_mac_key)

@spec generate_patch_mac(
  binary(),
  [binary()],
  non_neg_integer(),
  String.t(),
  binary()
) :: binary()

Patch MAC: HMAC-SHA256(patch_mac_key, snapshot_mac ++ value_macs ++ u64be(version) ++ name).

generate_snapshot_mac(lthash, version, name, snapshot_mac_key)

@spec generate_snapshot_mac(binary(), non_neg_integer(), String.t(), binary()) ::
  binary()

Snapshot MAC: HMAC-SHA256(snapshot_mac_key, lthash ++ u64be(version) ++ name).

u64be(version)

@spec u64be(non_neg_integer()) :: binary()