package pseudohsm import ( "fmt" "io/ioutil" "os" "path/filepath" "time" "github.com/pborman/uuid" "github.com/bytom/vapor/crypto/ed25519/chainkd" ) const ( version = 1 keytype = "bytom_kd" ) // XKey struct type for keystore file type XKey struct { ID uuid.UUID KeyType string Alias string XPrv chainkd.XPrv XPub chainkd.XPub } type keyStore interface { // Loads and decrypts the key from disk. GetKey(alias string, filename string, auth string) (*XKey, error) // Writes and encrypts the key. StoreKey(filename string, k *XKey, auth string) error // Joins filename with the key directory unless it is already absolute. JoinPath(filename string) string } type encryptedKeyJSON struct { Crypto cryptoJSON `json:"crypto"` ID string `json:"id"` Type string `json:"type"` Version int `json:"version"` Alias string `json:"alias"` XPub string `json:"xpub"` } type cryptoJSON struct { Cipher string `json:"cipher"` CipherText string `json:"ciphertext"` CipherParams cipherparamsJSON `json:"cipherparams"` KDF string `json:"kdf"` KDFParams map[string]interface{} `json:"kdfparams"` MAC string `json:"mac"` } type cipherparamsJSON struct { IV string `json:"iv"` } type scryptParamsJSON struct { N int `json:"n"` R int `json:"r"` P int `json:"p"` DkLen int `json:"dklen"` Salt string `json:"salt"` } func writeKeyFile(file string, content []byte) error { // Create the keystore directory with appropriate permissions // in case it is not present yet. const dirPerm = 0700 if err := os.MkdirAll(filepath.Dir(file), dirPerm); err != nil { return err } // Atomic write: create a temporary hidden file first // then move it into place. TempFile assigns mode 0600. f, err := ioutil.TempFile(filepath.Dir(file), "."+filepath.Base(file)+".tmp") if err != nil { return err } if _, err := f.Write(content); err != nil { f.Close() os.Remove(f.Name()) return err } f.Close() return os.Rename(f.Name(), file) } func zeroKey(k *XKey) { b := k.XPrv for i := range b { b[i] = 0 } } // keyFileName implements the naming convention for keyfiles: // UTC---
func keyFileName(keyId string) string { ts := time.Now().UTC() return fmt.Sprintf("UTC--%s--%s", toISO8601(ts), keyId) } func toISO8601(t time.Time) string { var tz string name, offset := t.Zone() if name == "UTC" { tz = "Z" } else { tz = fmt.Sprintf("%03d00", offset/3600) } 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) }