Cipher Set 2a

August 10, 2014 · View on GitHub

This profile is the algorithms used during the telehash development process in 2013.

The base algorithms in this set are:

  • SHA2 256 - generally well trusted and produces the matching cipher key sizes
  • RSA 2048 - selected as a well known and highly trusted public key algorithm and size
  • ECC P-256 - chosen to be as different from RSA as possible to reduce single vulnerabilities, and a well known curve with many implementations and the matching ECDH secret sizes
  • AES 256-GCM - trusted common implementations available and matching key input sizes

Hashname Fingerprint

When generating a hashname including CS2a, the public/private keypair is RSA 2048. For the purposes of calculating fingerprints and providing the public key within open packets, binary public keys are encoded in DER as X.509 SubjectPublicKeyInfo structures. (Most cryptographic libraries support this encoding; see RFC 5280 section 4.1 and RFC 3279 section 2.3.1 for more details.) The fingerprint is generated by using SHA-256 on the binary DER value, resulting in a 64 character lower case hex string.

Open

BODY bytes:

  • LINE KEY CIPHERTEXT (KEYC) - 256 bytes, PKCS1 OAEP (v2) RSA encrpyted, ECC P-256 public line key
  • SIGNATURE CIPHERTEXT (SIGC) - 256 bytes, PKCS1 v1.5 RSA signature, AES-256-GCM encrypted
  • SIGC MAC - (SMAC) - 4 bytes, GCM MAC/tag digest for the SIGC (some libs append this to the SIGC)
  • INNER CIPHERTEXT - (INNERC) inner packet raw bytes, AES-256-GCM encrypted inner packet
  • INNERC MAC - (IMAC) - 16 bytes, GCM MAC/tag digest (some libs append this to the INNERC)

The KEYC is created by generating a new elliptic (ECC) public key and using RSA to encrypt it to the recipient's RSA public key. The ECC keypair should be generated using the P-256 (nistp256/secp256r/X9.62 prime256v1) curve. The key should be in the uncompressed form of XY, 64 bytes (ANSI X9.63 format with the "04" identifier prefix byte removed). The RSA encryption should use PKCS1 OAEP (v2) padding. The result is always 256 bytes.

The INNERC is created by encrypting the inner packet (see open) using AES-256-GCM. The 16 byte IV is always the value of "1" (in full hex it's "00000000000000000000000000000001") and the 32 byte key is the SHA-256 of the 64 byte ECC public line key that was used for KEYC. The "tag" size for GCM is 16 bytes (128 bits), and no additional/auth data is included in it's input.

The SIGC is then calculated by first signing the resulting INNERC using the sender's RSA public key (SHA256 hash and PKCS1 v1.5 padding), resulting in a 256 byte signature. This signature is then encrypted using AES-256-GCM with the same 16 byte IV and a 32 byte key that is the SHA-256 of the 64 byte ECC public line key and the 16 byte line value included in the inner packet. The GCM tag size is 4 bytes (32 bits) and no additional/auth data is included. The result is 260 bytes (256byte signature ciphertext plus 4byte GCM tag).

Line

Line encryption/decryption secret keys are generated by using ECDH with the local line private key, and the remote line public key, and performing a SHA-256 with the ECDH derived secret (32 bytes) and sent/received line ids (16 bytes each) from the inner packets:

  • line encryption key: SHA256(ecdh-secret, my-line-id, their-line-id)
  • line decryption key: SHA256(ecdh-secret, their-line-id, my-line-id)

Line packet binary is defined as:

  • IV - 16 bytes
  • CHANNEL CIPHERTEXT - the AES-256-GCM encrypted channel packet
  • GCM TAG/MAC - (GMAC) - 16 bytes, GCM MAC digest (some GCM libraries auto-append this with the AES-256-GCM cipher output)

The IV is 16 random bytes generated for every line packet sent and used as the input to the GCM calculation, along with the appropriate encryption/decryption keys calculated for the line. The tag size for GCM is 16 bytes (128 bits) and no additiona/auth data is included as input to it.