local.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package kms
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "encoding/hex"
  6. "io"
  7. "github.com/minio/sha256-simd"
  8. "gocloud.dev/secrets/localsecrets"
  9. "golang.org/x/crypto/hkdf"
  10. )
  11. type localSecret struct {
  12. baseSecret
  13. masterKey string
  14. }
  15. func newLocalSecret(base baseSecret, masterKey string) SecretProvider {
  16. return &localSecret{
  17. baseSecret: base,
  18. masterKey: masterKey,
  19. }
  20. }
  21. func (s *localSecret) Name() string {
  22. return localProviderName
  23. }
  24. func (s *localSecret) IsEncrypted() bool {
  25. return s.Status == SecretStatusSecretBox
  26. }
  27. func (s *localSecret) Encrypt() error {
  28. if s.Status != SecretStatusPlain {
  29. return errWrongSecretStatus
  30. }
  31. if s.Payload == "" {
  32. return errInvalidSecret
  33. }
  34. secretKey, err := localsecrets.NewRandomKey()
  35. if err != nil {
  36. return err
  37. }
  38. key, err := s.deriveKey(secretKey[:], false)
  39. if err != nil {
  40. return err
  41. }
  42. keeper := localsecrets.NewKeeper(key)
  43. defer keeper.Close()
  44. ciphertext, err := keeper.Encrypt(context.Background(), []byte(s.Payload))
  45. if err != nil {
  46. return err
  47. }
  48. s.Key = hex.EncodeToString(secretKey[:])
  49. s.Payload = base64.StdEncoding.EncodeToString(ciphertext)
  50. s.Status = SecretStatusSecretBox
  51. s.Mode = s.getEncryptionMode()
  52. return nil
  53. }
  54. func (s *localSecret) Decrypt() error {
  55. if !s.IsEncrypted() {
  56. return errWrongSecretStatus
  57. }
  58. encrypted, err := base64.StdEncoding.DecodeString(s.Payload)
  59. if err != nil {
  60. return err
  61. }
  62. secretKey, err := hex.DecodeString(s.Key)
  63. if err != nil {
  64. return err
  65. }
  66. key, err := s.deriveKey(secretKey[:], true)
  67. if err != nil {
  68. return err
  69. }
  70. keeper := localsecrets.NewKeeper(key)
  71. defer keeper.Close()
  72. plaintext, err := keeper.Decrypt(context.Background(), encrypted)
  73. if err != nil {
  74. return err
  75. }
  76. s.Status = SecretStatusPlain
  77. s.Payload = string(plaintext)
  78. s.Key = ""
  79. s.AdditionalData = ""
  80. s.Mode = 0
  81. return nil
  82. }
  83. func (s *localSecret) deriveKey(key []byte, isForDecryption bool) ([32]byte, error) {
  84. var masterKey []byte
  85. if s.masterKey == "" || (isForDecryption && s.Mode == 0) {
  86. var combined []byte
  87. combined = append(combined, key...)
  88. if s.AdditionalData != "" {
  89. combined = append(combined, []byte(s.AdditionalData)...)
  90. }
  91. combined = append(combined, key...)
  92. hash := sha256.Sum256(combined)
  93. masterKey = hash[:]
  94. } else {
  95. masterKey = []byte(s.masterKey)
  96. }
  97. var derivedKey [32]byte
  98. var info []byte
  99. if s.AdditionalData != "" {
  100. info = []byte(s.AdditionalData)
  101. }
  102. kdf := hkdf.New(sha256.New, masterKey, key, info)
  103. if _, err := io.ReadFull(kdf, derivedKey[:]); err != nil {
  104. return derivedKey, err
  105. }
  106. return derivedKey, nil
  107. }
  108. func (s *localSecret) getEncryptionMode() int {
  109. if s.masterKey == "" {
  110. return 0
  111. }
  112. return 1
  113. }