keyDerivation.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package rfc3961
  2. import (
  3. "bytes"
  4. "github.com/jcmturner/gokrb5/v8/crypto/etype"
  5. )
  6. const (
  7. prfconstant = "prf"
  8. )
  9. // DeriveRandom implements the RFC 3961 defined function: DR(Key, Constant) = k-truncate(E(Key, Constant, initial-cipher-state)).
  10. //
  11. // key: base key or protocol key. Likely to be a key from a keytab file.
  12. //
  13. // usage: a constant.
  14. //
  15. // n: block size in bits (not bytes) - note if you use something like aes.BlockSize this is in bytes.
  16. //
  17. // k: key length / key seed length in bits. Eg. for AES256 this value is 256.
  18. //
  19. // e: the encryption etype function to use.
  20. func DeriveRandom(key, usage []byte, e etype.EType) ([]byte, error) {
  21. n := e.GetCypherBlockBitLength()
  22. k := e.GetKeySeedBitLength()
  23. //Ensure the usage constant is at least the size of the cypher block size. Pass it through the nfold algorithm that will "stretch" it if needs be.
  24. nFoldUsage := Nfold(usage, n)
  25. //k-truncate implemented by creating a byte array the size of k (k is in bits hence /8)
  26. out := make([]byte, k/8)
  27. // Keep feeding the output back into the encryption function until it is no longer short than k.
  28. _, K, err := e.EncryptData(key, nFoldUsage)
  29. if err != nil {
  30. return out, err
  31. }
  32. for i := copy(out, K); i < len(out); {
  33. _, K, _ = e.EncryptData(key, K)
  34. i = i + copy(out[i:], K)
  35. }
  36. return out, nil
  37. }
  38. // DeriveKey derives a key from the protocol key based on the usage and the etype's specific methods.
  39. func DeriveKey(protocolKey, usage []byte, e etype.EType) ([]byte, error) {
  40. r, err := e.DeriveRandom(protocolKey, usage)
  41. if err != nil {
  42. return nil, err
  43. }
  44. return e.RandomToKey(r), nil
  45. }
  46. // RandomToKey returns a key from the bytes provided according to the definition in RFC 3961.
  47. func RandomToKey(b []byte) []byte {
  48. return b
  49. }
  50. // DES3RandomToKey returns a key from the bytes provided according to the definition in RFC 3961 for DES3 etypes.
  51. func DES3RandomToKey(b []byte) []byte {
  52. r := fixWeakKey(stretch56Bits(b[:7]))
  53. r2 := fixWeakKey(stretch56Bits(b[7:14]))
  54. r = append(r, r2...)
  55. r3 := fixWeakKey(stretch56Bits(b[14:21]))
  56. r = append(r, r3...)
  57. return r
  58. }
  59. // DES3StringToKey returns a key derived from the string provided according to the definition in RFC 3961 for DES3 etypes.
  60. func DES3StringToKey(secret, salt string, e etype.EType) ([]byte, error) {
  61. s := secret + salt
  62. tkey := e.RandomToKey(Nfold([]byte(s), e.GetKeySeedBitLength()))
  63. return e.DeriveKey(tkey, []byte("kerberos"))
  64. }
  65. // PseudoRandom function as defined in RFC 3961
  66. func PseudoRandom(key, b []byte, e etype.EType) ([]byte, error) {
  67. h := e.GetHashFunc()()
  68. h.Write(b)
  69. tmp := h.Sum(nil)[:e.GetMessageBlockByteSize()]
  70. k, err := e.DeriveKey(key, []byte(prfconstant))
  71. if err != nil {
  72. return []byte{}, err
  73. }
  74. _, prf, err := e.EncryptData(k, tmp)
  75. if err != nil {
  76. return []byte{}, err
  77. }
  78. return prf, nil
  79. }
  80. func stretch56Bits(b []byte) []byte {
  81. d := make([]byte, len(b), len(b))
  82. copy(d, b)
  83. var lb byte
  84. for i, v := range d {
  85. bv, nb := calcEvenParity(v)
  86. d[i] = nb
  87. if bv != 0 {
  88. lb = lb | (1 << uint(i+1))
  89. } else {
  90. lb = lb &^ (1 << uint(i+1))
  91. }
  92. }
  93. _, lb = calcEvenParity(lb)
  94. d = append(d, lb)
  95. return d
  96. }
  97. func calcEvenParity(b byte) (uint8, uint8) {
  98. lowestbit := b & 0x01
  99. // c counter of 1s in the first 7 bits of the byte
  100. var c int
  101. // Iterate over the highest 7 bits (hence p starts at 1 not zero) and count the 1s.
  102. for p := 1; p < 8; p++ {
  103. v := b & (1 << uint(p))
  104. if v != 0 {
  105. c++
  106. }
  107. }
  108. if c%2 == 0 {
  109. //Even number of 1s so set parity to 1
  110. b = b | 1
  111. } else {
  112. //Odd number of 1s so set parity to 0
  113. b = b &^ 1
  114. }
  115. return lowestbit, b
  116. }
  117. func fixWeakKey(b []byte) []byte {
  118. if weak(b) {
  119. b[7] ^= 0xF0
  120. }
  121. return b
  122. }
  123. func weak(b []byte) bool {
  124. // weak keys from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-67r1.pdf
  125. weakKeys := [4][]byte{
  126. {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
  127. {0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE},
  128. {0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1},
  129. {0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
  130. }
  131. semiWeakKeys := [12][]byte{
  132. {0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E},
  133. {0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01},
  134. {0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1},
  135. {0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01},
  136. {0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE},
  137. {0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01},
  138. {0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1},
  139. {0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E},
  140. {0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE},
  141. {0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E},
  142. {0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
  143. {0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1},
  144. }
  145. for _, k := range weakKeys {
  146. if bytes.Equal(b, k) {
  147. return true
  148. }
  149. }
  150. for _, k := range semiWeakKeys {
  151. if bytes.Equal(b, k) {
  152. return true
  153. }
  154. }
  155. return false
  156. }