いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-52 (bcryptパッケージを使ってパスワードをハッシュ化)

概要

小ネタ。忘れない内にメモメモ。

パスワードのハッシュ化でおなじみのbcryptさん、いろんな言語にライブラリとして存在しますが

もちろんGoにも存在します。

pkg.go.dev

これを使って、入力したパスワードをハッシュ化してみます。

ついでに、パスワード入力でおなじみのローカルエコー無しにしたいのでterminalパッケージも利用します。

pkg.go.dev

サンプル

以下のパッケージをgo get しておきます。

$ go get golang.org/x/crypto
package crypto

import (
    "github.com/devlights/try-golang/lib/output"
    "golang.org/x/crypto/bcrypt"
    "golang.org/x/crypto/ssh/terminal"
    "syscall"
)

// BcryptPasswordHash は、 bcrypt パッケージを利用してパスワードのハッシュ化をしてみるサンプルです.
// パスワードの読み取りには、 terminal パッケージの ReadPassword() を利用しています.
//
// REFERENCES::
//   - https://medium.com/@jcox250/password-hash-salt-using-golang-b041dc94cb72
//   - https://pkg.go.dev/golang.org/x/crypto/bcrypt?tab=doc
//   - https://pkg.go.dev/golang.org/x/crypto/ssh/terminal?tab=doc
//   - https://ja.wikipedia.org/wiki/Bcrypt
//   - https://liginc.co.jp/377191
//   - https://stackoverflow.com/questions/30363790/silence-user-input-in-scan-function
func BcryptPasswordHash() error {

    // パスワード読み取り
    password, err := readPassword()
    if err != nil {
        return err
    }

    // bcrypt で ハッシュ化
    hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
    if err != nil {
        return err
    }

    // ハッシュ化したものを文字列で表示
    output.Stdoutl("Hashed Password: ", string(hashedPassword))

    // 再度パスワード読み取り
    password2, err := readPassword()
    if err != nil {
        return err
    }

    // 一致するかを bcrypt パッケージの関数で確認
    err = bcrypt.CompareHashAndPassword(hashedPassword, password2)
    if err != nil {
        output.Stdoutl("CompareHashAndPassword", "一致しませんでした")
    } else {
        output.Stdoutl("CompareHashAndPassword", "一致しました")
    }

    return nil
}

func readPassword() ([]byte, error) {

    output.Stdoutf("ENTER Password: ", "")

    password, err := terminal.ReadPassword(int(syscall.Stdin))
    if err != nil {
        return nil, err
    }
    output.Stdoutl("", "")

    return password, nil
}

try-golang/bcrypt_password_hash.go at master · devlights/try-golang · GitHub

実行すると以下のようになります。

$ make run
go clean github.com/devlights/try-golang/cmd/trygolang
rm -f ./trygolang
go generate -x ./...
genny -in=generic_queue.go -out=builtins_queue.go gen T=BUILTINS
genny -in=generic_stack.go -out=builtins_stack.go gen T=BUILTINS
go run github.com/devlights/try-golang/cmd/trygolang -onetime -example ""

ENTER EXAMPLE NAME: crypto_bcrypt_password_hash
[Name] "crypto_bcrypt_password_hash"
ENTER Password: 

ここでパスワードを一度入力。terminal.ReadPassword() を使っているのでローカルエコーはされません。

パスワードを入れると、ハッシュ化された値がでます。

Hashed Password:     $2a$10$tm6tuNhCJLckSxQOiaXD.u1GIz4m0hET/ztNCF2Kao.sKqYeUJ8J6
ENTER Password:

$2a$って先頭についているのがbcryptハッシュを表していますね。

2回めのパスワード入力がでます。同じパスワードを入れると

CompareHashAndPassword 一致しました

って表示されます。


過去の記事については、以下のページからご参照下さい。

  • いろいろ備忘録日記まとめ

devlights.github.io

サンプルコードは、以下の場所で公開しています。

  • いろいろ備忘録日記サンプルソース置き場

github.com

github.com

github.com