common.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Package common provides encryption methods common across encryption types
  2. package common
  3. import (
  4. "bytes"
  5. "crypto/hmac"
  6. "encoding/binary"
  7. "encoding/hex"
  8. "errors"
  9. "fmt"
  10. "gopkg.in/jcmturner/gokrb5.v2/crypto/etype"
  11. )
  12. const (
  13. s2kParamsZero = 4294967296
  14. )
  15. // ZeroPad pads bytes with zeros to nearest multiple of message size m.
  16. func ZeroPad(b []byte, m int) ([]byte, error) {
  17. if m <= 0 {
  18. return nil, errors.New("Invalid message block size when padding")
  19. }
  20. if b == nil || len(b) == 0 {
  21. return nil, errors.New("Data not valid to pad: Zero size")
  22. }
  23. if l := len(b) % m; l != 0 {
  24. n := m - l
  25. z := make([]byte, n)
  26. b = append(b, z...)
  27. }
  28. return b, nil
  29. }
  30. // PKCS7Pad pads bytes according to RFC 2315 to nearest multiple of message size m.
  31. func PKCS7Pad(b []byte, m int) ([]byte, error) {
  32. if m <= 0 {
  33. return nil, errors.New("Invalid message block size when padding")
  34. }
  35. if b == nil || len(b) == 0 {
  36. return nil, errors.New("Data not valid to pad: Zero size")
  37. }
  38. n := m - (len(b) % m)
  39. pb := make([]byte, len(b)+n)
  40. copy(pb, b)
  41. copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
  42. return pb, nil
  43. }
  44. // PKCS7Unpad removes RFC 2315 padding from byes where message size is m.
  45. func PKCS7Unpad(b []byte, m int) ([]byte, error) {
  46. if m <= 0 {
  47. return nil, errors.New("Invalid message block size when unpadding")
  48. }
  49. if b == nil || len(b) == 0 {
  50. return nil, errors.New("Padded data not valid: Zero size")
  51. }
  52. if len(b)%m != 0 {
  53. return nil, errors.New("Padded data not valid: Not multiple of message block size")
  54. }
  55. c := b[len(b)-1]
  56. n := int(c)
  57. if n == 0 || n > len(b) {
  58. return nil, errors.New("Padded data not valid: Data may not have been padded")
  59. }
  60. for i := 0; i < n; i++ {
  61. if b[len(b)-n+i] != c {
  62. return nil, errors.New("Padded data not valid")
  63. }
  64. }
  65. return b[:len(b)-n], nil
  66. }
  67. // GetHash generates the keyed hash value according to the etype's hash function.
  68. func GetHash(pt, key []byte, usage []byte, etype etype.EType) ([]byte, error) {
  69. k, err := etype.DeriveKey(key, usage)
  70. if err != nil {
  71. return nil, fmt.Errorf("Unable to derive key for checksum: %v", err)
  72. }
  73. mac := hmac.New(etype.GetHashFunc(), k)
  74. p := make([]byte, len(pt))
  75. copy(p, pt)
  76. mac.Write(p)
  77. return mac.Sum(nil)[:etype.GetHMACBitLength()/8], nil
  78. }
  79. // GetChecksumHash returns a keyed checksum hash of the bytes provided.
  80. func GetChecksumHash(b, key []byte, usage uint32, etype etype.EType) ([]byte, error) {
  81. return GetHash(b, key, GetUsageKc(usage), etype)
  82. }
  83. // GetIntegrityHash returns a keyed integrity hash of the bytes provided.
  84. func GetIntegrityHash(b, key []byte, usage uint32, etype etype.EType) ([]byte, error) {
  85. return GetHash(b, key, GetUsageKi(usage), etype)
  86. }
  87. // VerifyChecksum compares the checksum of the msg bytes is the same as the checksum provided.
  88. func VerifyChecksum(key, chksum, msg []byte, usage uint32, etype etype.EType) bool {
  89. //The ciphertext output is the concatenation of the output of the basic
  90. //encryption function E and a (possibly truncated) HMAC using the
  91. //specified hash function H, both applied to the plaintext with a
  92. //random confounder prefix and sufficient padding to bring it to a
  93. //multiple of the message block size. When the HMAC is computed, the
  94. //key is used in the protocol key form.
  95. expectedMAC, _ := GetChecksumHash(msg, key, usage, etype)
  96. return hmac.Equal(chksum, expectedMAC)
  97. }
  98. // GetUsageKc returns the checksum key usage value for the usage number un.
  99. //
  100. // RFC 3961: 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.
  101. //
  102. // Kc = DK(base-key, usage | 0x99);
  103. func GetUsageKc(un uint32) []byte {
  104. return getUsage(un, 0x99)
  105. }
  106. // GetUsageKe returns the encryption key usage value for the usage number un
  107. //
  108. // RFC 3961: 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.
  109. //
  110. // Ke = DK(base-key, usage | 0xAA);
  111. func GetUsageKe(un uint32) []byte {
  112. return getUsage(un, 0xAA)
  113. }
  114. // GetUsageKi returns the integrity key usage value for the usage number un
  115. //
  116. // RFC 3961: 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.
  117. //
  118. // Ki = DK(base-key, usage | 0x55);
  119. func GetUsageKi(un uint32) []byte {
  120. return getUsage(un, 0x55)
  121. }
  122. func getUsage(un uint32, o byte) []byte {
  123. var buf bytes.Buffer
  124. binary.Write(&buf, binary.BigEndian, un)
  125. return append(buf.Bytes(), o)
  126. }
  127. // IterationsToS2Kparams converts the number of iterations as an integer to a string representation.
  128. func IterationsToS2Kparams(i int) string {
  129. b := make([]byte, 4, 4)
  130. binary.BigEndian.PutUint32(b, uint32(i))
  131. return hex.EncodeToString(b)
  132. }
  133. // S2KparamsToItertions converts the string representation of iterations to an integer
  134. func S2KparamsToItertions(s2kparams string) (int, error) {
  135. //process s2kparams string
  136. //The parameter string is four octets indicating an unsigned
  137. //number in big-endian order. This is the number of iterations to be
  138. //performed. If the value is 00 00 00 00, the number of iterations to
  139. //be performed is 4,294,967,296 (2**32).
  140. var i uint32
  141. if len(s2kparams) != 8 {
  142. return s2kParamsZero, errors.New("Invalid s2kparams length")
  143. }
  144. b, err := hex.DecodeString(s2kparams)
  145. if err != nil {
  146. return s2kParamsZero, errors.New("Invalid s2kparams, cannot decode string to bytes")
  147. }
  148. i = binary.BigEndian.Uint32(b)
  149. //buf := bytes.NewBuffer(b)
  150. //err = binary.Read(buf, binary.BigEndian, &i)
  151. if err != nil {
  152. return s2kParamsZero, errors.New("Invalid s2kparams, cannot convert to big endian int32")
  153. }
  154. return int(i), nil
  155. }