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 }