github.com/opentofu/opentofu@v1.7.1/internal/encryption/keyprovider/pbkdf2/provider.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 // Package pbkdf2 contains a key provider that takes a passphrase and emits a PBKDF2 hash of the configured length. 7 package pbkdf2 8 9 import ( 10 "fmt" 11 "io" 12 13 "github.com/opentofu/opentofu/internal/encryption/keyprovider" 14 15 goPBKDF2 "golang.org/x/crypto/pbkdf2" 16 ) 17 18 type pbkdf2KeyProvider struct { 19 Config 20 } 21 22 func (p pbkdf2KeyProvider) generateMetadata() (*Metadata, error) { 23 // Build outMeta based on current configuration 24 outMeta := &Metadata{ 25 Iterations: p.Iterations, 26 HashFunction: p.HashFunction, 27 Salt: make([]byte, p.SaltLength), 28 KeyLength: p.KeyLength, 29 } 30 // Generate new salt 31 if _, err := io.ReadFull(p.randomSource, outMeta.Salt); err != nil { 32 return nil, &keyprovider.ErrKeyProviderFailure{ 33 Message: fmt.Sprintf("failed to obtain %d bytes of random data", p.SaltLength), 34 Cause: err, 35 } 36 } 37 return outMeta, nil 38 } 39 40 func (p pbkdf2KeyProvider) Provide(rawMeta keyprovider.KeyMeta) (keyprovider.Output, keyprovider.KeyMeta, error) { 41 if rawMeta == nil { 42 return keyprovider.Output{}, nil, &keyprovider.ErrInvalidMetadata{Message: "bug: no metadata struct provided"} 43 } 44 inMeta, ok := rawMeta.(*Metadata) 45 if !ok { 46 return keyprovider.Output{}, nil, &keyprovider.ErrInvalidMetadata{ 47 Message: fmt.Sprintf("bug: incorrect metadata type of %T provided", rawMeta), 48 } 49 } 50 51 outMeta, err := p.generateMetadata() 52 if err != nil { 53 return keyprovider.Output{}, nil, err 54 } 55 56 var decryptionKey []byte 57 if inMeta.isPresent() { 58 if err := inMeta.validate(); err != nil { 59 return keyprovider.Output{}, nil, err 60 } 61 decryptionKey = goPBKDF2.Key( 62 []byte(p.Passphrase), 63 inMeta.Salt, 64 inMeta.Iterations, 65 inMeta.KeyLength, 66 inMeta.HashFunction.Function(), 67 ) 68 } 69 70 return keyprovider.Output{ 71 EncryptionKey: goPBKDF2.Key( 72 []byte(p.Passphrase), 73 outMeta.Salt, 74 outMeta.Iterations, 75 outMeta.KeyLength, 76 outMeta.HashFunction.Function(), 77 ), 78 DecryptionKey: decryptionKey, 79 }, outMeta, nil 80 }