溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

比原怎么通過create-key接口創建密鑰

發布時間:2021-12-20 16:42:41 來源:億速云 閱讀:194 作者:iii 欄目:互聯網科技

這篇文章主要講解了“比原怎么通過create-key接口創建密鑰”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“比原怎么通過create-key接口創建密鑰”吧!

API.buildHandler方法中:

api/api.go#L164-L244

func (a *API) buildHandler() {
    // ...
    if a.wallet != nil {
        // ...
        m.Handle("/create-key", jsonHandler(a.pseudohsmCreateKey))
        // ...

可見,其路徑為/create-key,而相應的handler是a.pseudohsmCreateKey(外面套著的jsonHandler在之前已經討論過,這里不提):

api/hsm.go#L23-L32

func (a *API) pseudohsmCreateKey(ctx context.Context, in struct {
    Alias string `json:"alias"`
    Password string `json:"password"`
}) Response {
    xpub, err := a.wallet.Hsm.XCreate(in.Alias, in.Password)
    if err != nil {
        return NewErrorResponse(err)
    }
    return NewSuccessResponse(xpub)
}

它主要是調用了a.wallet.Hsm.XCreate,讓我們跟進去:

blockchain/pseudohsm/pseudohsm.go#L50-L66

// XCreate produces a new random xprv and stores it in the db.
func (h *HSM) XCreate(alias string, auth string) (*XPub, error) {
    // ...
    // 1.
    normalizedAlias := strings.ToLower(strings.TrimSpace(alias))
    // 2.
    if ok := h.cache.hasAlias(normalizedAlias); ok {
        return nil, ErrDuplicateKeyAlias
    }

    // 3.
    xpub, _, err := h.createChainKDKey(auth, normalizedAlias, false)
    if err != nil {
        return nil, err
    }
    // 4.
    h.cache.add(*xpub)
    return xpub, err
}

其中出現了HSM這個詞,它是指Hardware-Security-Module,原來比原還預留了跟硬件相關的模塊(暫不討論)。

上面的代碼分成了4部分,分別是:

  1. 首先對傳進來的alias參數進行標準化操作,即去兩邊空白,并且轉換成小寫

  2. 檢查cache中有沒有,有的話就直接返回并報個相應的錯,不會重復生成,因為私鑰和別名是一一對應的。在前端可以根據這個錯誤提醒用戶檢查或者換一個新的別名。

  3. 調用createChainKDKey生成相應的密鑰,并拿到返回的公鑰xpub

  4. 把公鑰放入cache中??雌饋砉€和別名并不是同一個東西,那前面為什么可以查詢alias呢?

所以我們進入h.cache.hasAlias看看:

blockchain/pseudohsm/keycache.go#L76-L84

func (kc *keyCache) hasAlias(alias string) bool {
    xpubs := kc.keys()
    for _, xpub := range xpubs {
        if xpub.Alias == alias {
            return true
        }
    }
    return false
}

通過xpub.Alias我們可以了解到,原來別名跟公鑰是綁定的,alias可以看作是公鑰的一個屬性(當然也屬于相應的私鑰)。所以前面把公鑰放進cache,之后就可以查詢別名了。

那么第3步中的createChainKDKey又是如何生成密鑰的呢?

blockchain/pseudohsm/pseudohsm.go#L68-L86

func (h *HSM) createChainKDKey(auth string, alias string, get bool) (*XPub, bool, error) {
    // 1.
    xprv, xpub, err := chainkd.NewXKeys(nil)
    if err != nil {
        return nil, false, err
    }
    // 2.
    id := uuid.NewRandom()
    key := &XKey{
        ID: id,
        KeyType: "bytom_kd",
        XPub: xpub,
        XPrv: xprv,
        Alias: alias,
    }
    // 3.
    file := h.keyStore.JoinPath(keyFileName(key.ID.String()))
    if err := h.keyStore.StoreKey(file, key, auth); err != nil {
        return nil, false, errors.Wrap(err, "storing keys")
    }
    // 4.
    return &XPub{XPub: xpub, Alias: alias, File: file}, true, nil
}

這塊代碼內容比較清晰,我們可以把它分成4步,分別是:

  1. 調用chainkd.NewXKeys生成密鑰。其中chainkd對應的是比原代碼庫中的另一個包"crypto/ed25519/chainkd",從名稱上來看,使用的是ed25519算法。如果對前面文章“如何連上一個比原節點”還有印象的話,會記得比原在有新節點連上的時候,就會使用該算法生成一對密鑰,用于當次連接進行加密通信。不過需要注意的是,雖然兩者都是ed25519算法,但是上次使用的代碼卻是來自第三方庫"github.com/tendermint/go-crypto"的。它跟這次的算法在細節上究竟有哪些不同,目前還不清楚,留待以后合適的機會研究。然后是傳入chainkd.NewXKeys(nil)的參數nil,對應的是“隨機數生成器”。如果傳的是nil,NewXKeys就會在內部使用默認的隨機數生成器生成隨機數并生成密鑰。關于密鑰算法相關的內容,在本文中并不探討。

  2. 給當前密鑰生成一個唯一的id,在后面用于生成文件名,保存在硬盤上。id使用的是uuid,生成的是一個形如62bc9340-f6a7-4d16-86f0-4be61920a06e這樣的全球唯一的隨機數

  3. 把密鑰以文件形式保存在硬盤上。這塊內容比較多,下面詳細講。

  4. 把公鑰相關信息組合在一起,供調用者使用。

我們再詳細講一下第3步,把密鑰保存成文件。首先是生成文件名,keyFileName函數對應的代碼如下:

blockchain/pseudohsm/key.go#L96-L101

// keyFileName implements the naming convention for keyfiles:
// UTC--<created_at UTC ISO8601>-<address hex>
func keyFileName(keyAlias string) string {
    ts := time.Now().UTC()
    return fmt.Sprintf("UTC--%s--%s", toISO8601(ts), keyAlias)
}

注意這里的參數keyAlias實際上應該是keyID,就是前面生成的uuid。寫成alias有點誤導,已經提交PR#922。最后生成的文件名,形如:UTC--2018-05-07T06-20-46.270917000Z--62bc9340-f6a7-4d16-86f0-4be61920a06e

生成文件名之后,會通過h.keyStore.JoinPath把它放在合適的目錄下。通常來說,這個目錄是本機數據目錄下的keystore,如果你是OSX系統,它應該在你的~/Library/Bytom/keystore,如果是別的,你可以通過下面的代碼來確定DefaultDataDir()

關于上面的保存密鑰文件的目錄,到底是怎么確定的,在代碼中其實是有點繞的。不過如果你對這感興趣的話,我相信你應該能自行找到,這里就不列出來了。如果找不到的話,可以試試以下關鍵字:pseudohsm.New(config.KeysDir()), os.ExpandEnv(config.DefaultDataDir()), DefaultDataDir(),DefaultBaseConfig()

在第3步的最后,會調用keyStore.StoreKey方法,把它保存成文件。該方法代碼如下:

blockchain/pseudohsm/keystore_passphrase.go#L67-L73

func (ks keyStorePassphrase) StoreKey(filename string, key *XKey, auth string) error {
    keyjson, err := EncryptKey(key, auth, ks.scryptN, ks.scryptP)
    if err != nil {
        return err
    }
    return writeKeyFile(filename, keyjson)
}

EncryptKey里做了很多事情,把傳進來的密鑰及其它信息利用起來生成了JSON格式的信息,然后通過writeKeyFile把它保存硬盤上。所以在你的keystore目錄下,會看到屬于你的密鑰文件。它們很重要,千萬別誤刪了。

a.wallet.Hsm.XCreate看完了,讓我們回到a.pseudohsmCreateKey方法的最后一部分??梢钥吹?,當成功生成key之后,會返回一個NewSuccessResponse(xpub),把與公鑰相關的信息返回給前端。它會被jsonHandler自動轉換成JSON格式,通過http返回過去。

感謝各位的閱讀,以上就是“比原怎么通過create-key接口創建密鑰”的內容了,經過本文的學習后,相信大家對比原怎么通過create-key接口創建密鑰這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女