-
Notifications
You must be signed in to change notification settings - Fork 17
Dark Decoys Tagging and Signalling
Moved from the old wiki, last edit was on Feb 7, 2019.
In Dark Decoys we don't need to decrypt the original flow, and station engineers agree that if we have a chance not to import OpenSSL, then we should not import OpenSSL. However, we used to have variable-length protobuf in a header of first HTTP request, which we don't want to decrypt anymore.
We do however need multiple cryptographic keys now. And we do want a variable-length sized protobuf in there for extensibility.
High-level decryption algorithm:
- extract shared_secret from Representative and generate encryption keys
- decrypt Fixed-Size Payload, which will contain size of Variable-Size Payload
- decrypt Variable-Size Payload
[ VSP ][VSP GMAC][Representative][ FSP ][ FSP GMAC ][ Suffix ]
\ variable* / \ 16* / \ 32 bytes* / \ 6* / \ 16* / \ 4 /
* before base64-style encoding. Actual size on the wire will increase by 33%.
Same old stuff. Grab eligator-transformed representative of client's public key, combine it with station's private key, get 32 byte-long shared_secret.
Located at 92 bytes offset from the end. Calculations(from the end):
- [16 bytes] GMAC for the whole TLS record
- [4 bytes] suffix
- [16 bytes] GMAC from FSP encryption
- [6 bytes] FSP
- [32 bytes] representative
(32 + 6 + 16) / 3 * 4 + 4 + 16 = 92
Use HKDF to expand and extract with following parameters
- PRK = SHA256
- SECRET = shared_secret, derived from representative
- SALT =
[]byte{"tapdancetapdancetapdancetapdance"}
- INFO = nil
This gives us a Key Derivation Function, that is able to generate a stream, which we then use to derive multiple secure keys of any length:
-
FSP_key
= first 16 bytes from HKDF -
FSP_iv
= next 12 bytes -
VSP_key
= next 16 bytes -
VSP_iv
= next 12 bytes -
new_master_secret
= next 48 bytes -
DarkDecoy_seed
= next 16 bytes
Encrypted with AES-128-GCM, using FSP_key and FSP_iv.
- size of encrypted VSP [2 bytes, BigEndian uint16] - MUST be divisible by 3
- flags [1 byte]
- Unassigned [3 bytes]
Empty right now. Will probably contain ClientToStation
protobuf
4 bytes long.
Allows us to append \r\n\r\n
at the end of the request to complete it. For incomplete requests, may be filled with anything in ASCII range.