goldwarden-vaultwarden-bitw.../agent/bitwarden/crypto/keyhierarchy.go

85 lines
2.4 KiB
Go

package crypto
import (
"crypto/sha256"
"fmt"
"io"
"github.com/awnumar/memguard"
"golang.org/x/crypto/hkdf"
)
func InitKeyringFromMasterPassword(keyring *Keyring, accountKey EncString, accountPrivateKey EncString, orgKeys map[string]string, password memguard.LockedBuffer, email string, kdfConfig KDFConfig) error {
masterKey, err := DeriveMasterKey(password, email, kdfConfig)
if err != nil {
return err
}
return InitKeyringFromMasterKey(keyring, accountKey, accountPrivateKey, orgKeys, masterKey)
}
func InitKeyringFromMasterKey(keyring *Keyring, accountKey EncString, accountPrivateKey EncString, orgKeys map[string]string, masterKey MasterKey) error {
var accountSymmetricKeyByteArray []byte
switch accountKey.Type {
case AesCbc256_HmacSha256_B64:
stretchedMasterKey, err := stretchKey(masterKey)
if err != nil {
return err
}
accountSymmetricKeyByteArray, err = DecryptWith(accountKey, stretchedMasterKey)
if err != nil {
return err
}
default:
return fmt.Errorf("unsupported account key type: %d", accountKey.Type)
}
accountSymmetricKey, err := SymmetricEncryptionKeyFromBytes(accountSymmetricKeyByteArray)
if err != nil {
return err
}
keyring.AccountKey = &accountSymmetricKey
pkcs8PrivateKey, err := DecryptWith(accountPrivateKey, accountSymmetricKey)
if err != nil {
return err
}
keyring.AsymmetricEncyryptionKey = AsymmetricEncryptionKey{memguard.NewEnclave(pkcs8PrivateKey)}
keyring.OrganizationKeys = orgKeys
return nil
}
func InitKeyringFromUserSymmetricKey(keyring *Keyring, accountSymmetricKey SymmetricEncryptionKey, accountPrivateKey EncString, orgKeys map[string]string) error {
keyring.AccountKey = &accountSymmetricKey
pkcs8PrivateKey, err := DecryptWith(accountPrivateKey, accountSymmetricKey)
if err != nil {
return err
}
keyring.AsymmetricEncyryptionKey = AsymmetricEncryptionKey{memguard.NewEnclave(pkcs8PrivateKey)}
keyring.OrganizationKeys = orgKeys
return nil
}
func stretchKey(masterKey MasterKey) (SymmetricEncryptionKey, error) {
key := make([]byte, 32)
macKey := make([]byte, 32)
buffer, err := masterKey.encKey.Open()
if err != nil {
return SymmetricEncryptionKey{}, err
}
var r io.Reader
r = hkdf.Expand(sha256.New, buffer.Data(), []byte("enc"))
r.Read(key)
r = hkdf.Expand(sha256.New, buffer.Data(), []byte("mac"))
r.Read(macKey)
return SymmetricEncryptionKey{memguard.NewEnclave(key), memguard.NewEnclave(macKey)}, nil
}