😸
Goでのハッシュ値生成
はじめに
現在携わっているプロジェクトで、特定の文字列をハッシュ化する機会がありました。
実際やったものも含め、どんな実装ができるのか改めて調べてみました!
SHA-1
-
Secure Hash Algorithm 1
の略 - 20バイトのハッシュ値を生成する
- 脆弱性が発見されているため仕様の廃止が検討されている
SHA-2
- SHA-1のアップデート版
-
SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256
の全部で6種類がある - SHA-2の改良版であるSHA-3も存在するが、SHA-2でも安全性が確保されているという
実装
今回は、SHA-1、SHA-224、SHA-256、SHA-384、SHA-512
の実装を見ていきます。
package main
import (
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"fmt"
)
func main() {
msg := "Hello, World!"
// sha1
hash1 := sha1.Sum([]byte(msg))
fmt.Println("hash1:",hash1)
// 出力結果
// バイトスライス化し、その結果をバイト配列で返している
// hash1: [10 10 159 42 103 114 148 37 87 171 83 85 215 106 244 66 248 246 94 1]
str1 := hex.EncodeToString(hash1[:])
fmt.Println("str1:",str1)
// 出力結果
// スライスをhex.EncodeToString関数で16進数の文字列に変換
// str1: 0a0a9f2a6772942557ab5355d76af442f8f65e01
sum1 := sha1.Sum([]byte(msg))
fmt.Printf("sum1: %x\n", sum1)
// 出力結果
// 書式指定子%xを使うことで、hex/encodingを使わなくても文字列に変換される
// sum1: 0a0a9f2a6772942557ab5355d76af442f8f65e01
// sha224
hash224 := sha256.Sum224([]byte(msg))
fmt.Println("hash224:",hash224)
// 出力結果
// hash224: [114 162 61 250 65 27 166 253 224 29 191 171 243 176 10 112 156 147 235 242 115 220 41 226 216 178 97 255]
str224 := hex.EncodeToString(hash224[:])
fmt.Println("str224:",str224)
// 出力結果
// str224: 72a23dfa411ba6fde01dbfabf3b00a709c93ebf273dc29e2d8b261ff
sum224 := sha256.Sum224([]byte(msg))
fmt.Printf("sum224: %x\n", sum224)
// 出力結果
// sum224: 72a23dfa411ba6fde01dbfabf3b00a709c93ebf273dc29e2d8b261ff
// sha256
hash256 := sha256.Sum256([]byte(msg))
fmt.Println("hash256:",hash256)
// 出力結果
// hash256: [223 253 96 33 187 43 213 176 175 103 98 144 128 158 195 165 49 145 221 129 199 247 10 75 40 104 138 54 33 130 152 111]
str256 := hex.EncodeToString(hash256[:])
fmt.Println("str256:",str256)
// 出力結果
// str256: dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f
sum256 := sha256.Sum256([]byte(msg))
fmt.Printf("sum256: %x\n", sum256)
// 出力結果
// sum256: dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f
// sha384
hash384 := sha512.Sum384([]byte(msg))
fmt.Println("hash384:",hash384)
// 出力結果
// hash384: [84 133 204 155 51 101 180 48 93 251 78 131 55 224 165 152 165 116 248 36 43 241 114 137 224 221 108 32 163 205 68 160 137 222 22 171 74 179 8 246 62 68 177 23 14 181 245 21]
str384 := hex.EncodeToString(hash384[:])
fmt.Println("str384:",str384)
// 出力結果
// str384: 5485cc9b3365b4305dfb4e8337e0a598a574f8242bf17289e0dd6c20a3cd44a089de16ab4ab308f63e44b1170eb5f515
sum384 := sha512.Sum384([]byte(msg))
fmt.Printf("sum384: %x\n", sum384)
// 出力結果
// sum384: 5485cc9b3365b4305dfb4e8337e0a598a574f8242bf17289e0dd6c20a3cd44a089de16ab4ab308f63e44b1170eb5f515
// sha512
hash512 := sha512.Sum512([]byte(msg))
fmt.Println("hash512:",hash512)
// 出力結果
// hash512: [55 77 121 74 149 205 207 216 179 89 147 24 95 239 155 163 104 241 96 216 218 244 50 208 139 169 241 237 30 90 190 108 198 146 145 224 250 47 224 0 106 82 87 14 241 140 25 222 244 230 23 195 60 229 46 240 166 229 251 227 24 203 3 135]
str512 := hex.EncodeToString(hash512[:])
fmt.Println("str512:",str512)
// 出力結果
// str512: 374d794a95cdcfd8b35993185fef9ba368f160d8daf432d08ba9f1ed1e5abe6cc69291e0fa2fe0006a52570ef18c19def4e617c33ce52ef0a6e5fbe318cb0387
sum512 := sha512.Sum512([]byte(msg))
fmt.Printf("sum512: %x\n", sum512)
// 出力結果
// sum512: 374d794a95cdcfd8b35993185fef9ba368f160d8daf432d08ba9f1ed1e5abe6cc69291e0fa2fe0006a52570ef18c19def4e617c33ce52ef0a6e5fbe318cb0387
}
まとめ
SHA-1が20バイトのハッシュ値を生成するのに対し、SHA-512では64バイトのハッシュ値を生成するので、長さが圧倒的に異なることがわかりました。
また、文字列生成の方法として、
-
hex.EncodeToString
を使う - 書式指定子である
%x
を使う
これらが存在し、どっちも同じことを示しているということもわかりました。
今回は見ていませんが、SHA-512/224やSHA-512/256の実装も改めて見てみたいと思います!
Discussion