-
Notifications
You must be signed in to change notification settings - Fork 36
Boxes
trevp edited this page Dec 15, 2016
·
313 revisions
Noise assumes the following variables and functions are defined by a ciphersuite:
SUITE_NAME = ? # 24-byte string uniquely naming the ciphersuite DH_LEN = ? # Length in bytes of DH private, public keys, and DH outputs CC_LEN = ? # Length in bytes of cipher context MAC_LEN = ? # Length in bytes that ciphertext is enlarged due to MAC DH(privkey, pubkey): # Calculates a DH result. # Returns a DH secret of length DH_LEN. ENCRYPT(cc, plaintext, authtext): # Takes a cipher context, some additional authenticated data, and plaintext. # Returns an "authenticated encryption" ciphertext of length equal to # plaintext plus MAC_LEN. # Modifies the value of 'cc'.
All Noise ciphersuites use the following HMAC-SHA2-512 based key derivation functions:
CV_LEN = 48 H_LEN = 64 # output length of hash, >= 32 KDF(secret, extra_secret, info, output_len): # Outputs a byte sequence that the caller typically splits into multiple variables # such as a chain variable and cipher context, or two cipher contexts. # # The 'extra_secret' is used to pass a chaining variable to mix into the KDF. # The 'info' ensures that applying the KDF to the same secret values will # produce independent output, provided 'info' is different. output = [] t = zeros[H_LEN] for c = 0...(ceil(output_len / H_LEN) - 1) t = HMAC-SHA2-512(secret, info || (byte)c || t[0:32] || extra_secret) output = output || t return output
struct { bytes encrypted_plaintext[plaintext_len]; bytes encrypted_padding[padding_len]; bytes encrypted_padding_len[4]; bytes mac[MAC_LEN]; } NoiseBody; struct { bytes ephemeral_pubkey[DH_LEN]; bytes encrypted_sender_pubkey[DH_LEN]; bytes mac[MAC_LEN]; NoiseBody body; } NoiseBox;
noise_body(cc, pad_len, app_data, authtext=""): plaintext = app_data || random(pad_len) || (uint32_little_endian)pad_len body = ENCRYPT(cc, plaintext, authtext) return body noise_box(eph_key, sender_key, target_pubkey, pad_len, app_data, kdf_num=0x00, cv=zeros[CV_LEN]): dh1 = DH(eph_key.priv, target_pubkey) dh2 = DH(sender_key.priv, target_pubkey) cv1 || cc1 = KDF(dh1, cv, SUITE_NAME || (byte)kdf_num, CV_LEN + CC_LEN) cv2 || cc2 = KDF(dh2, cv1, SUITE_NAME || (byte)(kdf_num + 1), CV_LEN + CC_LEN) header = eph_key.pub || ENCRYPT(cc1, sender_key.pub, target_pubkey || eph_key.pub) body = noise_body(cc2, pad_len, app_data, target_pubkey || header) return (header || body), cv2
- Box size: The box size is not encoded, so must be determined by other means (e.g. file length). Boxes add a minimum of (2*DH_LEN + 2*MAC_LEN + 4) bytes of overhead to the payload.
- Ephemeral key reuse: Ephemeral keys SHALL NOT be reused for multiple Noise boxes, since the ephemeral key functions as a "nonce".
- Anonymous boxes: If the sender doesn't have a sender key, the ephemeral key MAY be reused as a sender key. This allows the sender and recipient to skip the second ECDH calculation.