protocol.txt definitions of the security protocols Note that the 'transformations' section omits things that 2228 specifies for all protocols, such as base64 and "ENC". In exchanges where one party does multiple actions, the last action is to compute the data which is actually sent over the network, and all other actions are internal computations. All manipulations below are in terms of eight-bit octets (i.e. bytes), *not* bits. X-SafeTP1 --------- ADATs: 1. S: DSA-public-key 2. C: lookup DSA-public-key in database C: client-challenge = random(16) C: ElGamal-public-key | client-challenge 3. S: master-key = random(40) S: make-keys() S: server-challenge = random(16) S: DSASign(ElGamalEncrypt(master-key) | client-challenge | server-challenge | server-IP) 4. C: make-keys() C: CBC3DESEncrypt(server-challenge) server-IP: Network byte order IPv6 address, which may be an IPv4-mapped IPv6 address, in which case the format more specifically is: [ 10 bytes of 0 ][ 0xFFFF ][ network byte order IPv4 address ] make-keys(): client-control-3des-key = SHA(master-key | "client control 3des left") | Left4(SHA(master-key | "client control 3des right")) server-control-3des-key = SHA(master-key | "server control 3des left") | Left4(SHA(master-key | "server control 3des right")) client-control-3des-iv = Left8(SHA(master-key | "client control 3des iv")) server-control-3des-iv = Left8(SHA(master-key | "server control 3des iv")) client-data-3des-key = SHA(master-key | "client data 3des left") | Left4(SHA(master-key | "client data 3des right")) server-data-3des-key = SHA(master-key | "server data 3des left") | Left4(SHA(master-key | "server data 3des right")) client-shahmac-key = SHA(master-key | "client shahmac") server-shahmac-key = SHA(master-key | "server shahmac") Transformations: If 959 request is R, encrypted request is CBC3DESEncrypt(SHAHMAC(R | flags | sequence-#)) If 959 reply is R, encrypted reply is CBC3DESEncrypt(SHAHMAC(R | flags | sequence-#)) There are three data channel protection modes: 'C': Cleartext -- data channel is purely client data, with no block headers or other transformation For the next two, the 959 data is arbitrarily partitioned into blocks; each block is D below. 'T': Integrity encrypted data block is SHAHMAC(D | flags | file-# | sequence-#) 'P': Privacy (also used for 'S' and 'E' codes) encrypted data block is CBC3DESEncrypt(SHAHMAC(D | flags | file-# | sequence-#)) The flags are a 32-bit, big-endian, encoding of the logical-or of: Control connection 0x00000000 Data connection 0x80000000 Sent by client 0x00000000 Sent by server 0x40000000 Encryption algorithms: I recommend Bruce Schneier's "Applied Cryptography", ISBN 0471117099, as a reference for these algorithms and a general intro to crypto. If you're interested in implementing these algorithms, you won't go wrong by starting with his book. DSA: Digital Signature Algorithm This is a U.S. government standard for digital signatures, defined in NIST FIPS publication #186. ElGamal This is a public-key encryption algorithm, proposed by Taher ElGamal: T. ElGamal, "A Public-Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms" Advances in Cryptology: Proceedings of CRYPTO 84. Springer-Verlag, 1985, pp. 10-18. 3DES: Triple-DES (Data Encryption Standard) DES is a U.S. government standard for symmetric (conventional) encryption. It is defined in FIPS publication #46. Triple-DES uses three independent DES keys, and passes data through encrypt(K1), decrypt(K2), encrypt(K3). It has a brute-force effective key length of 112 bits (as of current publicly known cryptanalysis techniques). CBC: Cipher Block Chaining mode CBC is one of several methods for encrypting messages longer than a single block, using a block-oriented cipher such as DES. It is preferable to encrypting blocks individually, since this would preserve (among other things) repeating structure in the plaintext. SHA: Secure Hash Algorithm SHA is a U.S. government standard hash algorithm, propsed in the same document as DSA (FIPS 186). HMAC: Hashed Message Authentication Code An HMAC is a construction for generating "keyed" digests -- that is, digests that depend on both the message in question, and a shared secret key. It's only slightly more complicated than hashing the concatenation of the key and message. Notes: On the control channel, the client encrypts with client-control-3des-key and the server encrypts with server-control-3des-key. The final ADAT is a control-channel communication, and hence uses the control-channel keys. On the data channel, the *-data-* keys are used in corresponding ways. The client uses client-shahmac-key as the key for HMACs it appends, and the server likewise uses server-shahmac-key. The sequence numbers for the requests and replies are independent, 32-bit, big-endian-encoded integers. They start at 0 and increase by one for each request or reply sent. The file sequence numbers for data blocks are 32-bit big-endian integers, starting at 0, and incrementing by one for each encrypted data operation. The increment is defined to occur on the *attempt* of such a data command, whether it ultimately succeeds or not. Data commands are all those commands that require data channel establishment, as per RFC 959 (e.g. STOR, LIST, etc.) The client and server each maintain a single count (which, under ideal circumstances, are equal to each other). The sequence numbers for data blocks are 32-bit big-endian integers; they start at 0 for each file, and increase by one for each block sent. Syntax like block | "string" means to concatenate the string, *not* including a null terminator. E.g., in this case, the concatenated block would be exactly 6 bytes longer than 'block'. The strings are interpreted as rendered in ASCII. All instances of SHA are SHA-1 as opposed to SHA-0. The control channel CBC3DES is initialized with the corresponding IV, derived from the master key as specified above. The data channel IV is simply the file # for that transfer, represented as a big-endian 64-bit number. We assume that the pseudo-random number generator does not compromise internal state when it outputs bytes. For example, if the PRNG always hashes its output, that would satisfy this assumption. DSA-public-key is the key itself, followed by a string identifying the server, then a 32-bit string length, and finally a signature for the whole thing, signed with the corresponding DSA private key. The lookup of DSA-public-key is a countermeasure to modification attacks after an initial successful connection. If the client discovers that the server is reporting a different public key than when the last communication took place, the user must be notified, and given the option to terminate the connection. The server-IP address is wide enough for, and in the format (as I understand it) of, IPv6 addresses. The particular form should encode IPv4 addresses as IPv6 addresses. (See RFC 2373.) This protocol is insecure against a modification attack during the first connection attempt. This insecurity is the cost of not having to deal with a certification authority. (The remainder of these protocols are either for debugging purposes only (and *not* enabled in production releases) or are obsolete and not implemented anywhere currently.) X-Cleartext ----------- ADATs: none Transformations: identity X-Cleartext2 ------------ ADATs: 1. S: "Cleartext2 first server ADAT" 2. C: "Cleartext2 first client ADAT" 3. S: "Cleartext2 second server ADAT" 4. C: "Cleartext2 second client ADAT" Transformations: identity Notes: For implementation convenience, the ADATs include the null terminator. They are, of course, rendered in ASCII. X-DSA-ELGAMAL-3DES-SHA1HMAC --------------------------- Obsolete. X-SafeTP1 is the replacement.