RFC 3961
Encryption and Checksum Specifications for Kerberos 5
RFC 3961: Encryption and Checksum Specifications for Kerberos 5 ๐
okay bestie, let's get into it ๐ง This is RFC 3961, and it's all about how Kerberos encryption and checksums get defined. Here's the title block:
- Network Working Group: the group this is part of
- Author: K. Raeburn, MIT ๐
- Category: Standards Track
- Date: February 2005
- The header doesn't list any RFCs it obsoletes or updates.
Status of This Memo ๐
This document is an Internet standards track protocol for the Internet community, and it's asking for discussion and suggestions for improvements ๐ซถ For the standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1). Distribution of this memo is unlimited.
Copyright Notice ยฉ๏ธ
Copyright (C) The Internet Society (2005).
Abstract ๐ธ
This doc gives you a framework for defining encryption and checksum mechanisms that Kerberos can use ๐ It makes an abstraction layer sitting between Kerberos and its related protocols on one side and the actual mechanisms on the other, so they don't have to know each other's business. It also defines several mechanisms. Some come from RFC 1510, reshaped to fit this new framework, and occasionally fixed in content when the old spec was wrong ๐ New mechanisms are introduced here too โจ And the big thing it does not do is say which mechanisms count as "required to implement."
Table of Contents ๐๏ธ
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . 2
3. Encryption Algorithm Profile . . . . . . . . . . . . . . . . 4
4. Checksum Algorithm Profile . . . . . . . . . . . . . . . . . 9
5. Simplified Profile for CBC Ciphers with Key Derivation . . . 10
5.1. A Key Derivation Function . . . . . . . . . . . . . . . 10
5.2. Simplified Profile Parameters . . . . . . . . . . . . . 12
5.3. Cryptosystem Profile Based on Simplified Profile . . . 13
5.4. Checksum Profiles Based on Simplified Profile . . . . . 16
6. Profiles for Kerberos Encryption and Checksum Algorithms . . 16
6.1. Unkeyed Checksums . . . . . . . . . . . . . . . . . . . 17
6.2. DES-based Encryption and Checksum Types . . . . . . . . 18
6.3. Triple-DES Based Encryption and Checksum Types . . . . 28
7. Use of Kerberos Encryption Outside This Specification . . . . 30
8. Assigned Numbers . . . . . . . . . . . . . . . . . . . . . . 31
9. Implementation Notes . . . . . . . . . . . . . . . . . . . . 32
10. Security Considerations . . . . . . . . . . . . . . . . . . . 33
11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 35
12. Acknowledgements. . . . . . . . . . . . . . . . . . . . . . . 36
A. Test vectors . . . . . . . . . . . . . . . . . . . . . . . . 38
A.1. n-fold . . . . . . . . . . . . . . . . . . . . . . . . 38
A.2. mit_des_string_to_key . . . . . . . . . . . . . . . . . 39
A.3. DES3 DR and DK . . . . . . . . . . . . . . . . . . . . 43
A.4. DES3string_to_key . . . . . . . . . . . . . . . . . . . 44
A.5. Modified CRC-32 . . . . . . . . . . . . . . . . . . . . 44
B. Significant Changes from RFC 1510 . . . . . . . . . . . . . . 45
Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Normative References. . . . . . . . . . . . . . . . . . . . . . . 47
Informative References. . . . . . . . . . . . . . . . . . . . . . 48
Editor's Address. . . . . . . . . . . . . . . . . . . . . . . . . 49
Full Copyright Statement. . . . . . . . . . . . . . . . . . . . . 50
1. Introduction โจ
okay so Kerberos is built to encrypt messages of any size ๐ It uses block ciphers or, less commonly, stream ciphers. Encryption is how network entities prove who they are during message exchanges. Here's the lowkey cool part: nothing in the Kerberos protocol insists on one specific encryption algorithm ๐ Any algorithm works, as long as it includes certain operations.
The sections that follow spell out the encryption and checksum mechanisms that are currently defined for Kerberos, plus a framework for defining future ones ๐ฆ They also cover the encoding, chaining, padding, and other requirements for each one. And Appendix A has test vectors for several functions, so you can check your work ๐
2. Concepts ๐
Both encryption and checksum mechanisms get profiled in later sections. Each profile lays out a collection of operations and attributes that a mechanism must define. A Kerberos encryption or checksum mechanism spec isn't complete unless it defines all of them ๐
An encryption mechanism must provide confidentiality and integrity of the original plaintext. (Adding a checksum may allow integrity checking, if the encryption mode doesn't have an integrity check of its own.) It must also provide non-malleability [Bellare98] [Dolev91]. Prepending a random confounder to the plaintext is recommended ๐ซถ It should not be possible to tell whether two ciphertexts match the same plaintext without the key. ๐
A checksum mechanism [1] must prove the integrity of the associated message, and it must keep the message confidential in case it isn't sent in the clear. Finding two plaintexts with the same checksum should be infeasible. It is NOT required that an eavesdropper be unable to tell whether two checksums belong to the same message, since the messages themselves would presumably be visible to any such eavesdropper ๐
Due to advances in cryptography, some cryptographers think using the same key for multiple purposes is unwise ๐ฌ Kerberos uses keys for a bunch of different functions, so it's desirable to use different keys for each purpose, even though we start with a single long-term or session key ๐๏ธ
So here's how we do it: we list out the different uses of keys within Kerberos, and we make the "usage number" an input to the encryption or checksum mechanisms. Listing those uses is outside the scope of this document. Later sections define simplified profile templates for encryption and checksum mechanisms that apply a key derivation function to a CBC mode (or similar) cipher and a checksum or hash algorithm ๐
We distinguish the "base key" from other documents from the "specific key" used for a specific encryption or checksum operation ๐ง The specific key is expected, but not required, to be one or more separate keys derived from the original protocol key and the key usage number. The specific key should not be explicitly referenced outside of this document. Other documents typically say something like, "encrypt this octet string using this key and this usage number," and generating the specific key and cipher state (covered in the next section) is implicit. Creating a new cipher-state object, or reusing one from a previous encryption operation, may also be explicit ๐
New protocols defined in terms of the Kerberos encryption and checksum types should use their own key usage values. Key usages are unsigned 32-bit integers, and zero is not permitted ๐ซ
All data is assumed to be strings of octets, or eight-bit bytes. Environments with other byte sizes will have to emulate this behavior to get correct results ๐ค
Each algorithm gets an encryption type (or "etype") or checksum type number, which Kerberos uses to identify it on the wire. The full list of current type number assignments is in section 8 ๐
3. Encryption Algorithm Profile ๐
An encryption mechanism profile must define the following attributes and operations. The operations must be defined as functions in the mathematical sense. No additional or implicit inputs (such as Kerberos principal names or message sequence numbers) are permitted ๐ โโ๏ธ
- protocol key format: This describes which octet string values represent valid keys. For encryption mechanisms that don't have perfectly dense key spaces, this describes the representation used to encode keys. It doesn't need to describe invalid specific values, though all key generation routines should avoid them โจ
- specific key structure: This isn't a protocol format at all. It describes the keying material derived from the chosen key and used to encrypt or decrypt data, or to compute or verify a checksum. It could be a single key, a set of keys, or a combination of the original key with additional data. The authors recommend using one or more keys derived from the original key through one-way key derivation functions ๐
- required checksum mechanism: This names a checksum mechanism that must be available whenever this encryption mechanism is used. Kerberos has no built-in way to negotiate checksum mechanisms, so once an encryption mechanism is chosen, the matching checksum mechanism can be used ๐ซถ
- key-generation seed length,
K: This is the length of the random bitstring needed to generate a key with the encryption scheme's random-to-key function (described below). It must be a fixed value, so that various techniques for producing a random bitstring of a given length can be used with key generation functions ๐ฒ - key generation functions: Keys have to be generated in a number of cases, from different kinds of inputs. Every function spec must say how to generate keys in the proper wire format, and it must avoid generating keys that significantly compromise the confidentiality of encrypted data, if the cryptosystem has such keys. Entropy from each source should be preserved as much as possible. Many inputs, though unknown, may be at least partly predictable. For example, a password string is likely to be entirely in the ASCII subset and fairly short in many environments, and a semi-random string may include time stamps. The benefit of that predictability to an attacker must be minimized ๐
string-to-key (UTF-8 string, UTF-8 string, opaque)->(protocol-key): This function makes a key from two UTF-8 strings and an opaque octet string. One of the strings is usually the principal's pass phrase, but in general it's just a secret string. The other string is a "salt" string, meant to produce different keys from the same password for different users or realms. Even though the strings use UTF-8 encoding, no specific version of Unicode should be assumed, and all valid UTF-8 strings should be allowed. Strings provided in other encodings MUST first be converted to UTF-8 before applying this function ๐ธ
The third argument, the octet string, may be used to pass mechanism-specific parameters into this function. Since doing so implies knowledge of the specific encryption system, generating non-default parameter values should be an uncommon operation. Normal Kerberos applications should be able to treat this parameter block as an opaque object supplied by the Key Distribution Center, or defaulted to some mechanism-specific constant value ๐ง
The string-to-key function should be a one-way function, so that compromising a user's key in one realm doesn't compromise it in another, even if the same password (but a different salt) is used ๐
random-to-key (bitstring[K])->(protocol-key)
okay so this one takes a random bitstring of a specific size and turns it into a protocol key ๐ All the bits of the input are treated as equally random, bestie, even though the entropy in the actual random source might be kinda limited ๐ฅบ
key-derivation (protocol-key, integer)->(specific-key)
the integer input here is the key usage value we covered above ๐ฆ An attacker is assumed to know all the usage values (no secrets there!), and the specific-key output is the one described in section 2 โจ
string-to-key parameter format
this describes the format of the data block you can pass into the string-to-key function to configure its extra parameters ๐ We also have to set bounds on what's allowed, because otherwise a spoofed KDC could compromise the user's password ๐ญ If it's practical, it MAY be desirable to build the encoding so that values which would unacceptably weaken the resulting key simply cannot be encoded ๐ฅ
Local security policy MAY permit tighter bounds to avoid excess resource consumption. If it does, the specification SHOULD give RECOMMENDED defaults for these bounds ๐ธ The description SHOULD also outline the possible weaknesses if bounds checks or other validations are not applied to a parameter string received from the network ๐
As mentioned above, this SHOULD be considered opaque to most normal applications ๐
default string-to-key parameters (octet string)
this is the default value for the "params" argument of the string-to-key function, and it SHOULD be used whenever the application protocol (Kerberos or something else) doesn't explicitly set the parameter value ๐ Like we said before, in most cases this parameter block should be treated as an opaque object ๐ซถ
cipher state
this is any info that can get carried over from one encryption or decryption operation to the next, for use with a given specific key โจ For example, a block cipher used in CBC mode MAY put an initial vector of one block in the cipher state. Other encryption modes MAY track nonces or other data ๐ง
This state MUST be non-empty and MUST influence encryption so that messages are decrypted in the same order they were encrypted, if the cipher state is carried over from one encryption to the next. Telling apart out-of-order or missing messages from corrupted ones is not required ๐คทโโ๏ธ If you want that, you can do it at a higher level by including sequence numbers and NOT "chaining" the cipher state between encryption operations ๐
The cipher state MAY NOT be reused in multiple encryption or decryption operations. These operations all generate a new cipher state that MAY be used for following operations using the same key and operation ๐ฆ
The contents of the cipher state MUST be treated as opaque outside of encryption system specifications ๐
initial cipher state (specific-key, direction)->(state)
this covers generating the initial value for the cipher state when it's NOT being carried over from a previous encryption or decryption operation ๐
It also describes any initial state setup needed before encrypting arbitrary amounts of data with a given specific key. The specific key and the direction of operations (encrypt versus decrypt) MUST be the only inputs needed for this initialization ๐
This state SHOULD be treated as opaque in any uses outside of an encryption algorithm definition ๐
IMPLEMENTATION NOTE: [Kerb1510] was vague on whether, and to what degree, an application protocol could control the initial vector used in DES CBC operations. Some existing implementations let you set the initial vector. This framework does NOT provide for application control of the cipher state (beyond "initialize" and "carry over from previous encryption"), because the form and content of the initial cipher state can vary between encryption systems and MAY NOT always be a single block of random data ๐
New Kerberos application protocols SHOULD NOT assume control over the initial vector, or assume that one even exists. Still, a general-purpose implementation MAY wish to provide the capability, in case applications that explicitly set it get encountered ๐ซ
encrypt (specific-key, state, octet string)->(state, octet string)
this takes the specific key, the cipher state, and a non-empty plaintext string as input, and spits out ciphertext plus a new cipher state ๐ If the basic encryption algorithm doesn't provide integrity protection by itself (like DES in CBC mode), then some form of verifiable MAC or checksum MUST be included ๐ฅ A random factor like a confounder SHOULD be included too, so an observer can't tell whether two messages contain the same plaintext, even when the cipher state and specific keys are the same ๐
The exact length of the plaintext doesn't need to be encoded. But if it isn't, and padding is required, the padding MUST be added at the end of the string so the decrypted version can be parsed from the beginning ๐
The spec for the encryption function MUST indicate not only the precise contents of the output octet string, but also the output cipher state. The application protocol MAY carry the output cipher state forward from one encryption with a given specific key to another, and the effect of this "chaining" MUST be defined [2] ๐
Assuming the specific key and cipher state were correctly produced, NO input octet string may result in an error indication ๐
decrypt (specific-key, state, octet string)->(state, octet string)
this takes the specific key, cipher state, and ciphertext as inputs, and verifies the integrity of the ciphertext ๐ต๏ธโโ๏ธ If the integrity is intact, it produces the plaintext and a new cipher state. Otherwise an error indication MUST be returned, and the data MUST be discarded ๐
The result of decryption MAY be longer than the original plaintext, like when the encryption mode adds padding to reach a multiple of a block size. If that happens, any extra octets MUST come after the decoded plaintext ๐ซง An application protocol that needs to know the exact length of the message MUST encode a length or a recognizable "end of message" marker within the plaintext [3] โจ
Same as with the encryption function, a correct spec for this one MUST indicate not only the contents of the output octet string, but also the resulting cipher state ๐
pseudo-random (protocol-key, octet-string)->(octet-string)
this pseudo-random function SHOULD generate an octet string of some size that's independent of the octet string input. The PRF output SHOULD be suitable for key generation, even if the octet string input is public. It SHOULD NOT reveal the input key, even if the output is made public ๐
These operations and attributes are all that is required to support Kerberos and various proposed preauthentication schemes ๐ธ
For convenience, certain application protocols MAY want to use the encryption profile, so we add a constraint: for any given plaintext input size, a message size MUST exist between that size and that size plus 65,535, such that the length of the decrypted version of the ciphertext never has extra octets at the end ๐
Mathematically, that looks like this: for every message length L1, there exists a message size L2 such that
L2 >= L1
L2 < L1 + 65,536
for every message M with |M| = L2, decrypt(encrypt(M)) = M
A document defining a new encryption type SHOULD also describe known weaknesses or attacks, so its security can be fairly assessed. It SHOULD include test vectors or other validation procedures for the operations defined ๐งช Specific references to information that's readily available elsewhere are sufficient ๐
4. Checksum Algorithm Profile โจ
A checksum mechanism profile MUST define the following attributes and operations ๐
associated encryption algorithm(s)
this indicates the types of encryption keys this checksum mechanism can be used with ๐
A keyed checksum mechanism MAY have more than one associated encryption algorithm, as long as they share the same wire-key format, string-to-key function, default string-to-key-parameters, and key derivation function. (This combination means that, for example, a checksum type, key usage value, and password are enough to get the specific key used to compute a checksum ๐ฆ)
An unkeyed checksum mechanism can be used with any encryption type, since the key is ignored. But its use MUST be limited to cases where the checksum itself is protected, to avoid trivial attacks ๐ โโ๏ธ
get_mic function
this generates a MIC token for a given specific key (see section 3) and message (represented as an octet string), and the token can be used to verify the integrity of the associated message ๐ It is not required to return the same deterministic result each time. It just needs to generate a token that the verify_mic routine can check ๐ค
The output of this function also dictates the size of the checksum. It MUST be no larger than 65,535 octets ๐
verify_mic function
given a specific key, message, and MIC token, this function figures out whether the message integrity has been compromised ๐ต๏ธโโ๏ธ For a deterministic get_mic routine, the corresponding verify_mic MAY simply generate another checksum and compare the two ๐
The get_mic and verify_mic operations MUST allow inputs of arbitrary length. If any padding is needed, the padding scheme MUST be specified as part of these functions ๐ซถ
These operations and attributes are all that SHOULD be required to support Kerberos and various proposed preauthentication schemes โจ
As with encryption mechanism definition documents, documents defining new checksum mechanisms SHOULD indicate validation processes and known weaknesses ๐งช
5. Simplified Profile for CBC Ciphers with Key Derivation ๐ธ
The profile outlined in sections 3 and 4 describes a big pile of operations that MUST be defined for encryption and checksum algorithms to be used with Kerberos ๐ญ So here we describe a simpler profile that can generate both encryption and checksum mechanism definitions. It fills in uses of key derivation in the right places, provides integrity protection, and defines multiple operations for the cryptosystem profile based on a smaller set of operations ๐ Not all of the existing cryptosystems for Kerberos fit into this simplified profile, but we recommend that future cryptosystems use it or something based on it [4] ๐ฆ
Not all the operations in the complete profiles are defined through this mechanism. Several still MUST be defined for each new algorithm pair ๐ซถ
5.1. A Key Derivation Function ๐
Okay so instead of building one giant "protocol key" out of a bunch of encryption keys (way too messy ๐), we just derive keys from a base key and use those for the actual crypto ops โจ. The base key must be used only for generating the derived keys, and this derivation must be non-invertible and entropy preserving. With those rules locked in, compromising one derived key doesn't compromise the others ๐ก๏ธ. The base key is also pretty safe, since it's only used for derivation and never exposed to any user data ๐ซถ.
To make a derived key, we first generate a pseudorandom octet string using the DR algorithm (more on that below), and then turn that string into a key with a function that depends on the encryption algorithm. That function needs a specific input length, which also depends on the algorithm. That length sets how long the DR output has to be (the value "k" below). This whole procedure is based on the key derivation in [Blumenthal96] ๐.
Derived Key = DK(Base Key, Well-Known Constant)
DK(Key, Constant) = random-to-key(DR(Key, Constant))
DR(Key, Constant) = k-truncate(E(Key, Constant,
initial-cipher-state))
So DR is the random-octet generation function and DK is the key-derivation function built on top of it ๐ง. E(Key, Plaintext, CipherState) is a cipher, Constant is a well-known constant chosen based on how this function is used, and k-truncate keeps the first k bits of its argument. The k is the key generation seed length that the encryption system needs โญ.
The DR output is a bit string, and the actual key comes from running the cryptosystem's random-to-key operation on it ๐ฅ.
If the Constant is smaller than E's cipher block size, it must be expanded with n-fold() so it can be encrypted ๐. If E's output is shorter than k bits, it gets fed back into the encryption as many times as it takes. Here's the construction (where | means concatenation):
K1 = E(Key, n-fold(Constant), initial-cipher-state)
K2 = E(Key, K1, initial-cipher-state)
K3 = E(Key, K2, initial-cipher-state)
K4 = ...
DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)
n-fold is the algorithm that takes m input bits and stretches them out to n output bits, with every input bit contributing equally to the output. Here's how [Blumenthal96] describes it, word for word:
We first define a primitive called n-folding, which takes a variable-length input block and produces a fixed-length output sequence. The intent is to give each input bit approximately equal weight in determining the value of each output bit. Note that whenever we need to treat a string of octets as a number, the assumed representation is Big-Endian -- Most Significant Byte first. To n-fold a number X, replicate the input value to a length that is the least common multiple of n and the length of X. Before each repetition, the input is rotated to the right by 13 bit positions. The successive n-bit chunks are added together using 1's-complement addition (that is, with end-around carry) to yield a n-bit result....
Test vectors for n-fold are in appendix A [5] ๐งพ.
In this section, n-fold is always used to produce c bits of output, where c is the cipher block size of E ๐ .
The size of the Constant must not be larger than c, because shrinking the Constant with n-folding can cause collisions ๐.
If the Constant is smaller than c, it must be n-folded out to length c, and that string is then fed into E. If E's block size is less than the random-to-key input size, the output from E is taken as input to a second invocation of E. This keeps going until the bits accumulated are greater than or equal to the random-to-key input size. Once there are enough bits, the first k are used as the random data to build the key with the algorithm-dependent random-to-key function ๐.
And here's the big payoff: since the derived key is the result of one or more encryptions under the base key, figuring out the base key from the derived key is the same as figuring it out from a very small number of plaintext/ciphertext pairs. So this construction is exactly as strong as the cryptosystem itself ๐.
5.2. Simplified Profile Parameters ๐
These are the operations and attributes that must be defined:
protocol key formatstring-to-key functiondefault string-to-key parameterskey-generation seed length, krandom-to-key function- As above for the normal encryption mechanism profile.
unkeyed hash algorithm, H
This should be a collision-resistant hash algorithm with fixed-size output, suitable for use in an HMAC [HMAC] ๐ธ. It must support inputs of arbitrary length. Its output must be at least the message block size (below).
HMAC output size, h
This is the size of the leading substring of the HMAC output that should be used in transmitted messages ๐ฆ. It should be at least half the output size of the hash function H, and at least 80 bits. It doesn't need to match the output size.
message block size, m
This is the size of the smallest units the cipher can handle in the mode it's being used in ๐. Messages get padded to a multiple of this size. If a block cipher is used in a mode that can handle messages that aren't multiples of the cipher block size, like CBC mode with cipher text stealing (CTS, see [RC5]), this value would be one octet. For traditional CBC mode with padding, it would be the underlying cipher's block size.
This value must be a multiple of eight bits (one octet).
encryption/decryption functions, E and D
These are the basic encryption and decryption functions for messages whose sizes are multiples of the message block size โจ. No integrity checking or confounder should be included here. For inputs, these functions take the IV or similar data, a protocol-format key, and an octet string, and they return a new IV and an octet string.
The encryption function isn't required to use CBC mode, but it's assumed to be using something with similar properties. In particular, prepending a cipher block-size confounder to the plaintext should alter the entire ciphertext (comparable to choosing and including a random initial vector for CBC mode) ๐.
Encrypting one cipher block (of size c, above) must be deterministic for the random octet generation function DR in the previous section to work. For best security, it should also be no larger than c.
cipher block size, c
This is the block size of the block cipher underlying the encryption and decryption functions above. It's used for key derivation and for the size of the message confounder and initial vector. (If a block cipher isn't in use, some comparable parameter should be figured out instead.) It must be at least 5 octets ๐ซง.
This isn't really an independent parameter. It's a property of the functions E and D. It's listed here so you can tell it apart from the message block size, m.
Although there are still a number of properties to specify, they're fewer and simpler than in the full profile ๐.
5.3. Cryptosystem Profile Based on Simplified Profile ๐
Okay, the key derivation function above gets used to produce three intermediate keys ๐๏ธ. One is for computing checksums of unencrypted data. The other two are for encrypting and checksumming plaintext that's going to be sent encrypted.
The ciphertext output is the concatenation of the output of the basic encryption function E and a (possibly truncated) HMAC using the specified hash function H. Both are applied to the plaintext, with a random confounder prefix and enough padding to bring it up to a multiple of the message block size. When the HMAC is computed, the key is used in its protocol key form ๐ฆ.
Decryption works by removing the (partial) HMAC, decrypting the rest, and then verifying the HMAC ๐ต๏ธ. The cipher state is an initial vector, initialized to zero.
The substring notation "[1..h]" in the table below should be read with 1-based indexing, and leading substrings are used ๐ข.
Cryptosystem from Simplified Profile
------------------------------------------------------------------------
protocol key format As given.
specific key structure Three protocol-format keys: { Kc, Ke, Ki }.
key-generation seed As given.
length
required checksum As defined below in section 5.4.
mechanism
cipher state Initial vector (usually of length c)
initial cipher state All bits zero
encryption function conf = Random string of length c
pad = Shortest string to bring confounder
and plaintext to a length that's a
multiple of m.
(C1, newIV) = E(Ke, conf | plaintext | pad,
oldstate.ivec)
H1 = HMAC(Ki, conf | plaintext | pad)
ciphertext = C1 | H1[1..h]
newstate.ivec = newIV
decryption function (C1,H1) = ciphertext
(P1, newIV) = D(Ke, C1, oldstate.ivec)
if (H1 != HMAC(Ki, P1)[1..h])
report error
newstate.ivec = newIV
default string-to-key As given.
params
pseudo-random function tmp1 = H(octet-string)
tmp2 = truncate tmp1 to multiple of m
PRF = E(DK(protocol-key, prfconstant),
tmp2, initial-cipher-state)
The "prfconstant" used in the PRF operation is the three-octet string "prf" ๐ท.
Cryptosystem from Simplified Profile
------------------------------------------------------------------------
key generation functions:
string-to-key function As given.
random-to-key function As given.
key-derivation function The "well-known constant" used for the DK
function is the key usage number, expressed as
four octets in big-endian order, followed by
one octet indicated below.
Kc = DK(base-key, usage | 0x99);
Ke = DK(base-key, usage | 0xAA);
Ki = DK(base-key, usage | 0x55);
5.4. Checksum Profiles Based on Simplified Profile โ
When an encryption system is defined with the simplified profile from section 5.2, a checksum algorithm may be defined for it as follows ๐ซถ:
Checksum Mechanism from Simplified Profile
--------------------------------------------------
associated cryptosystem As defined above.
get_mic HMAC(Kc, message)[1..h]
verify_mic get_mic and compare
The HMAC function and key Kc are as described in section 5.3 ๐.
6. Profiles for Kerberos Encryption and Checksum Algorithms โจ
Okay bestie, this section is where we meet the Kerberos encryption and checksum systems ๐. Some of them are a little bit vintage and don't meet every requirement from the earlier sections. They're kept around for backward compatibility ๐ฐ๏ธ, but newer implementations should (whenever possible) pick encryption systems that meet all the profile requirements ๐ . The full list of current encryption and checksum type number assignments, including values that are reserved but not defined here, lives in section 8 ๐.
6.1. Unkeyed Checksums ๐งฉ
These checksum types don't use encryption keys, so they can be paired with any encryption type ๐. They may only be used with caution, though, and only in limited situations where having no key doesn't open a window for an attack ๐ช. Preferably they're used as part of an encrypted message [6]. Keyed checksum algorithms are recommended ๐.
6.1.1. The RSA MD5 Checksum ๐ธ
The RSA-MD5 checksum uses the RSA MD5 algorithm [MD5-92] ๐งฎ. It takes an input message of any length and spits out a 128-bit (sixteen octet) checksum ๐.
rsa-md5
----------------------------------------------
associated cryptosystem any
get_mic rsa-md5(msg)
verify_mic get_mic and compare
The rsa-md5 checksum algorithm gets assigned checksum type number seven (7) ๐.
6.1.2. The RSA MD4 Checksum ๐
The RSA-MD4 checksum uses the RSA MD4 algorithm [MD4-92] โจ. Same deal as MD5: any-length input, 128-bit (sixteen octet) output ๐ซถ.
rsa-md4
----------------------------------------------
associated cryptosystem any
get_mic md4(msg)
verify_mic get_mic and compare
The rsa-md4 checksum algorithm gets checksum type number two (2) ๐ฆ.
6.1.3. CRC-32 Checksum ๐ง
Okay, this one is a big "not recommended" energy moment ๐ฌ. The CRC-32 checksum is based on a cyclic redundancy check described in ISO 3309 [CRC], but it's been modified in a couple of ways ๐ ๏ธ. The result is four (4) octets long ๐. It is neither keyed nor collision-proof, so using it is not recommended ๐ซ. An attacker running a probabilistic chosen-plaintext attack like the one described in [SG92] might be able to craft a different message that still satisfies the checksum ๐.
The CRC-32 checksum used in the des-cbc-crc encryption mode matches the 32-bit FCS from ISO 3309 with two exceptions ๐. First, the sum with the all-ones polynomial times x**k is omitted. Second, the final remainder is not ones-complemented ๐. ISO 3309 describes the FCS in terms of bits, but this document describes the Kerberos protocol in terms of octets ๐ง . To make the ISO 3309 definition clear for computing CRC-32 in the des-cbc-crc encryption mode, the ordering of bits in each octet shall be assumed to be LSB first ๐. With that bit ordering assumed, the mapping of bits to polynomial coefficients shall be identical to what ISO 3309 specifies ๐.
Test values for this modified CRC function are included in appendix A.5 ๐.
crc32
----------------------------------------------
associated cryptosystem any
get_mic crc32(msg)
verify_mic get_mic and compare
The crc32 checksum algorithm gets checksum type number one (1) ๐.
6.2. DES-Based Encryption and Checksum Types ๐๐
These encryption systems encrypt information under the Data Encryption Standard [DES77] using the cipher block chaining mode [DESM80] ๐. A checksum is computed as described below and placed in the cksum field ๐งพ. DES blocks are eight bytes, so the data to be encrypted (the confounder, checksum, and message put together) must be padded to an eight byte boundary before encryption ๐. The values of the padding bytes are unspecified ๐คทโโ๏ธ.
Plaintext and DES ciphertext are encoded as blocks of eight octets. Those blocks get concatenated to make the 64-bit inputs for the DES algorithms ๐งฉ. The first octet supplies the eight most significant bits (the octet's MSB becomes the DES input block's MSB, and so on). The second octet supplies the next eight bits, and it keeps going like that. The eighth octet supplies the 8 least significant bits ๐.
Encryption under DES with cipher block chaining needs an extra input called an initialization vector ๐. The vector is specified below for each encryption system ๐.
The DES specifications [DESI81] identify four 'weak' and twelve 'semi-weak' keys ๐จ. These keys SHALL NOT be used for encrypting messages for use in Kerberos ๐. The "variant keys" generated for the RSA-MD5-DES, RSA-MD4-DES, and DES-MAC checksum types by an eXclusive-OR of a DES key with a constant aren't checked for this property ๐.
A DES key is eight octets of data ๐๏ธ. That's 56 bits of actual key data plus eight parity bits, one per octet ๐ . The key is encoded as a series of eight octets written in MSB-first order, and the bits inside the key are encoded in MSB order too ๐ข. For example, if the encryption key is (B1,B2,...,B7,P1,B8,...,B14,P2,B15,...,B49,P7,B50,...,B56,P8), where B1,B2,...,B56 are the key bits in MSB order and P1,P2,...,P8 are the parity bits, then the first octet of the key would be B1,B2,...,B7,P1 (with B1 as the most significant bit). See the [DESM80] introduction for reference ๐.
Encryption Data Format ๐
The data to be encrypted includes a one-block confounder, a checksum, the encoded plaintext, and any necessary padding, as shown in this diagram ๐ผ๏ธ. The msg-seq field holds the part of the protocol message to be encrypted ๐.
+-----------+----------+---------+-----+
|confounder | checksum | msg-seq | pad |
+-----------+----------+---------+-----+
Here's the recipe ๐ณ. Generate a random confounder of one block and place it in 'confounder'. Zero out the 'checksum' field (sized to exactly hold the checksum you're about to compute). Add the necessary padding. Calculate the checksum over the whole sequence and place the result in 'checksum'. Then encrypt using the specified encryption type and the right key โจ.
String or Random-Data to Key Transformation ๐ช
To make a DES key from two UTF-8 text strings (password and salt), concatenate the two strings with password first. Then pad the result with zero-valued octets until it's a multiple of eight octets ๐ง.
The top bit of each octet is discarded. It's always zero if the password is plain ASCII, which is what was assumed when the original specification was written ๐ธ. The remaining seven bits of each octet form a bitstring. That bitstring gets fan-folded and eXclusive-ORed with itself to produce a 56-bit string ๐. An eight-octet key is formed from this string, with each octet using seven bits from the bitstring and the least significant bit left unassigned ๐. The key is then "corrected" by fixing its parity. If the key matches a 'weak' or 'semi-weak' key from the DES specification, it gets eXclusive-ORed with the constant 0x00000000000000F0 ๐ซ. That key is then used to generate a DES CBC checksum on the initial string with the salt appended ๐. The CBC checksum result gets "corrected" the same way as above, and that becomes the returned key ๐.
For the string-to-key function, the DES CBC checksum is calculated by CBC encrypting a string using the key as the IV, with the final eight byte block used as the checksum ๐งก.
Pseudocode time ๐ค:
removeMSBits(8byteblock) {
/* Treats a 64 bit block as 8 octets and removes the MSB in
each octet (in big endian mode) and concatenates the
result. E.g., the input octet string:
01110000 01100001 11110011 01110011 11110111 01101111
11110010 01100100
results in the output bitstring:
1110000 1100001 1110011 1110011 1110111 1101111
1110010 1100100 */
}
reverse(56bitblock) {
/* Treats a 56-bit block as a binary string and reverses it.
E.g., the input string:
1000001 1010100 1001000 1000101 1001110 1000001
0101110 1001101
results in the output string:
1011001 0111010 1000001 0111001 1010001 0001001
0010101 1000001 */
}
add_parity_bits(56bitblock) {
/* Copies a 56-bit block into a 64-bit block, left shifts
content in each octet, and add DES parity bit.
E.g., the input string:
1100000 0001111 0011100 0110100 1000101 1100100
0110110 0010111
results in the output string:
11000001 00011111 00111000 01101000 10001010 11001000
01101101 00101111 */
}
key_correction(key) {
fixparity(key);
if (is_weak_key(key))
key = key XOR 0xF0;
return(key);
}
mit_des_string_to_key(string,salt) {
odd = 1;
s = string | salt;
tempstring = 0; /* 56-bit string */
pad(s); /* with nulls to 8 byte boundary */
for (8byteblock in s) {
56bitstring = removeMSBits(8byteblock);
if (odd == 0) reverse(56bitstring);
odd = ! odd;
tempstring = tempstring XOR 56bitstring;
}
tempkey = key_correction(add_parity_bits(tempstring));
key = key_correction(DES-CBC-check(s,tempkey));
return(key);
}
des_string_to_key(string,salt,params) {
if (length(params) == 0)
type = 0;
else if (length(params) == 1)
type = params[0];
else
error("invalid params");
if (type == 0)
mit_des_string_to_key(string,salt);
else
error("invalid params");
}
One common extension is to support the "AFS string-to-key" algorithm, which isn't defined here, if the type value above is one (1) ๐งช.
Random Bitstring to Key ๐ฒ
For generating a key from a random bitstring, start with a 56-bit string and insert parity bits, same as in the string-to-key operation above ๐งต. If the result is a weak or semi-weak key, modify it by eXclusive-ORing it with the constant 0x00000000000000F0 ๐ฉท:
des_random_to_key(bitstring) {
return key_correction(add_parity_bits(bitstring));
}
6.2.1. DES with MD5 ๐
okay so des-cbc-md5 encrypts info under DES in CBC mode, starting with an all-zero initial vector ๐ธ and an MD5 checksum (described in [MD5-92]) gets computed and tucked into the checksum field โจ literally the perfect little combo ๐ซถ
Here are the encryption system parameters for des-cbc-md5 ๐
des-cbc-md5
--------------------------------------------------------------------
protocol key format 8 bytes, parity in low bit of each
specific key structure copy of original key
required checksum rsa-md5-des
mechanism
key-generation seed 8 bytes
length
cipher state 8 bytes (CBC initial vector)
initial cipher state all-zero
encryption function des-cbc(confounder | checksum | msg | pad,
ivec=oldstate)
where
checksum = md5(confounder | 0000...
| msg | pad)
newstate = last block of des-cbc output
decryption function decrypt encrypted text and verify checksum
newstate = last block of ciphertext
des-cbc-md5
--------------------------------------------------------------------
default string-to-key empty string
params
pseudo-random function des-cbc(md5(input-string), ivec=0)
key generation functions:
string-to-key des_string_to_key
random-to-key des_random_to_key
key-derivation identity
the des-cbc-md5 encryption type is assigned the etype value three (3) ๐
6.2.2. DES with MD4 ๐ฆ
the des-cbc-md4 mode is giving the same vibe ๐ it also encrypts under DES in CBC mode with an all-zero initial vector, and an MD4 checksum (described in [MD4-92]) gets computed and placed in the checksum field ๐
des-cbc-md4
--------------------------------------------------------------------
protocol key format 8 bytes, parity in low bit of each
specific key structure copy of original key
required checksum rsa-md4-des
mechanism
key-generation seed 8 bytes
length
cipher state 8 bytes (CBC initial vector)
initial cipher state all-zero
encryption function des-cbc(confounder | checksum | msg | pad,
ivec=oldstate)
where
checksum = md4(confounder | 0000...
| msg | pad)
newstate = last block of des-cbc output
des-cbc-md4
--------------------------------------------------------------------
decryption function decrypt encrypted text and verify checksum
newstate = last block of ciphertext
default string-to-key empty string
params
pseudo-random function des-cbc(md5(input-string), ivec=0)
key generation functions:
string-to-key des_string_to_key
random-to-key copy input, then fix parity bits
key-derivation identity
ngl this one has a plot twist ๐ des-cbc-md4 uses md5, not md4, in the PRF definition. don't mix them up bestie ๐ญ
the des-cbc-md4 encryption algorithm is assigned the etype value two (2) ๐
6.2.3. DES with CRC ๐ง
the des-cbc-crc type uses DES in CBC mode, with the key used as the initialization vector ๐ฅ it also uses a four-octet CRC-based checksum computed as described in section 6.1.3. heads up, this is not a standard CRC-32 checksum. it's a slightly modified one ๐
des-cbc-crc
--------------------------------------------------------------------
protocol key format 8 bytes, parity in low bit of each
specific key structure copy of original key
required checksum rsa-md5-des
mechanism
key-generation seed 8 bytes
length
cipher state 8 bytes (CBC initial vector)
des-cbc-crc
--------------------------------------------------------------------
initial cipher state copy of original key
encryption function des-cbc(confounder | checksum | msg | pad,
ivec=oldstate)
where
checksum = crc(confounder | 00000000
| msg | pad)
newstate = last block of des-cbc output
decryption function decrypt encrypted text and verify checksum
newstate = last block of ciphertext
default string-to-key empty string
params
pseudo-random function des-cbc(md5(input-string), ivec=0)
key generation functions:
string-to-key des_string_to_key
random-to-key copy input, then fix parity bits
key-derivation identity
the des-cbc-crc encryption algorithm is assigned the etype value one (1) ๐
6.2.4. RSA MD5 Cryptographic Checksum Using DES ๐ธ
the RSA-MD5-DES checksum is a keyed, collision-proof checksum ๐ here's how it works, bestie: it prepends an eight octet confounder before the text, applies the RSA MD5 checksum algorithm, then encrypts the confounder and the checksum with DES in CBC mode. the key gets XORed with the hex constant 0xF0F0F0F0F0F0F0F0 first, so that's the variant you actually use โจ the initialization vector should be zero, and the resulting checksum is 24 octets long ๐
rsa-md5-des
----------------------------------------------------------------
associated cryptosystem des-cbc-md5, des-cbc-md4, des-cbc-crc
get_mic des-cbc(key XOR 0xF0F0F0F0F0F0F0F0,
conf | rsa-md5(conf | msg))
verify_mic decrypt and verify rsa-md5 checksum
the rsa-md5-des checksum algorithm is assigned a checksum type number of eight (8) ๐ฆ
6.2.5. RSA MD4 Cryptographic Checksum Using DES ๐ง
the RSA-MD4-DES checksum is basically the same energy ๐ it's keyed and collision-proof too. it prepends an eight octet confounder, applies the RSA MD4 checksum algorithm [MD4-92], and then encrypts the confounder and the checksum with DES in CBC mode. the key is XORed with the constant 0xF0F0F0F0F0F0F0F0 [7] to get the variant, and the initialization vector should be zero. the resulting checksum is 24 octets long ๐
rsa-md4-des
----------------------------------------------------------------
associated cryptosystem des-cbc-md5, des-cbc-md4, des-cbc-crc
get_mic des-cbc(key XOR 0xF0F0F0F0F0F0F0F0,
conf | rsa-md4(conf | msg),
ivec=0)
verify_mic decrypt and verify rsa-md4 checksum
the rsa-md4-des checksum algorithm is assigned a checksum type number of three (3) ๐
6.2.6. RSA MD4 Cryptographic Checksum Using DES Alternative ๐
the RSA-MD4-DES-K checksum is a keyed, collision-proof checksum too ๐ it applies the RSA MD4 checksum algorithm, then encrypts the result with DES in CBC mode, using a DES key as both the key and the initialization vector. the resulting checksum is 16 octets long. it's tamper-proof and believed to be collision-proof ๐ก๏ธ
โ ๏ธ heads up: this checksum type is the old method for encoding the RSA-MD4-DES checksum. it is no longer recommended, so be careful with it ๐
rsa-md4-des-k
----------------------------------------------------------------
associated cryptosystem des-cbc-md5, des-cbc-md4, des-cbc-crc
get_mic des-cbc(key, md4(msg), ivec=key)
verify_mic decrypt, compute checksum and compare
the rsa-md4-des-k checksum algorithm is assigned a checksum type number of six (6) ๐ธ
6.2.7. DES CBC Checksum โจ
the DES-MAC checksum goes like this ๐ซถ you prepend an eight octet confounder to the plaintext, pad it with zero-valued octets if needed so the length is a multiple of eight octets, and run DES CBC-mode encryption on the result using the key and an all-zero initialization vector. then you take the last block of the ciphertext, prepend the same confounder, and encrypt that pair with DES in CBC mode using the key variant (the key XORed with 0xF0F0F0F0F0F0F0F0). the initialization vector should be zero. the resulting checksum is 128 bits (sixteen octets) long, and 64 bits of it are redundant ๐คฏ it's tamper-proof and collision-proof ๐
des-mac
---------------------------------------------------------------------
associated des-cbc-md5, des-cbc-md4, des-cbc-crc
cryptosystem
get_mic des-cbc(key XOR 0xF0F0F0F0F0F0F0F0,
conf | des-mac(key, conf | msg | pad, ivec=0),
ivec=0)
verify_mic decrypt, compute DES MAC using confounder, compare
the des-mac checksum algorithm is assigned a checksum type number of four (4) ๐ฆ
6.2.8. DES CBC Checksum Alternative ๐
the DES-MAC-K checksum is computed by doing DES CBC-mode encryption of the plaintext, with zero-valued padding bytes if needed to make the length a multiple of eight octets. the last block of the ciphertext becomes the checksum value ๐ง it's keyed with an encryption key, and that same key is also used as the initialization vector. the resulting checksum is 64 bits (eight octets) long, and it's tamper-proof and collision-proof ๐ฅ
โ ๏ธ this one is the old way of encoding the DESMAC checksum. it is no longer recommended ๐ญ
des-mac-k
----------------------------------------------------------------
associated cryptosystem des-cbc-md5, des-cbc-md4, des-cbc-crc
get_mic des-mac(key, msg | pad, ivec=key)
verify_mic compute MAC and compare
the des-mac-k checksum algorithm is assigned a checksum type number of five (5) ๐
6.3. Triple-DES Based Encryption and Checksum Types โจ
okay so this pair is built on the Triple DES cryptosystem running in Outer-CBC mode, with HMAC-SHA1 handling the message authentication ๐๐
a Triple DES key is basically three DES keys stuck together, just like the des-cbc-md5 description above ๐งฉ and each of the three gets made from its own separate chunk of random data ๐ฒโจ
encrypted data using this type must be generated the way section 5.3 describes ๐ธ if your input isn't a multiple of the block size, zero-valued octets must be used to pad the plaintext out to the next eight-octet boundary ๐ and the confounder must be eight random octets, which is one block ๐ซถ
here's the simplified profile for Triple DES, with the key derivation from section 5 ๐ฆ
des3-cbc-hmac-sha1-kd, hmac-sha1-des3-kd
------------------------------------------------
protocol key format 24 bytes, parity in low
bit of each
key-generation seed 21 bytes
length
des3-cbc-hmac-sha1-kd, hmac-sha1-des3-kd
------------------------------------------------
hash function SHA-1
HMAC output size 160 bits
message block size 8 bytes
default string-to-key empty string
params
encryption and triple-DES encrypt and
decryption functions decrypt, in outer-CBC
mode (cipher block size
8 octets)
key generation functions:
random-to-key DES3random-to-key (see
below)
string-to-key DES3string-to-key (see
below)
the des3-cbc-hmac-sha1-kd encryption type gets the value sixteen (16) ๐ and the hmac-sha1-des3-kd checksum algorithm gets checksum type number twelve (12) ๐
6.3.1. Triple DES Key Production (random-to-key, string-to-key)
so here's how the 168 bits of random key data turn into a protocol key value ๐ง first, the 168 bits get split into three groups of 56 bits, and each group gets expanded into 64 bits like this โจ
DES3random-to-key:
1 2 3 4 5 6 7 p
9 10 11 12 13 14 15 p
17 18 19 20 21 22 23 p
25 26 27 28 29 30 31 p
33 34 35 36 37 38 39 p
41 42 43 44 45 46 47 p
49 50 51 52 53 54 55 p
56 48 40 32 24 16 8 p
the "p" bits are parity bits, worked out from the data bits ๐ then the outputs from all three expansions get fixed up so they dodge "weak" and "semi-weak" keys (same trick as section 6.2), and then they're glued together to form the protocol key value ๐
the string-to-key function is what turns UTF-8 passwords into DES3 keys ๐ and it leans on the "N-fold" algorithm and the DK function, both from section 5 ๐
the n-fold algorithm gets applied to the password string smooshed together with a salt value ๐ for 3-key triple DES that means a 168-fold of the input password string, which makes an intermediate key, and then the DK function derives the user's long-term key from that ๐ here's the DES3 string-to-key function in pseudocode ๐
DES3string-to-key(passwordString, salt, params)
if (params != emptyString)
error("invalid params");
s = passwordString + salt
tmpKey = random-to-key(168-fold(s))
key = DK (tmpKey, KerberosConstant)
weak key checking happens inside both the random-to-key and DK operations ๐ and the KerberosConstant value is the byte string {0x6b 0x65 0x72 0x62 0x65 0x72 0x6f 0x73}, which is just the ASCII for the string "kerberos" ๐ธ
7. Use of Kerberos Encryption Outside This Specification ๐
ngl this part is so relatable ๐ญ a bunch of Kerberos-based application protocols and preauthentication systems have been built and deployed, and they all do encryption and message integrity checks in their own ways ๐ sometimes there's a good reason to pin a protocol to specific algorithms, but we think that's usually not the case, and more generic approaches that don't depend on particular algorithms are going to be way more useful ๐ฆ nobody wants every protocol designer reinventing the wheel for protecting data, handling multiple keys, and so on, so this section is a general framework ๐ it's meant to be enough for Kerberos itself and for lots of preauthentication systems and application protocols, while steering clear of some sneaky assumptions that can creep into protocol designs ๐
some problematic assumptions we've seen (and honestly, sometimes made ourselves) are these ๐
- a random bitstring is always valid as a key. not true for DES keys with parity ๐
- the basic block encryption chaining mode provides no integrity checking, or can easily be separated from such checking. not true for many modes in development that do both at once โจ
- a checksum for a message always comes out the same value. not true if a confounder is in the mix ๐ธ
- an initial vector is used. this may not be true if a block cipher in CBC mode isn't in use ๐ซถ
these assumptions might hold for any particular set of encryption and checksum algorithms, but they might not hold for the next algorithms that get defined ๐ฌ and then the application protocol is stuck, unable to use those algorithms without updating its spec ๐
the Kerberos protocol only uses the attributes and operations from sections 3 and 4 ๐ and preauthentication systems and application protocols that use Kerberos are encouraged to do the same ๐ง the specific key and string-to-key parameters should generally be treated as opaque ๐ the string-to-key parameters are handled as an octet string, but how the specific key structure is represented is implementation defined, and it might not even be one single object ๐
we don't recommend this, but some application protocols are definitely going to keep using the key data directly, even if it's only in some of the existing protocol specs ๐ค so an implementation meant to support general Kerberos applications may need to make the key data available, along with the attributes and operations from sections 3 and 4 [8] ๐
8. Assigned Numbers ๐ข
these encryption-type numbers are already assigned or reserved for Kerberos and related protocols ๐
encryption type etype section or comment
-----------------------------------------------------------------
des-cbc-crc 1 6.2.3
des-cbc-md4 2 6.2.2
des-cbc-md5 3 6.2.1
[reserved] 4
des3-cbc-md5 5
[reserved] 6
des3-cbc-sha1 7
dsaWithSHA1-CmsOID 9 (pkinit)
md5WithRSAEncryption-CmsOID 10 (pkinit)
sha1WithRSAEncryption-CmsOID 11 (pkinit)
rc2CBC-EnvOID 12 (pkinit)
rsaEncryption-EnvOID 13 (pkinit from PKCS#1 v1.5)
rsaES-OAEP-ENV-OID 14 (pkinit from PKCS#1 v2.0)
des-ede3-cbc-Env-OID 15 (pkinit)
des3-cbc-sha1-kd 16 6.3
aes128-cts-hmac-sha1-96 17 [KRB5-AES]
aes256-cts-hmac-sha1-96 18 [KRB5-AES]
rc4-hmac 23 (Microsoft)
rc4-hmac-exp 24 (Microsoft)
subkey-keymaterial 65 (opaque; PacketCable)
(heads up: the "des3-cbc-sha1" assignment is a deprecated version that uses no key derivation ๐ โโ๏ธ so don't mix it up with des3-cbc-sha1-kd!)
several numbers have been reserved for encryption systems that aren't defined here ๐ง and encryption-type numbers have unfortunately been overloaded here and there in Kerberos-related protocols, so some of those reserved numbers won't ever line up with encryption systems that fit the profile we just laid out ๐ฉ
next up, the checksum-type numbers that are assigned or reserved ๐ same deal as before, some checksum numbers have been overloaded too ๐
Checksum type sumtype checksum section or
value size reference
---------------------------------------------------------------------
CRC32 1 4 6.1.3
rsa-md4 2 16 6.1.2
rsa-md4-des 3 24 6.2.5
des-mac 4 16 6.2.7
des-mac-k 5 8 6.2.8
rsa-md4-des-k 6 16 6.2.6
rsa-md5 7 16 6.1.1
rsa-md5-des 8 24 6.2.4
rsa-md5-des3 9 24 ??
sha1 (unkeyed) 10 20 ??
hmac-sha1-des3-kd 12 20 6.3
hmac-sha1-des3 13 20 ??
sha1 (unkeyed) 14 20 ??
hmac-sha1-96-aes128 15 20 [KRB5-AES]
hmac-sha1-96-aes256 16 20 [KRB5-AES]
[reserved] 0x8003 ? [GSS-KRB5]
encryption and checksum-type numbers are signed 32-bit values ๐ข zero is invalid, negative numbers are reserved for local use ๐ and all standardized values must be positive โจ
9. Implementation Notes ๐
the "interface" described here is the minimal info that must be defined to make a cryptosystem useful within Kerberos in an interoperable way ๐ซถ the functional notation that shows up in some places isn't an attempt to define an API for cryptographic functionality within Kerberos ๐ โโ๏ธ real implementations with clean APIs will probably expose extra info that could be derived from a spec written to the framework here ๐ for example, an application designer might want to know the largest number of bytes that can be encrypted without overflowing a certain size output buffer, or the other way around, the maximum number of bytes you might get from decrypting a ciphertext of a given size ๐งฎ (and fun fact, an implementation of the GSS-API Kerberos mechanism [GSS-KRB5] will need some of these ๐ธ)
the presence of a mechanism in this document shouldn't be read as meaning it has to be implemented for compliance with any spec ๐จ required mechanisms will be specified elsewhere ๐ also, some of the mechanisms described here are kept around for backward compatibility, and they're now considered pretty weak for protecting critical data ๐
10. Security Considerations ๐
Okay bestie, DES has been getting absolutely roasted ๐ by large-scale attacks for years now, so it is no longer considered a strong encryption mechanism. Triple-DES is generally the one people reach for instead, even though it's slower (poorer performance ๐ญ). Check [ESP-DES] for a summary of some of the potential attacks and [EFF-DES] for a detailed look at how particular attacks are built. Still, most Kerberos implementations keep DES as their primary interoperable encryption type, so it's giving "we can't let go yet" ๐ซ .
DES has four 'weak' keys and twelve 'semi-weak' keys, and using single-DES here avoids them โจ. BUT DES also has 48 'possibly-weak' keys [Schneier96] that are not avoided ๐ฌ. (Heads up: the tables in many editions of that reference have errors ๐.)
DES weak keys have the property that E1(E1(P)) = P, where E1 means encrypting a single block with key 1. DES semi-weak keys, aka "dual" keys, come in pairs with E1(P) = D2(P), and so E2(E1(P)) = P. Because CBC mode and the leading random confounder are used, though, these properties are unlikely to be a security problem ๐.
Many of the choices about when to do weak-key corrections are about compatibility with existing implementations more than any risk analysis ๐งฉ.
Checks are also done for the component DES keys inside a triple-DES key. The nature of weak keys makes it extremely unlikely they'll weaken triple-DES encryption. It's only slightly more likely that the middle of the three sub-keys matches one of the other two, which effectively turns the encryption into single-DES. That's a case we make no effort to avoid ๐.
The true CRC-32 checksum is not collision-proof. An attacker could use a probabilistic chosen-plaintext attack to generate a valid message even if a confounder is used [SG92]. Collision-proof checksums are of course recommended for environments where these attacks are a significant threat ๐ก๏ธ. The "simplifications" (read: bugs) introduced when CRC-32 was implemented for Kerberos cause leading zeros to be effectively ignored, so messages differing only in leading zero bits will have the same checksum ๐.
[HMAC] and [IPSEC-HMAC] discuss weaknesses of the HMAC algorithm. Unlike [IPSEC-HMAC], the triple-DES specification here does not use the suggested truncation of the HMAC output. As pointed out in [IPSEC-HMAC], SHA-1 was not developed for use as a keyed hash function, which is a criterion of HMAC. [HMAC-TEST] contains test vectors for HMAC-SHA-1 ๐งช.
The mit_des_string_to_key function was originally built on the assumption that all input would be ASCII. It ignores the top bit of each input byte. Folding with XOR also isn't an especially good mixing mechanism for preserving randomness ๐ฉ.
The n-fold function used in the string-to-key operation for des3-cbc-hmac-sha1-kd was designed so that each bit of input contributes equally to the output. It was not designed to maximize or equally distribute randomness in the input, and randomness may conceivably be lost with partially structured input. This should only be an issue for highly structured passwords, though ๐.
[RFC1851] discusses the relative strength of triple-DES encryption. The relatively slow speed of triple-DES may also be an issue for some applications ๐ข.
[Bellovin91] suggests that analyses of encryption schemes include a model of an attacker who can submit known plaintexts to be encrypted with an unknown key, and who can perform many types of operations on known protocol messages. Recent chosen-plaintext attacks on Kerberos version 4 totally prove the value of this suggestion ๐.
The use of unkeyed encrypted checksums, like those used in the single-DES cryptosystems specified in [Kerb1510], allows cut-and-paste attacks, especially if a confounder is not used. Unkeyed encrypted checksums are also vulnerable to chosen-plaintext attacks: an attacker with access to an encryption oracle can easily encrypt the required unkeyed checksum along with the chosen plaintext [Bellovin99]. These weaknesses, combined with a common implementation design choice described below, allow for a cross-protocol attack from version 4 to version 5 ๐ฑ.
The use of a random confounder is an important way to stop an attacker from making effective use of protocol exchanges as an encryption oracle. In Kerberos version 4, encrypting constant plaintext to constant ciphertext makes an effective encryption oracle for an attacker. The use of random confounders in [Kerb1510] frustrates this sort of chosen-plaintext attack ๐ธ.
Using the same key for multiple purposes can enable or increase the scope of chosen-plaintext attacks. Some software that implements both versions 4 and 5 of the Kerberos protocol uses the same keys for both versions. That lets the version 4 encryption oracle be used to attack version 5. Vulnerabilities to attacks like this cross-protocol attack make it unwise to use a key for multiple purposes ๐ซ.
โ ๏ธ This document, like the Kerberos protocol, does not address limiting the amount of data a key may be used with to a quantity based on the robustness of the algorithm or the size of the key. It is assumed that any defined algorithms and key sizes will be strong enough to support very large amounts of data, or that they will be deprecated once significant attacks are known.
This document also places no bounds on the amount of data that can be handled in various operations. To avoid denial of service attacks, implementations will probably seek to restrict message sizes at some higher level ๐งฑ.
11. IANA Considerations ๐
Two registries for numeric values have been created: Kerberos Encryption Type Numbers and Kerberos Checksum Type Numbers. These are signed values ranging from -2147483648 to 2147483647. Positive values should be assigned only for algorithms specified in accordance with this specification for use with Kerberos or related protocols. Negative values are for private use, so local and experimental algorithms should use those. Zero is reserved and may not be assigned ๐ข.
Positive encryption- and checksum-type numbers may be assigned following either of two policies described in [BCP26].
Standards-track specifications may be assigned values under the Standards Action policy ๐๏ธ.
Specifications in non-standards track RFCs may be assigned values after Expert Review. A non-IETF specification may be assigned values by publishing an Informational or standards-track RFC that references the external specification. That specification must be public and published in some permanent record, much like the IETF RFCs. It is highly desirable, though not required, that the full specification be published as an IETF RFC โจ.
Smaller encryption type values should be used for IETF standards-track mechanisms, and much higher values (16777216 and above) for other mechanisms. (Rationale: in the Kerberos ASN.1 encoding, smaller numbers encode to smaller octet sequences, so this favors standards-track mechanisms with slightly smaller messages ๐ง .) Aside from that guideline, IANA may choose numbers as it sees fit.
Internet-Draft specifications should not include values for encryption- and checksum-type numbers. Instead, they should indicate that values would be assigned by IANA when the document is approved as an RFC. For development and interoperability testing, values in the private-use range (negative values) may be used, but they should not be included in the draft specification ๐งช.
Each registered value should have an associated unique reference name. The lists given in section 8 were used to create the initial registry. They include reservations for specifications in progress in parallel with this document, and certain other values believed to already be in use ๐.
12. Acknowledgements ๐ซถ
This document is an extension of the encryption specification included in [Kerb1510] by B. Clifford Neuman and John Kohl, and much of the text on background, concepts, and DES specifications is drawn directly from that document ๐.
The abstract framework presented in this document was put together by Jeff Altman, Sam Hartman, Jeff Hutzelman, Cliff Neuman, Ken Raeburn, and Tom Yu. The details were refined several times based on comments from John Brezak and others ๐.
Marc Horowitz wrote the original specification of triple-DES and key derivation in a pair of Internet-Drafts (under the names draft-horowitz-key-derivation and draft-horowitz-kerb-key-derivation). Those were later folded into a draft revision of [Kerb1510], from which this document was later split off ๐.
Tom Yu provided the text describing the modifications to the standard CRC algorithm as Kerberos implementations actually use it, and some of the text in the Security Considerations section ๐ฆ.
Miroslav Jurisic provided information for one of the UTF-8 test cases for the string-to-key functions ๐ธ.
Marcus Watts noticed some errors in earlier versions and pointed out that the simplified profile could easily be modified to support cipher text stealing modes ๐.
Simon Josefsson contributed some clarifications to the DES "CBC checksum" and string-to-key and weak key descriptions, plus some test vectors ๐ง.
Simon Josefsson, Louis LeVay, and others also caught some errors in earlier versions of this document ๐.
A. Test Vectors ๐งช
This section provides test vectors for various functions defined or described in this document. For convenience, most inputs are ASCII strings, though some UTF-8 samples are provided for string-to-key functions. Keys and other binary data are specified as hexadecimal strings โจ.
A.1. n-fold โจ
okay so the n-fold function lives in section 5.1 ๐ and there's a little plot twist there: the sample vector in the original paper that defines the algorithm looks wrong ๐ญ so we've got better test cases, courtesy of Marc Horowitz and Simon Josefsson ๐ซถ
64-fold("012345") =
64-fold(303132333435) = be072631276b1955
56-fold("password") =
56-fold(70617373776f7264) = 78a07b6caf85fa
64-fold("Rough Consensus, and Running Code") =
64-fold(526f75676820436f6e73656e7375732c20616e642052756e
6e696e6720436f6465) = bb6ed30870b7f0e0
168-fold("password") =
168-fold(70617373776f7264) =
59e4a8ca7c0385c3c37b3f6d2000247cb6e6bd5b3e
192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY")
192-fold(4d41535341434856534554545320494e5354495456544520
4f4620544543484e4f4c4f4759) =
db3b0d8f0b061e603282b308a50841229ad798fab9540c1b
168-fold("Q") =
168-fold(51) =
518a54a2 15a8452a 518a54a2 15a8452a
518a54a2 15
168-fold("ba") =
168-fold(6261) =
fb25d531 ae897449 9f52fd92 ea9857c4
ba24cf29 7e
Here are some extra values for the folded forms of the string "kerberos" ๐ The 64-bit one is the star of the show because the des3 string-to-key in section 6.3.1 uses it ๐
64-fold("kerberos") =
6b657262 65726f73
128-fold("kerberos") =
6b657262 65726f73 7b9b5b2b 93132b93
168-fold("kerberos") =
8372c236 344e5f15 50cd0747 e15d62ca
7a5a3bce a4
256-fold("kerberos") =
6b657262 65726f73 7b9b5b2b 93132b93
5c9bdcda d95c9899 c4cae4de e6d6cae4
Note: the first octets match the input string exactly whenever the output length is a multiple of the input length ๐
A.2. mit_des_string_to_key ๐ง
okay the function mit_des_string_to_key is defined in section 6.2, and here are a bunch of test values ๐ We also show some of the middle steps so you can see the receipts ๐งพ The fourth test is the one with UTF-8 across three characters, and the last two are built on purpose to make the fan-folding produce an intermediate key that hits the weak-key fixups ๐ฅ Heads up though: we don't have any tests that trigger those fixups on the final key ๐
Here's how the UTF-8 encodings used in the test vector look ๐
UTF-8 encodings used in test vector:
eszett U+00DF C3 9F s-caron U+0161 C5 A1
c-acute U+0107 C4 87 g-clef U+1011E F0 9D 84 9E
Now the test vectors themselves ๐
Test vector:
salt: "ATHENA.MIT.EDUraeburn"
415448454e412e4d49542e4544557261656275726e
password: "password" 70617373776f7264
fan-fold result: c01e38688ac86c2e
intermediate key: c11f38688ac86d2f
DES key: cbc22fae235298e3
salt: "WHITEHOUSE.GOVdanny"
5748495445484f5553452e474f5664616e6e79
password: "potatoe" 706f7461746f65
fan-fold result: a028944ee63c0416
intermediate key: a129944fe63d0416
DES key: df3d32a74fd92a01
salt: "EXAMPLE.COMpianist" 4558414D504C452E434F4D7069616E697374
password: g-clef (U+1011E) f09d849e
fan-fold result: 3c4a262c18fab090
intermediate key: 3d4a262c19fbb091
DES key: 4ffb26bab0cd9413
salt: "ATHENA.MIT.EDUJuri" + s-caron(U+0161) + "i" + c-acute(U+0107)
415448454e412e4d49542e4544554a757269c5a169c487
password: eszett(U+00DF)
c39f
fan-fold result:b8f6c40e305afc9e
intermediate key: b9f7c40e315bfd9e
DES key: 62c81a5232b5e69d
salt: "AAAAAAAA" 4141414141414141
password: "11119999" 3131313139393939
fan-fold result: e0e0e0e0f0f0f0f0
intermediate key: e0e0e0e0f1f1f101
DES key: 984054d0f1a73e31
salt: "FFFFAAAA" 4646464641414141
password: "NNNN6666" 4e4e4e4e36363636
fan-fold result: 1e1e1e1e0e0e0e0e
intermediate key: 1f1f1f1f0e0e0efe
DES key: c4bf6b25adf7a4f8
This trace from Simon Josefsson is my favourite because it shows every single step of one of the inputs ๐ It's giving full detective mode ๐ต๏ธโโ๏ธ
This trace provided by Simon Josefsson shows the intermediate
processing stages of one of the test inputs:
string_to_key (des-cbc-md5, string, salt)
;; string:
;; `password' (length 8 bytes)
;; 70 61 73 73 77 6f 72 64
;; salt:
;; `ATHENA.MIT.EDUraeburn' (length 21 bytes)
;; 41 54 48 45 4e 41 2e 4d 49 54 2e 45 44 55 72 61
;; 65 62 75 72 6e
des_string_to_key (string, salt)
;; String:
;; `password' (length 8 bytes)
;; 70 61 73 73 77 6f 72 64
;; Salt:
;; `ATHENA.MIT.EDUraeburn' (length 21 bytes)
;; 41 54 48 45 4e 41 2e 4d 49 54 2e 45 44 55 72 61
;; 65 62 75 72 6e
odd = 1;
s = string | salt;
tempstring = 0; /* 56-bit string */
pad(s); /* with nulls to 8 byte boundary */
;; s = pad(string|salt):
;; `passwordATHENA.MIT.EDUraeburn\x00\x00\x00'
;; (length 32 bytes)
;; 70 61 73 73 77 6f 72 64 41 54 48 45 4e 41 2e 4d
;; 49 54 2e 45 44 55 72 61 65 62 75 72 6e 00 00 00
for (8byteblock in s) {
;; loop iteration 0
;; 8byteblock:
;; `password' (length 8 bytes)
;; 70 61 73 73 77 6f 72 64
;; 01110000 01100001 01110011 01110011 01110111 01101111
;; 01110010 01100100
56bitstring = removeMSBits(8byteblock);
;; 56bitstring:
;; 1110000 1100001 1110011 1110011 1110111 1101111
;; 1110010 1100100
if (odd == 0) reverse(56bitstring); ;; odd=1
odd = ! odd
tempstring = tempstring XOR 56bitstring;
;; tempstring
;; 1110000 1100001 1110011 1110011 1110111 1101111
;; 1110010 1100100
for (8byteblock in s) {
;; loop iteration 1
;; 8byteblock:
;; `ATHENA.M' (length 8 bytes)
;; 41 54 48 45 4e 41 2e 4d
;; 01000001 01010100 01001000 01000101 01001110 01000001
;; 00101110 01001101
56bitstring = removeMSBits(8byteblock);
;; 56bitstring:
;; 1000001 1010100 1001000 1000101 1001110 1000001
;; 0101110 1001101
if (odd == 0) reverse(56bitstring); ;; odd=0
reverse(56bitstring)
;; 56bitstring after reverse
;; 1011001 0111010 1000001 0111001 1010001 0001001
;; 0010101 1000001
odd = ! odd
tempstring = tempstring XOR 56bitstring;
;; tempstring
;; 0101001 1011011 0110010 1001010 0100110 1100110
;; 1100111 0100101
for (8byteblock in s) {
;; loop iteration 2
;; 8byteblock:
;; `IT.EDUra' (length 8 bytes)
;; 49 54 2e 45 44 55 72 61
;; 01001001 01010100 00101110 01000101 01000100 01010101
;; 01110010 01100001
56bitstring = removeMSBits(8byteblock);
;; 56bitstring:
;; 1001001 1010100 0101110 1000101 1000100 1010101
;; 1110010 1100001
if (odd == 0) reverse(56bitstring); ;; odd=1
odd = ! odd
tempstring = tempstring XOR 56bitstring;
;; tempstring
;; 1100000 0001111 0011100 0001111 1100010 0110011
;; 0010101 1000100
for (8byteblock in s) {
;; loop iteration 3
;; 8byteblock:
;; `eburn\x00\x00\x00' (length 8 bytes)
;; 65 62 75 72 6e 00 00 00
;; 01100101 01100010 01110101 01110010 01101110 00000000
;; 00000000 00000000
56bitstring = removeMSBits(8byteblock);
;; 56bitstring:
;; 1100101 1100010 1110101 1110010 1101110 0000000
;; 0000000 0000000
if (odd == 0) reverse(56bitstring); ;; odd=0
reverse(56bitstring)
;; 56bitstring after reverse
;; 0000000 0000000 0000000 0111011 0100111 1010111
;; 0100011 1010011
odd = ! odd
tempstring = tempstring XOR 56bitstring;
;; tempstring
;; 1100000 0001111 0011100 0110100 1000101 1100100
;; 0110110 0010111
for (8byteblock in s) {
}
;; for loop terminated
tempkey = key_correction(add_parity_bits(tempstring));
;; tempkey
;; `\xc1\x1f8h\x8a\xc8m\x2f' (length 8 bytes)
;; c1 1f 38 68 8a c8 6d 2f
;; 11000001 00011111 00111000 01101000 10001010 11001000
;; 01101101 00101111
key = key_correction(DES-CBC-check(s,tempkey));
;; key
;; `\xcb\xc2\x2f\xae\x23R\x98\xe3' (length 8 bytes)
;; cb c2 2f ae 23 52 98 e3
;; 11001011 11000010 00101111 10101110 00100011 01010010
;; 10011000 11100011
;; string_to_key key:
;; `\xcb\xc2\x2f\xae\x23R\x98\xe3' (length 8 bytes)
;; cb c2 2f ae 23 52 98 e3
A.3. DES3 DR and DK ๐
these tests show the derived-random (DR) and derived-key (DK) values for the des3-hmac-sha1-kd encryption scheme ๐ฆ They use the DR and DK functions from section 6.3.1 ๐ The input keys were randomly generated, but the usage values come straight from this specification ๐ธ
key: dce06b1f64c857a11c3db57c51899b2cc1791008ce973b92
usage: 0000000155
DR: 935079d14490a75c3093c4a6e8c3b049c71e6ee705
DK: 925179d04591a79b5d3192c4a7e9c289b049c71f6ee604cd
key: 5e13d31c70ef765746578531cb51c15bf11ca82c97cee9f2
usage: 00000001aa
DR: 9f58e5a047d894101c469845d67ae3c5249ed812f2
DK: 9e58e5a146d9942a101c469845d67a20e3c4259ed913f207
key: 98e6fd8a04a4b6859b75a176540b9752bad3ecd610a252bc
usage: 0000000155
DR: 12fff90c773f956d13fc2ca0d0840349dbd39908eb
DK: 13fef80d763e94ec6d13fd2ca1d085070249dad39808eabf
key: 622aec25a2fe2cad7094680b7c64940280084c1a7cec92b5
usage: 00000001aa
DR: f8debf05b097e7dc0603686aca35d91fd9a5516a70
DK: f8dfbf04b097e6d9dc0702686bcb3489d91fd9a4516b703e
key: d3f8298ccb166438dcb9b93ee5a7629286a491f838f802fb
usage: 6b65726265726f73 ("kerberos")
DR: 2270db565d2a3d64cfbfdc5305d4f778a6de42d9da
DK: 2370da575d2a3da864cebfdc5204d56df779a7df43d9da43
key: c1081649ada74362e6a1459d01dfd30d67c2234c940704da
usage: 0000000155
DR: 348056ec98fcc517171d2b4d7a9493af482d999175
DK: 348057ec98fdc48016161c2a4c7a943e92ae492c989175f7
key: 5d154af238f46713155719d55e2f1f790dd661f279a7917c
usage: 00000001aa
DR: a8818bc367dadacbe9a6c84627fb60c294b01215e5
DK: a8808ac267dada3dcbe9a7c84626fbc761c294b01315e5c1
key: 798562e049852f57dc8c343ba17f2ca1d97394efc8adc443
usage: 0000000155
DR: c813f88b3be2b2f75424ce9175fbc8483b88c8713a
DK: c813f88a3be3b334f75425ce9175fbe3c8493b89c8703b49
key: 26dce334b545292f2feab9a8701a89a4b99eb9942cecd016
usage: 00000001aa
DR: f58efc6f83f93e55e695fd252cf8fe59f7d5ba37ec
DK: f48ffd6e83f83e7354e694fd252cf83bfe58f7d5ba37ec5d
A.4. DES3string_to_key โจ
okay so this is where we get the keys for triple-DES, and they're generated with the key derivation from section 6.3.1 ๐ here are some of the input strings and the keys they produce, bestie ๐
salt: "ATHENA.MIT.EDUraeburn"
passwd: "password"
key: 850bb51358548cd05e86768c313e3bfef7511937dcf72c3e
salt: "WHITEHOUSE.GOVdanny"
passwd: "potatoe"
key: dfcd233dd0a43204ea6dc437fb15e061b02979c1f74f377a
salt: "EXAMPLE.COMbuckaroo"
passwd: "penny"
key: 6d2fcdf2d6fbbc3ddcadb5da5710a23489b0d3b69d5d9d4a
salt: "ATHENA.MIT.EDUJuri" + s-caron(U+0161) + "i"
+ c-acute(U+0107)
passwd: eszett(U+00DF)
key: 16d5a40e1ce3bacb61b9dce00470324c831973a7b952feb0
salt: "EXAMPLE.COMpianist"
passwd: g-clef(U+1011E)
key: 85763726585dbc1cce6ec43e1f751f07f1c4cbb098f40b19
A.5. Modified CRC-32 ๐ฆ
so here are the modified-CRC32 values for a bunch of ASCII and octet strings ๐ธ only the printable ASCII characters get checksummed, and there's no C-style trailing zero-valued octet tacked on at the end ๐ you'll see the 32-bit modified CRC and the output bytes in the order Kerberos uses them. the octets are split up on purpose so you can see they're octet values and not 32-bit numbers, since that's the handiest form for some implementations to work with ๐ the bit and byte order you use inside your own code doesn't matter at all, the octet sequence that comes out is the part that counts โจ
mod-crc-32("foo") = 33 bc 32 73
mod-crc-32("test0123456789") = d6 88 3e b8
mod-crc-32("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") = f7 80 41 e3
mod-crc-32(8000) = 4b 98 83 3b
mod-crc-32(0008) = 32 88 db 0e
mod-crc-32(0080) = 20 83 b8 ed
mod-crc-32(80) = 20 83 b8 ed
mod-crc-32(80000000) = 3b b6 59 ed
mod-crc-32(00000001) = 96 30 07 77
B. Significant Changes from RFC 1510 ๐
the encryption and checksum mechanism profiles are brand new, and that's a big glow-up ๐ the old spec defined a few operations for various mechanisms, but it never said what abstract properties a new mechanism should have, or how to make sure a mechanism spec is complete enough for different implementations to actually talk to each other ๐ญ so the new profiles are different from the old one in a few ways:
Some message definitions in [Kerb1510] could be read as permitting the initial vector to be specified by the application; the text was too vague. It is explicitly not permitted in this specification. Some encryption algorithms may not use initialization vectors, so relying on chosen, secret initialization vectors for security is unwise. Also, the prepended confounder in the existing algorithms is roughly equivalent to a per-message initialization vector that is revealed in encrypted form. However, carrying state across from one encryption to another is explicitly permitted through the opaque "cipher state" object.
so the app can't pick the initial vector anymore, and that's a whole vibe check ๐ โโ๏ธ carrying state between encryptions is still allowed though, through that opaque "cipher state" object ๐ง
key derivation is new ๐
several new methods got introduced, including making a key in wire-protocol format from random input data ๐ฒ
the means for influencing the string-to-key algorithm are laid out way more clearly now ๐
triple-DES support is new ๐
the pseudo-random function is new too ๐ฆ
the des-cbc-crc, DES string-to-key, and CRC descriptions got updated so they line up with what existing implementations actually do ๐
[Kerb1510] didn't say what character set or encoding to use for pass phrases and salts, which was lowkey chaos ๐ซ
in [Kerb1510], key types, encryption algorithms, and checksum algorithms were only loosely connected, and nobody really described the connection well ๐ต in this spec, key types and encryption algorithms have a one-to-one correspondence, and the links between encryption and checksum algorithms are described so checksums can be computed from negotiated keys without negotiating a checksum type separately ๐
Notes ๐
[1] ngl, Message Authentication Code (MAC) or Message Integrity Check (MIC) would fit a lot of the uses in this document better, but we keep saying checksum for historical reasons ๐
[2] extending CBC mode across messages would be one obvious example of this chaining ๐ another could be counter mode, with a counter that's randomly initialized and attached to the ciphertext, and a second message could keep incrementing that counter when chaining the cipher state, so you don't have to send another counter value ๐ข but this chaining is only useful for uninterrupted, ordered sequences of messages, so keep that in mind ๐
[3] for Kerberos, the encrypted objects will usually be ASN.1 DER encodings, which tell you their length in the first few octets ๐
[4] as of when this was written, new modes of operation had been proposed, and some of them might let you do encryption and integrity protection at the same time ๐คฏ once some of those proposals get enough analysis, we may want to make a new simplified profile based on one of them ๐
[5] it should be noted that the sample vector in appendix B.2 of the original paper looks incorrect ๐ฌ two independent implementations from the specification (one in C by Marc Horowitz, and another in Scheme by Bill Sommerfeld) agree on a value that's different from the one in [Blumenthal96] ๐ซฃ
[6] for example, in MIT's implementation of [Kerb1510], the rsa-md5 unkeyed checksum of application data may be included in an authenticator encrypted in a service's key ๐
[7] using a variant of the key limits a key to one particular function, which separates generating a checksum from other encryption done with the session key ๐งฉ the constant 0xF0F0F0F0F0F0F0F0 was picked because it keeps the key parity intact ๐ฏ the properties of DES ruled out using the complement ๐ซ the same constant is used for a similar purpose in the Message Integrity Check in the Privacy Enhanced Mail standard ๐
[8] one of the more common reasons for directly performing encryption is direct control over the negotiation, to pick a "sufficiently strong" encryption algorithm (whatever that even means for a given application) ๐คทโโ๏ธ Kerberos doesn't directly give you any facility for negotiating encryption types between the application client and server, but there are other ways to get similar goals, like requesting only "strong" session key types from the KDC and assuming the application server will understand and support whatever type the KDC actually returns ๐งโโ๏ธ
Normative References ๐
[BCP26] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
[Bellare98] Bellare, M., Desai, A., Pointcheval, D., and P. Rogaway, "Relations Among Notions of Security for Public-Key Encryption Schemes". Extended abstract published in Advances in Cryptology-Crypto 98 Proceedings, Lecture Notes in Computer Science Vol. 1462, H. Krawcyzk ed., Springer-Verlag, 1998.
[Blumenthal96] Blumenthal, U. and S. Bellovin, "A Better Key Schedule for DES-Like Ciphers", Proceedings of PRAGOCRYPT '96, 1996.
[CRC] International Organization for Standardization, "ISO Information Processing Systems - Data Communication - High-Level Data Link Control Procedure - Frame Structure," IS 3309, 3rd Edition, October 1984.
[DES77] National Bureau of Standards, U.S. Department of Commerce, "Data Encryption Standard," Federal Information Processing Standards Publication 46, Washington, DC, 1977.
[DESI81] National Bureau of Standards, U.S. Department of Commerce, "Guidelines for implementing and using NBS Data Encryption Standard," Federal Information Processing Standards Publication 74, Washington, DC, 1981.
[DESM80] National Bureau of Standards, U.S. Department of Commerce, "DES Modes of Operation," Federal Information Processing Standards Publication 81, Springfield, VA, December 1980.
[Dolev91] Dolev, D., Dwork, C., and M. Naor, "Non-malleable cryptography", Proceedings of the 23rd Annual Symposium on Theory of Computing, ACM, 1991.
[HMAC] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, February 1997.
[KRB5-AES] Raeburn, K., "Advanced Encryption Standard (AES) Encryption for Kerberos 5", RFC 3962, February 2005.
[MD4-92] Rivest, R., "The MD4 Message-Digest Algorithm", RFC 1320, April 1992.
[MD5-92] Rivest, R., "The MD5 Message-Digest Algorithm ", RFC 1321, April 1992.
[SG92] Stubblebine, S. and V. D. Gligor, "On Message Integrity in Cryptographic Protocols," in Proceedings of the IEEE Symposium on Research in Security and Privacy, Oakland, California, May 1992.
Informative References ๐ท
[Bellovin91] Bellovin, S. M. and M. Merrit, "Limitations of the Kerberos Authentication System", in Proceedings of the Winter 1991 Usenix Security Conference, January, 1991.
[Bellovin99] Bellovin, S. M. and D. Atkins, private communications, 1999.
[EFF-DES] Electronic Frontier Foundation, "Cracking DES: Secrets of Encryption Research, Wiretap Politics, and Chip Design", O'Reilly & Associates, Inc., May 1998.
[ESP-DES] Madson, C. and N. Doraswamy, "The ESP DES-CBC Cipher Algorithm With Explicit IV", RFC 2405, November 1998.
[GSS-KRB5] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC 1964, June 1996.
[HMAC-TEST] Cheng, P. and R. Glenn, "Test Cases for HMAC-MD5 and HMAC-SHA-1", RFC 2202, September 1997.
[IPSEC-HMAC] Madson, C. and R. Glenn, "The Use of HMAC-SHA-1-96 within ESP and AH", RFC 2404, November 1998.
[Kerb] Neuman, C., Yu, T., Hartman, S., and K. Raeburn, "The Kerberos Network Authentication Service (V5)", Work in Progress, September 2004.
[Kerb1510] Kohl, J. and C. Neuman, "The Kerberos Network Authentication Service (V5)", RFC 1510, September 1993.
[RC5] Baldwin, R. and R. Rivest, "The RC5, RC5-CBC, RC5-CBC-Pad, and RC5-CTS Algorithms", RFC 2040, October 1996.
[RFC1851] Karn, P., Metzger, P., and W. Simpson, "The ESP Triple DES Transform", RFC 1851, September 1995.
[Schneier96] Schneier, B., "Applied Cryptography Second Edition", John Wiley & Sons, New York, NY, 1996. ISBN 0-471-12845-7.
Editor's Address ๐
Kenneth Raeburn Massachusetts Institute of Technology 77 Massachusetts Avenue Cambridge, MA 02139
EMail: raeburn@mit.edu
Full Copyright Statement ๐
Okay bestie, the legal bit ๐งพ. Copyright (C) The Internet Society (2005). ๐
This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights. โจ
This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ๐
Intellectual Property ๐ฆ
Okay so the IETF is not taking a side ๐ โโ๏ธ on whether any Intellectual Property Rights or other rights that might be claimed to apply to the implementation or use of the technology in this document are valid or in scope, or whether any license under those rights might be available. It also doesn't claim it has done any independent effort to find those rights. ๐ If you want the details on the IETF's procedures for rights in IETF Documents, check out BCP 78 and BCP 79. ๐
Copies of IPR disclosures made to the IETF Secretariat, and any assurances of licenses to be made available, can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr. ๐ The same goes for the result of an attempt to get a general license or permission to use those proprietary rights, made by implementers or users of this specification. ๐
The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. ๐ซถ Send that info to the IETF at ietf-ipr@ietf.org. ๐
Acknowledgement ๐ธ
Funding for the RFC Editor function is currently provided by the Internet Society. ๐ Thank you, Internet Society, you're literally keeping the lights on ๐งโจ
๐ฆ where this page comes from
- ietf: rfc3961 2005-02
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms