概要
pysha2 という pure Python な SHA-2 ライブラリがあるのだが、これが Python 2 用だったので、Python 3 で動くようにして、Github 上で公開した。
SHA256 のコアな処理
分かりづらい命名だが、SHA256 は SHA2 の一部の規格である。
上記のコードのうち、SHA256 の核心的な部分を記す。
def _rotr(self, x, y):
return ((x >> y) | (x << (32-y))) & 0xFFFFFFFF
def _sha256_process(self, c):
w = [0]*64
w[0:16] = struct.unpack('!16L', c)
for i in range(16, 64):
s0 = self._rotr(w[i-15], 7) ^ self._rotr(w[i-15], 18) ^ (w[i-15] >> 3)
s1 = self._rotr(w[i-2], 17) ^ self._rotr(w[i-2], 19) ^ (w[i-2] >> 10)
w[i] = (w[i-16] + s0 + w[i-7] + s1) & 0xFFFFFFFF
a,b,c,d,e,f,g,h = self._h
for i in range(64):
s0 = self._rotr(a, 2) ^ self._rotr(a, 13) ^ self._rotr(a, 22)
maj = (a & b) ^ (a & c) ^ (b & c)
t2 = s0 + maj
s1 = self._rotr(e, 6) ^ self._rotr(e, 11) ^ self._rotr(e, 25)
ch = (e & f) ^ ((~e) & g)
t1 = h + s1 + ch + self._k[i] + w[i]
h = g
g = f
f = e
e = (d + t1) & 0xFFFFFFFF
d = c
c = b
b = a
a = (t1 + t2) & 0xFFFFFFFF
self._h = [(x+y) & 0xFFFFFFFF for x,y in zip(self._h, [a,b,c,d,e,f,g,h])]
self._k
は64個の4バイトの数字の定数表。
self._h
は8個の4バイトの数字が格納されるワーキングエリアで、ある定数の初期値が設定されている。
要するに、ローテート・シフト・AND・XOR・NOT等の典型的な論理演算を、最初から設定されている定数とダイジェストしたいメッセージに対して行って、self._h
という32バイトのワーキングエリアを更新していき、最後に self._h
をハッシュ値として出力している。SHA256 の名前のとおり、このハッシュ値は 32バイト * 8 = 256ビットになる。
想像より単純な実装という印象である。これが現代の情報セキュリティの基礎になっているのかと思うと感慨深い。