Skip to content

Latest commit

 

History

History
77 lines (49 loc) · 4.89 KB

1a.md

File metadata and controls

77 lines (49 loc) · 4.89 KB

Cipher Set 1a

This is a minimum lightweight profile to support embedded devices and low resource environments. It has many constraints in place to minimize the code size and bytes on the wire (over speed), without significantly sacrificing security and maintaining a modern level of privacy.

The base algorithms used in this set are chosen to be readily implementable on embedded hardware (8bit 16mhz 32k AVR) and are considered minimum-grade security:

  • ECC secp160r1 - small key sizes, balance of relatively strong crypto (~1024bit) and still supportable with low cpu
  • HMAC-SHA256 - common implementations available for embedded environments
  • AES-128-CTR - low impact cipher, many implementations including hardware ones

Hashname Fingerprint

When generating a hashname including CS1a, the public/private keypair is an ECC secp160r1 curve and the binary public key format is uncompressed with the first identifier byte (0x04) truncated, resulting in 40 bytes (X and Y of the curve). In this document this is referred to as the hashname-key.

The fingerprint is generated by using SHA-256 on the binary public key, resulting in a 64 character lower case hex string.

Folding

In order to minimize the over-the-wire footprint and match key sizes while using the same SHA-256 hashing algorithm that is required for the rest of telehash, a 32-byte hash is folded once into a 16-byte value for usage as the fingerprint and as the input key for AES-128, and the 32-byte HMAC digest is folded three times into a smaller 4-byte value for usage as the MAC on open and line packets.

The folding is a simple XOR of the lower half bytes with the upper ones, example pseudocode:

var digest = sha256("foo");
var folded = digest.slice(0,16);
for(i = 0; i < 16; i++) folded[i] = folded[i] ^ digest[i+16];

The triple fold uses progressively smaller chunks of the input, as in this C code

void fold3(unsigned char in[32], unsigned char out[4])
{
  unsigned char i, buf[16];
  for(i=0;i<16;i++) buf[i] = in[i] ^ in[i+16];
  for(i=0;i<8;i++) buf[i] ^= buf[i+8];
  for(i=0;i<4;i++) out[i] = buf[i] ^ buf[i+4];
}

Open

In order to create a line, a switch must generate a new temporary ECC key, called the line-key. The line-key is used along with ECDH and AES-128-CTR to encrypt the open and line packets.

The BODY of any open packet is binary and defined with the following byte sections in sequential order:

  • HMAC - 4 bytes, the calculated HMAC folded three times
  • LINE KEY - 40 bytes, the sender's temporary line public key (X+Y)
  • INNER CIPHERTEXT - the AES-128-CTR encrypted inner packet

By performing ECDH with the sender's given line-key and the recipient's hashname-key, the resulting 20 byte secret is used create the AES cipher and decode the inner packet. The secret is SHA-256 hashed and folded once to create the AES key, and the IV is "1" ("00000000000000000000000000000001" in hex) since this secret is only ever used once.

The inner packet then contains the sender's hashname-key and must be verified. Using the hashname-key attached to the inner packet and ECDH with the recipient's hashname-key, the shared secret is used as-is (20 bytes) as the input to the HMAC, and the result after folding three times (4 bytes) is verified against the original BODY after the HMAC (bytes 4+ of the open as the input).

Compacted Inner

Any switch supporting 1a must also support an optional compacted inner format. This is only possible when the sending hashname is only created using 1a as a way to minimize the bytes required (for low-bandwidth networks) to be sent to perform an open handshake, any hashname using more than 1a must use a normal JSON inner packet format.

The compacted inner has a zero-length JSON and the BODY is always 60 bytes in three parts, the 4-byte at integer in network byte order (big-endian), then the 16-byte line id, followed by the 40-byte sender's hashname-key.

Line

Line secrets are generated by using ECDH with both line-keys, performing a SHA-256 with the secret and line ids from the inner packet and folding the digest to get the 16 bytes as the line keys:

  • line encryption key: sha256(secret, my-line-id, their-line-id) / 2
  • line decryption key: sha256(secret, their-line-id, my-line-id) / 2

Line packets are designed to be very lightweight with minimum overhead for use on networks such as 802.15.4 where there is a very low MTU. The BODY is binary and defined as:

  • HMAC - 4 bytes, the SHA-256 HMAC folded three times
  • IV - 4 bytes, incremented sequence
  • CHANNEL CIPHERTEXT - the AES-128-CTR encrypted channel packet

Using the correct line key the HMAC can be verified/created, and then using that key with the IV the channel packet can be encrypted/decrypted.

The IV must be initialized to 4 random bytes to make the individual line packets less identifiable, and then incremented for every new line packet created.