github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/blockchain/pseudohsm/key.go (about)

     1  package pseudohsm
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"time"
     9  
    10  	"github.com/bytom/bytom/crypto/ed25519/chainkd"
    11  	"github.com/pborman/uuid"
    12  )
    13  
    14  const (
    15  	version = 1
    16  	keytype = "bytom_kd"
    17  )
    18  
    19  // XKey struct type for keystore file
    20  type XKey struct {
    21  	ID      uuid.UUID
    22  	KeyType string
    23  	Alias   string
    24  	XPrv    chainkd.XPrv
    25  	XPub    chainkd.XPub
    26  }
    27  
    28  type keyStore interface {
    29  	// Loads and decrypts the key from disk.
    30  	GetKey(alias string, filename string, auth string) (*XKey, error)
    31  	// Writes and encrypts the key.
    32  	StoreKey(filename string, k *XKey, auth string) error
    33  	// Joins filename with the key directory unless it is already absolute.
    34  	JoinPath(filename string) string
    35  }
    36  
    37  type encryptedKeyJSON struct {
    38  	Crypto  cryptoJSON `json:"crypto"`
    39  	ID      string     `json:"id"`
    40  	Type    string     `json:"type"`
    41  	Version int        `json:"version"`
    42  	Alias   string     `json:"alias"`
    43  	XPub    string     `json:"xpub"`
    44  }
    45  
    46  type cryptoJSON struct {
    47  	Cipher       string                 `json:"cipher"`
    48  	CipherText   string                 `json:"ciphertext"`
    49  	CipherParams cipherparamsJSON       `json:"cipherparams"`
    50  	KDF          string                 `json:"kdf"`
    51  	KDFParams    map[string]interface{} `json:"kdfparams"`
    52  	MAC          string                 `json:"mac"`
    53  }
    54  
    55  type cipherparamsJSON struct {
    56  	IV string `json:"iv"`
    57  }
    58  
    59  type scryptParamsJSON struct {
    60  	N     int    `json:"n"`
    61  	R     int    `json:"r"`
    62  	P     int    `json:"p"`
    63  	DkLen int    `json:"dklen"`
    64  	Salt  string `json:"salt"`
    65  }
    66  
    67  func writeKeyFile(file string, content []byte) error {
    68  	// Create the keystore directory with appropriate permissions
    69  	// in case it is not present yet.
    70  	const dirPerm = 0700
    71  	if err := os.MkdirAll(filepath.Dir(file), dirPerm); err != nil {
    72  		return err
    73  	}
    74  	// Atomic write: create a temporary hidden file first
    75  	// then move it into place. TempFile assigns mode 0600.
    76  	f, err := ioutil.TempFile(filepath.Dir(file), "."+filepath.Base(file)+".tmp")
    77  	if err != nil {
    78  		return err
    79  	}
    80  	if _, err := f.Write(content); err != nil {
    81  		f.Close()
    82  		os.Remove(f.Name())
    83  		return err
    84  	}
    85  	f.Close()
    86  	return os.Rename(f.Name(), file)
    87  }
    88  
    89  func zeroKey(k *XKey) {
    90  	b := k.XPrv
    91  	for i := range b {
    92  		b[i] = 0
    93  	}
    94  }
    95  
    96  // keyFileName implements the naming convention for keyfiles:
    97  // UTC--<created_at UTC ISO8601>-<address hex>
    98  func keyFileName(keyId string) string {
    99  	ts := time.Now().UTC()
   100  	return fmt.Sprintf("UTC--%s--%s", toISO8601(ts), keyId)
   101  }
   102  
   103  func toISO8601(t time.Time) string {
   104  	var tz string
   105  	name, offset := t.Zone()
   106  	if name == "UTC" {
   107  		tz = "Z"
   108  	} else {
   109  		tz = fmt.Sprintf("%03d00", offset/3600)
   110  	}
   111  	return fmt.Sprintf("%04d-%02d-%02dT%02d-%02d-%02d.%09d%s", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), tz)
   112  }