OSDN Git Service

Hulk did something
[bytom/vapor.git] / blockchain / pseudohsm / key.go
diff --git a/blockchain/pseudohsm/key.go b/blockchain/pseudohsm/key.go
new file mode 100644 (file)
index 0000000..bb94410
--- /dev/null
@@ -0,0 +1,112 @@
+package pseudohsm
+
+import (
+       "fmt"
+       "io/ioutil"
+       "os"
+       "path/filepath"
+       "time"
+
+       "github.com/pborman/uuid"
+       "github.com/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--<created_at UTC ISO8601>-<address hex>
+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)
+}