scram_formatter.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package sarama
  2. import (
  3. "crypto/hmac"
  4. "crypto/sha256"
  5. "crypto/sha512"
  6. "hash"
  7. )
  8. // ScramFormatter implementation
  9. // @see: https://github.com/apache/kafka/blob/99b9b3e84f4e98c3f07714e1de6a139a004cbc5b/clients/src/main/java/org/apache/kafka/common/security/scram/internals/ScramFormatter.java#L93
  10. type scramFormatter struct {
  11. mechanism ScramMechanismType
  12. }
  13. func (s scramFormatter) mac(key []byte) (hash.Hash, error) {
  14. var m hash.Hash
  15. switch s.mechanism {
  16. case SCRAM_MECHANISM_SHA_256:
  17. m = hmac.New(sha256.New, key)
  18. case SCRAM_MECHANISM_SHA_512:
  19. m = hmac.New(sha512.New, key)
  20. default:
  21. return nil, ErrUnknownScramMechanism
  22. }
  23. return m, nil
  24. }
  25. func (s scramFormatter) hmac(key []byte, extra []byte) ([]byte, error) {
  26. mac, err := s.mac(key)
  27. if err != nil {
  28. return nil, err
  29. }
  30. if _, err := mac.Write(extra); err != nil {
  31. return nil, err
  32. }
  33. return mac.Sum(nil), nil
  34. }
  35. func (s scramFormatter) xor(result []byte, second []byte) {
  36. for i := 0; i < len(result); i++ {
  37. result[i] = result[i] ^ second[i]
  38. }
  39. }
  40. func (s scramFormatter) saltedPassword(password []byte, salt []byte, iterations int) ([]byte, error) {
  41. mac, err := s.mac(password)
  42. if err != nil {
  43. return nil, err
  44. }
  45. if _, err := mac.Write(salt); err != nil {
  46. return nil, err
  47. }
  48. if _, err := mac.Write([]byte{0, 0, 0, 1}); err != nil {
  49. return nil, err
  50. }
  51. u1 := mac.Sum(nil)
  52. prev := u1
  53. result := u1
  54. for i := 2; i <= iterations; i++ {
  55. ui, err := s.hmac(password, prev)
  56. if err != nil {
  57. return nil, err
  58. }
  59. s.xor(result, ui)
  60. prev = ui
  61. }
  62. return result, nil
  63. }