github.com/elastos/Elastos.ELA.SideChain.ETH@v0.2.2/chainbridge-core/keystore/decrypt.go (about)

     1  // Copyright 2020 ChainSafe Systems
     2  // SPDX-License-Identifier: LGPL-3.0-only
     3  
     4  package keystore
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"path/filepath"
    11  
    12  	"github.com/elastos/Elastos.ELA.SideChain.ESC/accounts/keystore"
    13  	"github.com/elastos/Elastos.ELA.SideChain.ESC/chainbridge-core/crypto"
    14  	"github.com/elastos/Elastos.ELA.SideChain.ESC/chainbridge-core/crypto/secp256k1"
    15  )
    16  
    17  // Decrypt uses AES to decrypt ciphertext with the symmetric key deterministically created from `password`
    18  func Decrypt(data, password []byte) ([]byte, error) {
    19  	gcm, err := gcmFromPassphrase(password)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	nonceSize := gcm.NonceSize()
    25  	nonce, ciphertext := data[:nonceSize], data[nonceSize:]
    26  	plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
    27  	if err != nil {
    28  		if err.Error() == "cipher: message authentication failed" {
    29  			err = errors.New(err.Error() + ". Incorrect Password.")
    30  		}
    31  		return nil, err
    32  	}
    33  
    34  	return plaintext, nil
    35  }
    36  
    37  // DecodeKeypair turns input bytes into a keypair based on the specified key type
    38  func DecodeKeypair(in []byte, keytype crypto.KeyType) (kp crypto.Keypair, err error) {
    39  	if keytype == crypto.Secp256k1Type {
    40  		kp = &secp256k1.Keypair{}
    41  		err = kp.Decode(in)
    42  	} else {
    43  		return nil, errors.New("cannot decode key: invalid key type")
    44  	}
    45  
    46  	return kp, err
    47  }
    48  
    49  // DecryptPrivateKey uses AES to decrypt the ciphertext into a `crypto.PrivateKey` with a symmetric key deterministically
    50  // created from `password`
    51  func DecryptKeypair(expectedPubK string, data, password []byte, keytype string) (crypto.Keypair, error) {
    52  	pk, err := Decrypt(data, password)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	kp, err := DecodeKeypair(pk, keytype)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	// Check that the decoding matches what was expected
    62  	if kp.PublicKey() != expectedPubK {
    63  		return nil, fmt.Errorf("unexpected key file data, file may be corrupt or have been tampered with")
    64  	}
    65  	return kp, nil
    66  }
    67  
    68  // ReadFromFileAndDecrypt reads ciphertext from a file and decrypts it using the password into a `crypto.PrivateKey`
    69  func ReadFromFileAndDecrypt(filename string, password []byte, keytype string) (crypto.Keypair, error) {
    70  	fp, err := filepath.Abs(filename)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	data, err := ioutil.ReadFile(filepath.Clean(fp))
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	key, err := keystore.DecryptKey(data, string(password))
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	_ = key
    84  	return secp256k1.NewKeypair(*key.PrivateKey), nil
    85  }