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 []byte, 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, keyring.IsMemguard) 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) } var accountSymmetricKey SymmetricEncryptionKey var err error if keyring.IsMemguard { accountSymmetricKey, err = MemguardSymmetricEncryptionKeyFromBytes(accountSymmetricKeyByteArray) } else { accountSymmetricKey, err = MemorySymmetricEncryptionKeyFromBytes(accountSymmetricKeyByteArray) } if err != nil { return err } keyring.UnlockWithAccountKey(accountSymmetricKey) keyringLog.Info("Decrypting account private key") pkcs8PrivateKey, err := DecryptWith(accountPrivateKey, accountSymmetricKey) if err != nil { return err } if keyring.IsMemguard { keyring.AsymmetricEncyryptionKey = MemguardAsymmetricEncryptionKey{memguard.NewEnclave(pkcs8PrivateKey)} } else { keyring.AsymmetricEncyryptionKey = MemoryAsymmetricEncryptionKey{pkcs8PrivateKey} } keyring.OrganizationKeys = orgKeys return nil } func InitKeyringFromUserSymmetricKey(keyring *Keyring, accountSymmetricKey SymmetricEncryptionKey, accountPrivateKey EncString, orgKeys map[string]string) error { keyring.UnlockWithAccountKey(accountSymmetricKey) keyringLog.Info("Decrypting account private key") pkcs8PrivateKey, err := DecryptWith(accountPrivateKey, accountSymmetricKey) if err != nil { return err } if keyring.IsMemguard { keyring.AsymmetricEncyryptionKey = MemguardAsymmetricEncryptionKey{memguard.NewEnclave(pkcs8PrivateKey)} } else { keyring.AsymmetricEncyryptionKey = MemoryAsymmetricEncryptionKey{pkcs8PrivateKey} } keyring.OrganizationKeys = orgKeys return nil } func stretchKey(masterKey MasterKey, useMemguard bool) (SymmetricEncryptionKey, error) { key := make([]byte, 32) macKey := make([]byte, 32) buffer, err := masterKey.encKey.Open() if err != nil { return MemorySymmetricEncryptionKey{}, err } var r io.Reader r = hkdf.Expand(sha256.New, buffer.Data(), []byte("enc")) _, err = r.Read(key) if err != nil { return nil, err } r = hkdf.Expand(sha256.New, buffer.Data(), []byte("mac")) _, err = r.Read(macKey) if err != nil { return nil, err } if useMemguard { return MemguardSymmetricEncryptionKey{memguard.NewEnclave(key), memguard.NewEnclave(macKey)}, nil } else { return MemorySymmetricEncryptionKey{encKey: key, macKey: macKey}, nil } }