func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) { authArray := []byte(auth) salt := randentropy.GetEntropyMixed(32) derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptr, scryptp, scryptdkLen) if err != nil { return err } keyBytes := key.PrivateKey toEncrypt := PKCS7Pad(keyBytes) AES256Block, err := aes.NewCipher(derivedKey) if err != nil { return err } gcm, err := cipher.NewGCM(AES256Block) if err != nil { return err } // XXX: a GCM nonce may only be used once per key ever! nonce := randentropy.GetEntropyMixed(gcm.NonceSize()) // (dst, nonce, plaintext, extradata) cipherText := gcm.Seal(nil, nonce, toEncrypt, nil) cipherStruct := cipherJSON{ salt, nonce, cipherText, } keyStruct := encryptedKeyJSON{ key.Id, key.Type.String(), strings.ToUpper(hex.EncodeToString(key.Address)), cipherStruct, } keyJSON, err := json.Marshal(keyStruct) if err != nil { return err } return WriteKeyFile(key.Address, ks.keysDirPath, keyJSON) }
func DecryptKey(ks keyStorePassphrase, keyAddr []byte, auth string) (*Key, error) { fileContent, err := GetKeyFile(ks.keysDirPath, keyAddr) if err != nil { return nil, err } keyProtected := new(encryptedKeyJSON) if err = json.Unmarshal(fileContent, keyProtected); err != nil { return nil, err } keyId := keyProtected.Id keyType, err := KeyTypeFromString(keyProtected.Type) if err != nil { return nil, err } keyAddr2, err := hex.DecodeString(keyProtected.Address) if bytes.Compare(keyAddr, keyAddr2) != 0 { return nil, fmt.Errorf("address of key and address in file do not match. Got %x, expected %x", keyAddr2, keyAddr) } salt := keyProtected.Crypto.Salt nonce := keyProtected.Crypto.Nonce cipherText := keyProtected.Crypto.CipherText authArray := []byte(auth) derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptr, scryptp, scryptdkLen) if err != nil { return nil, err } plainText, err := aesGCMDecrypt(derivedKey, cipherText, nonce) if err != nil { return nil, err } // no need to use a checksum as done by gcm return &Key{ Id: uuid.UUID(keyId), Type: keyType, Address: keyAddr, PrivateKey: plainText, }, nil }