Skip to content

Instantly share code, notes, and snippets.

@ynkdir
Last active January 26, 2022 01:51
Show Gist options
  • Save ynkdir/4474930 to your computer and use it in GitHub Desktop.
Save ynkdir/4474930 to your computer and use it in GitHub Desktop.
hash function simple version
" md5: http://www.ietf.org/rfc/rfc1321.txt
function! Md5(data)
let data = (type(a:data) == type("") ? s:strtobytes(a:data) : a:data)
return s:md5(data)
endfunction
function! Md5Test()
let s = ""
let h = Md5(s)
if h ==? 'd41d8cd98f00b204e9800998ecf8427e'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "a"
let h = Md5(s)
if h ==? '0cc175b9c0f1b6a831c399e269772661'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "abc"
let h = Md5(s)
if h ==? '900150983cd24fb0d6963f7d28e17f72'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "message digest"
let h = Md5(s)
if h ==? 'f96b697d7cb7938d525a2f31aaf161d0'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "abcdefghijklmnopqrstuvwxyz"
let h = Md5(s)
if h ==? 'c3fcd3d76192e4007dfb496cca67e13b'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
let h = Md5(s)
if h ==? 'd174ab98d277d9f5a5611c2c9f419d9f'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
let h = Md5(s)
if h ==? '57edf4a22be3c955ac49da2e2107b67a'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
endfunction
function! s:md5(bytes)
let m = a:bytes
let bitslen = len(m) * 8
let m += [0x80]
let m += repeat([0], 64 - (len(m) + 8) % 64)
let m += s:uint64_to_bytes_le([bitslen, 0])
let a = 0x67452301
let b = 0xefcdab89
let c = 0x98badcfe
let d = 0x10325476
let x = repeat([0], 16)
for i in range(0, len(m) - 1, 64)
for t in range(0, 15)
let x[t] = s:bytes_to_uint32_le(m[i + t * 4 : i + t * 4 + 3])
endfor
let aa = a
let bb = b
let cc = c
let dd = d
let a = s:FF(a, b, c, d, x[ 0], 7, 0xd76aa478)
let d = s:FF(d, a, b, c, x[ 1], 12, 0xe8c7b756)
let c = s:FF(c, d, a, b, x[ 2], 17, 0x242070db)
let b = s:FF(b, c, d, a, x[ 3], 22, 0xc1bdceee)
let a = s:FF(a, b, c, d, x[ 4], 7, 0xf57c0faf)
let d = s:FF(d, a, b, c, x[ 5], 12, 0x4787c62a)
let c = s:FF(c, d, a, b, x[ 6], 17, 0xa8304613)
let b = s:FF(b, c, d, a, x[ 7], 22, 0xfd469501)
let a = s:FF(a, b, c, d, x[ 8], 7, 0x698098d8)
let d = s:FF(d, a, b, c, x[ 9], 12, 0x8b44f7af)
let c = s:FF(c, d, a, b, x[10], 17, 0xffff5bb1)
let b = s:FF(b, c, d, a, x[11], 22, 0x895cd7be)
let a = s:FF(a, b, c, d, x[12], 7, 0x6b901122)
let d = s:FF(d, a, b, c, x[13], 12, 0xfd987193)
let c = s:FF(c, d, a, b, x[14], 17, 0xa679438e)
let b = s:FF(b, c, d, a, x[15], 22, 0x49b40821)
let a = s:GG(a, b, c, d, x[ 1], 5, 0xf61e2562)
let d = s:GG(d, a, b, c, x[ 6], 9, 0xc040b340)
let c = s:GG(c, d, a, b, x[11], 14, 0x265e5a51)
let b = s:GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa)
let a = s:GG(a, b, c, d, x[ 5], 5, 0xd62f105d)
let d = s:GG(d, a, b, c, x[10], 9, 0x2441453)
let c = s:GG(c, d, a, b, x[15], 14, 0xd8a1e681)
let b = s:GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8)
let a = s:GG(a, b, c, d, x[ 9], 5, 0x21e1cde6)
let d = s:GG(d, a, b, c, x[14], 9, 0xc33707d6)
let c = s:GG(c, d, a, b, x[ 3], 14, 0xf4d50d87)
let b = s:GG(b, c, d, a, x[ 8], 20, 0x455a14ed)
let a = s:GG(a, b, c, d, x[13], 5, 0xa9e3e905)
let d = s:GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8)
let c = s:GG(c, d, a, b, x[ 7], 14, 0x676f02d9)
let b = s:GG(b, c, d, a, x[12], 20, 0x8d2a4c8a)
let a = s:HH(a, b, c, d, x[ 5], 4, 0xfffa3942)
let d = s:HH(d, a, b, c, x[ 8], 11, 0x8771f681)
let c = s:HH(c, d, a, b, x[11], 16, 0x6d9d6122)
let b = s:HH(b, c, d, a, x[14], 23, 0xfde5380c)
let a = s:HH(a, b, c, d, x[ 1], 4, 0xa4beea44)
let d = s:HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9)
let c = s:HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60)
let b = s:HH(b, c, d, a, x[10], 23, 0xbebfbc70)
let a = s:HH(a, b, c, d, x[13], 4, 0x289b7ec6)
let d = s:HH(d, a, b, c, x[ 0], 11, 0xeaa127fa)
let c = s:HH(c, d, a, b, x[ 3], 16, 0xd4ef3085)
let b = s:HH(b, c, d, a, x[ 6], 23, 0x4881d05)
let a = s:HH(a, b, c, d, x[ 9], 4, 0xd9d4d039)
let d = s:HH(d, a, b, c, x[12], 11, 0xe6db99e5)
let c = s:HH(c, d, a, b, x[15], 16, 0x1fa27cf8)
let b = s:HH(b, c, d, a, x[ 2], 23, 0xc4ac5665)
let a = s:II(a, b, c, d, x[ 0], 6, 0xf4292244)
let d = s:II(d, a, b, c, x[ 7], 10, 0x432aff97)
let c = s:II(c, d, a, b, x[14], 15, 0xab9423a7)
let b = s:II(b, c, d, a, x[ 5], 21, 0xfc93a039)
let a = s:II(a, b, c, d, x[12], 6, 0x655b59c3)
let d = s:II(d, a, b, c, x[ 3], 10, 0x8f0ccc92)
let c = s:II(c, d, a, b, x[10], 15, 0xffeff47d)
let b = s:II(b, c, d, a, x[ 1], 21, 0x85845dd1)
let a = s:II(a, b, c, d, x[ 8], 6, 0x6fa87e4f)
let d = s:II(d, a, b, c, x[15], 10, 0xfe2ce6e0)
let c = s:II(c, d, a, b, x[ 6], 15, 0xa3014314)
let b = s:II(b, c, d, a, x[13], 21, 0x4e0811a1)
let a = s:II(a, b, c, d, x[ 4], 6, 0xf7537e82)
let d = s:II(d, a, b, c, x[11], 10, 0xbd3af235)
let c = s:II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb)
let b = s:II(b, c, d, a, x[ 9], 21, 0xeb86d391)
let a = a + aa
let b = b + bb
let c = c + cc
let d = d + dd
endfor
let digest = s:uint32_to_bytes_le(a)
let digest += s:uint32_to_bytes_le(b)
let digest += s:uint32_to_bytes_le(c)
let digest += s:uint32_to_bytes_le(d)
return s:bytestohex(digest)
endfunction
function! s:F(x, y, z)
return or(and(a:x, a:y), and(invert(a:x), a:z))
endfunction
function! s:G(x, y, z)
return or(and(a:x, a:z), and(a:y, invert(a:z)))
endfunction
function! s:H(x, y, z)
return xor(xor(a:x, a:y), a:z)
endfunction
function! s:I(x, y, z)
return xor(a:y, or(a:x, invert(a:z)))
endfunction
function! s:FF(a, b, c, d, xk, s, ti)
return a:b + s:rotateleft32(a:a + s:F(a:b, a:c, a:d) + a:xk + a:ti, a:s)
endfunction
function! s:GG(a, b, c, d, xk, s, ti)
return a:b + s:rotateleft32(a:a + s:G(a:b, a:c, a:d) + a:xk + a:ti, a:s)
endfunction
function! s:HH(a, b, c, d, xk, s, ti)
return a:b + s:rotateleft32(a:a + s:H(a:b, a:c, a:d) + a:xk + a:ti, a:s)
endfunction
function! s:II(a, b, c, d, xk, s, ti)
return a:b + s:rotateleft32(a:a + s:I(a:b, a:c, a:d) + a:xk + a:ti, a:s)
endfunction
function! s:rotateleft32(a, offset)
return or(s:leftshift32(a:a, a:offset), s:rightshift32(a:a, 32 - a:offset))
endfunction
let s:pow2 = [
\ 0x1, 0x2, 0x4, 0x8,
\ 0x10, 0x20, 0x40, 0x80,
\ 0x100, 0x200, 0x400, 0x800,
\ 0x1000, 0x2000, 0x4000, 0x8000,
\ 0x10000, 0x20000, 0x40000, 0x80000,
\ 0x100000, 0x200000, 0x400000, 0x800000,
\ 0x1000000, 0x2000000, 0x4000000, 0x8000000,
\ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
\ ]
function! s:leftshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 : a:a * s:pow2[a:n]
endfunction
function! s:rightshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 :
\ a:a < 0
\ ? (a:a - 0x80000000) / s:pow2[a:n] + 0x40000000 / s:pow2[a:n - 1]
\ : a:a / s:pow2[a:n]
endfunction
function! s:bytes_to_uint32_le(x)
return a:x[3] * 0x1000000 + a:x[2] * 0x10000 + a:x[1] * 0x100 + a:x[0]
endfunction
function! s:uint32_to_bytes_le(x)
let x0 = and(a:x, 0xFF)
let x1 = and(s:rightshift32(a:x, 8), 0xFF)
let x2 = and(s:rightshift32(a:x, 16), 0xFF)
let x3 = and(s:rightshift32(a:x, 24), 0xFF)
return [x0, x1, x2, x3]
endfunction
function! s:uint64_to_bytes_le(x)
let x0 = and(a:x[0], 0xFF)
let x1 = and(s:rightshift32(a:x[0], 8), 0xFF)
let x2 = and(s:rightshift32(a:x[0], 16), 0xFF)
let x3 = and(s:rightshift32(a:x[0], 24), 0xFF)
let x4 = and(a:x[1], 0xFF)
let x5 = and(s:rightshift32(a:x[1], 8), 0xFF)
let x6 = and(s:rightshift32(a:x[1], 16), 0xFF)
let x7 = and(s:rightshift32(a:x[1], 24), 0xFF)
return [x0, x1, x2, x3, x4, x5, x6, x7]
endfunction
function! s:bytes(seq)
if type(a:seq)
return s:strtobytes(a:seq)
elseif type(a:seq) == type([])
return a:seq
else
throw 'type error'
endif
endfunction
function! s:hextobytes(hex)
return map(split(a:hex, '..\zs'), 'str2nr(v:val, 16)')
endfunction
function! s:bytestohex(bytes)
return join(map(copy(a:bytes), 'printf("%02x", v:val)'), '')
endfunction
function! s:strtobytes(str)
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
endfunction
" sha1: http://www.ietf.org/rfc/rfc3174.txt
function! Sha1(data)
let data = (type(a:data) == type("") ? s:strtobytes(a:data) : a:data)
return s:sha1(data)
endfunction
function! Sha1Test()
let s = "abc"
let h = Sha1(s)
if h ==? 'a9993e364706816aba3e25717850c26c9cd0d89d'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
let h = Sha1(s)
if h ==? '84983e441c3bd26ebaae4aa1f95129e5e54670f1'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
"let s = repeat("a", 1000000)
"let h = Sha1(s)
"if h ==? '34aa973cd4c4daa4f61eeb2bdbad27316534016f'
" echo printf('"%.1s..." => %s', s, h)
"else
" echoerr printf('"%.1s..." => %s', s, h)
"endif
let s = repeat("0123456701234567012345670123456701234567012345670123456701234567", 10)
let h = Sha1(s)
if h ==? 'dea356a2cddd90c7a7ecedc5ebb563934f460452'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
endfunction
function! s:sha1(bytes)
let m = a:bytes
let bitslen = len(m) * 8
let m += [0x80]
let m += repeat([0], 64 - (len(m) + 8) % 64)
let m += s:uint64_to_bytes_be([bitslen, 0])
let h0 = 0x67452301
let h1 = 0xEFCDAB89
let h2 = 0x98BADCFE
let h3 = 0x10325476
let h4 = 0xC3D2E1F0
let w = repeat([0], 80)
for i in range(0, len(m) - 1, 64)
for t in range(0, 15)
let w[t] = s:bytes_to_uint32_be(m[i + t * 4 : i + t * 4 + 3])
endfor
for t in range(16, 79)
let w[t] = s:rotateleft32(xor(xor(xor(w[t - 3], w[t - 8]), w[t - 14]), w[t - 16]), 1)
endfor
let a = h0
let b = h1
let c = h2
let d = h3
let e = h4
for t in range(0, 79)
if 0 <= t && t <= 19
let f = or(and(b, c), and(invert(b), d))
let k = 0x5A827999
elseif 20 <= t && t <= 39
let f = xor(xor(b, c), d)
let k = 0x6ED9EBA1
elseif 40 <= t && t <= 59
let f = or(or(and(b, c), and(b, d)), and(c, d))
let k = 0x8F1BBCDC
elseif 60 <= t && t <= 79
let f = xor(xor(b, c), d)
let k = 0xCA62C1D6
endif
let temp = s:rotateleft32(a, 5) + f + e + k + w[t]
let e = d
let d = c
let c = s:rotateleft32(b, 30)
let b = a
let a = temp
endfor
let h0 = h0 + a
let h1 = h1 + b
let h2 = h2 + c
let h3 = h3 + d
let h4 = h4 + e
endfor
let digest = s:uint32_to_bytes_be(h0)
let digest += s:uint32_to_bytes_be(h1)
let digest += s:uint32_to_bytes_be(h2)
let digest += s:uint32_to_bytes_be(h3)
let digest += s:uint32_to_bytes_be(h4)
return s:bytestohex(digest)
endfunction
function! s:rotateleft32(a, offset)
return or(s:leftshift32(a:a, a:offset), s:rightshift32(a:a, 32 - a:offset))
endfunction
let s:pow2 = [
\ 0x1, 0x2, 0x4, 0x8,
\ 0x10, 0x20, 0x40, 0x80,
\ 0x100, 0x200, 0x400, 0x800,
\ 0x1000, 0x2000, 0x4000, 0x8000,
\ 0x10000, 0x20000, 0x40000, 0x80000,
\ 0x100000, 0x200000, 0x400000, 0x800000,
\ 0x1000000, 0x2000000, 0x4000000, 0x8000000,
\ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
\ ]
function! s:leftshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 : a:a * s:pow2[a:n]
endfunction
function! s:rightshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 :
\ a:a < 0
\ ? (a:a - 0x80000000) / s:pow2[a:n] + 0x40000000 / s:pow2[a:n - 1]
\ : a:a / s:pow2[a:n]
endfunction
function! s:bytes_to_uint32_be(x)
return a:x[0] * 0x1000000 + a:x[1] * 0x10000 + a:x[2] * 0x100 + a:x[3]
endfunction
function! s:uint32_to_bytes_be(x)
let x0 = and(a:x, 0xFF)
let x1 = and(s:rightshift32(a:x, 8), 0xFF)
let x2 = and(s:rightshift32(a:x, 16), 0xFF)
let x3 = and(s:rightshift32(a:x, 24), 0xFF)
return [x3, x2, x1, x0]
endfunction
function! s:uint64_to_bytes_be(x)
let x0 = and(a:x[0], 0xFF)
let x1 = and(s:rightshift32(a:x[0], 8), 0xFF)
let x2 = and(s:rightshift32(a:x[0], 16), 0xFF)
let x3 = and(s:rightshift32(a:x[0], 24), 0xFF)
let x4 = and(a:x[1], 0xFF)
let x5 = and(s:rightshift32(a:x[1], 8), 0xFF)
let x6 = and(s:rightshift32(a:x[1], 16), 0xFF)
let x7 = and(s:rightshift32(a:x[1], 24), 0xFF)
return [x7, x6, x5, x4, x3, x2, x1, x0]
endfunction
function! s:bytes(seq)
if type(a:seq)
return s:strtobytes(a:seq)
elseif type(a:seq) == type([])
return a:seq
else
throw 'type error'
endif
endfunction
function! s:hextobytes(hex)
return map(split(a:hex, '..\zs'), 'str2nr(v:val, 16)')
endfunction
function! s:bytestohex(bytes)
return join(map(copy(a:bytes), 'printf("%02x", v:val)'), '')
endfunction
function! s:strtobytes(str)
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
endfunction
" sha224: http://www.ietf.org/rfc/rfc4634.txt
function! Sha224(data)
let data = (type(a:data) == type("") ? s:strtobytes(a:data) : a:data)
return s:sha224(data)
endfunction
function! Sha224Test()
let s = "abc"
let h = Sha224(s)
if h ==? '23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
let h = Sha224(s)
if h ==? '75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
"let s = repeat("a", 1000000)
"let h = Sha224(s)
"if h ==? '20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67'
" echo printf('"%.1s..." => %s', s, h)
"else
" echoerr printf('"%.1s..." => %s', s, h)
"endif
let s = repeat("0123456701234567012345670123456701234567012345670123456701234567", 10)
let h = Sha224(s)
if h ==? '567f69f168cd7844e65259ce658fe7aadfa25216e68eca0eb7ab8262'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
endfunction
let s:K = [
\ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
\ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
\ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
\ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
\ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
\ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
\ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
\ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
\ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
\ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
\ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
\ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
\ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
\ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
\ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
\ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
\ ]
function! s:sha224(bytes)
let m = a:bytes
let bitslen = len(m) * 8
let m += [0x80]
let m += repeat([0], 64 - (len(m) + 8) % 64)
let m += s:uint64_to_bytes_be([bitslen, 0])
let h0 = 0xc1059ed8
let h1 = 0x367cd507
let h2 = 0x3070dd17
let h3 = 0xf70e5939
let h4 = 0xffc00b31
let h5 = 0x68581511
let h6 = 0x64f98fa7
let h7 = 0xbefa4fa4
let w = repeat([0], 64)
for i in range(0, len(m) - 1, 64)
for t in range(0, 15)
let w[t] = s:bytes_to_uint32_be(m[i + t * 4 : i + t * 4 + 3])
endfor
for t in range(16, 63)
let w[t] = s:SSIG1(w[t - 2]) + w[t - 7] + s:SSIG0(w[t - 15]) + w[t - 16]
endfor
let a = h0
let b = h1
let c = h2
let d = h3
let e = h4
let f = h5
let g = h6
let h = h7
for t in range(0, 63)
let t1 = h + s:BSIG1(e) + s:CH(e, f, g) + s:K[t] + w[t]
let t2 = s:BSIG0(a) + s:MAJ(a, b, c)
let h = g
let g = f
let f = e
let e = d + t1
let d = c
let c = b
let b = a
let a = t1 + t2
endfor
let h0 = a + h0
let h1 = b + h1
let h2 = c + h2
let h3 = d + h3
let h4 = e + h4
let h5 = f + h5
let h6 = g + h6
let h7 = h + h7
endfor
let digest = s:uint32_to_bytes_be(h0)
let digest += s:uint32_to_bytes_be(h1)
let digest += s:uint32_to_bytes_be(h2)
let digest += s:uint32_to_bytes_be(h3)
let digest += s:uint32_to_bytes_be(h4)
let digest += s:uint32_to_bytes_be(h5)
let digest += s:uint32_to_bytes_be(h6)
return s:bytestohex(digest)
endfunction
function! s:CH(x, y, z)
return xor(and(a:x, a:y), and(invert(a:x), a:z))
endfunction
function! s:MAJ(x, y, z)
return xor(xor(and(a:x, a:y), and(a:x, a:z)), and(a:y, a:z))
endfunction
function! s:BSIG0(x)
return xor(xor(s:rotateright32(a:x, 2), s:rotateright32(a:x, 13)), s:rotateright32(a:x, 22))
endfunction
function! s:BSIG1(x)
return xor(xor(s:rotateright32(a:x, 6), s:rotateright32(a:x, 11)), s:rotateright32(a:x, 25))
endfunction
function! s:SSIG0(x)
return xor(xor(s:rotateright32(a:x, 7), s:rotateright32(a:x, 18)), s:rightshift32(a:x, 3))
endfunction
function! s:SSIG1(x)
return xor(xor(s:rotateright32(a:x, 17), s:rotateright32(a:x, 19)), s:rightshift32(a:x, 10))
endfunction
function! s:rotateleft32(a, offset)
return or(s:leftshift32(a:a, a:offset), s:rightshift32(a:a, 32 - a:offset))
endfunction
function! s:rotateright32(a, offset)
return or(s:rightshift32(a:a, a:offset), s:leftshift32(a:a, 32 - a:offset))
endfunction
let s:pow2 = [
\ 0x1, 0x2, 0x4, 0x8,
\ 0x10, 0x20, 0x40, 0x80,
\ 0x100, 0x200, 0x400, 0x800,
\ 0x1000, 0x2000, 0x4000, 0x8000,
\ 0x10000, 0x20000, 0x40000, 0x80000,
\ 0x100000, 0x200000, 0x400000, 0x800000,
\ 0x1000000, 0x2000000, 0x4000000, 0x8000000,
\ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
\ ]
function! s:leftshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 : a:a * s:pow2[a:n]
endfunction
function! s:rightshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 :
\ a:a < 0
\ ? (a:a - 0x80000000) / s:pow2[a:n] + 0x40000000 / s:pow2[a:n - 1]
\ : a:a / s:pow2[a:n]
endfunction
function! s:bytes_to_uint32_be(x)
return a:x[0] * 0x1000000 + a:x[1] * 0x10000 + a:x[2] * 0x100 + a:x[3]
endfunction
function! s:uint32_to_bytes_be(x)
let x0 = and(a:x, 0xFF)
let x1 = and(s:rightshift32(a:x, 8), 0xFF)
let x2 = and(s:rightshift32(a:x, 16), 0xFF)
let x3 = and(s:rightshift32(a:x, 24), 0xFF)
return [x3, x2, x1, x0]
endfunction
function! s:uint64_to_bytes_be(x)
let x0 = and(a:x[0], 0xFF)
let x1 = and(s:rightshift32(a:x[0], 8), 0xFF)
let x2 = and(s:rightshift32(a:x[0], 16), 0xFF)
let x3 = and(s:rightshift32(a:x[0], 24), 0xFF)
let x4 = and(a:x[1], 0xFF)
let x5 = and(s:rightshift32(a:x[1], 8), 0xFF)
let x6 = and(s:rightshift32(a:x[1], 16), 0xFF)
let x7 = and(s:rightshift32(a:x[1], 24), 0xFF)
return [x7, x6, x5, x4, x3, x2, x1, x0]
endfunction
function! s:bytes(seq)
if type(a:seq)
return s:strtobytes(a:seq)
elseif type(a:seq) == type([])
return a:seq
else
throw 'type error'
endif
endfunction
function! s:hextobytes(hex)
return map(split(a:hex, '..\zs'), 'str2nr(v:val, 16)')
endfunction
function! s:bytestohex(bytes)
return join(map(copy(a:bytes), 'printf("%02x", v:val)'), '')
endfunction
function! s:strtobytes(str)
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
endfunction
" sha256: http://www.ietf.org/rfc/rfc4634.txt
function! Sha256(data)
let data = (type(a:data) == type("") ? s:strtobytes(a:data) : a:data)
return s:sha256(data)
endfunction
function! Sha256Test()
let s = "abc"
let h = Sha256(s)
if h ==? 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
let h = Sha256(s)
if h ==? '248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
"let s = repeat("a", 1000000)
"let h = Sha256(s)
"if h ==? '594847328451bdfa85056225462cc1d867d877fb388df0ce35f25ab5562bfbb5'
" echo printf('"%.1s..." => %s', s, h)
"else
" echoerr printf('"%.1s..." => %s', s, h)
"endif
let s = repeat("0123456701234567012345670123456701234567012345670123456701234567", 10)
let h = Sha256(s)
if h ==? '594847328451bdfa85056225462cc1d867d877fb388df0ce35f25ab5562bfbb5'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
endfunction
let s:K = [
\ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
\ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
\ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
\ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
\ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
\ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
\ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
\ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
\ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
\ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
\ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
\ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
\ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
\ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
\ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
\ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
\ ]
function! s:sha256(bytes)
let m = a:bytes
let bitslen = len(m) * 8
let m += [0x80]
let m += repeat([0], 64 - (len(m) + 8) % 64)
let m += s:uint64_to_bytes_be([bitslen, 0])
let h0 = 0x6a09e667
let h1 = 0xbb67ae85
let h2 = 0x3c6ef372
let h3 = 0xa54ff53a
let h4 = 0x510e527f
let h5 = 0x9b05688c
let h6 = 0x1f83d9ab
let h7 = 0x5be0cd19
let w = repeat([0], 64)
for i in range(0, len(m) - 1, 64)
for t in range(0, 15)
let w[t] = s:bytes_to_uint32_be(m[i + t * 4 : i + t * 4 + 3])
endfor
for t in range(16, 63)
let w[t] = s:SSIG1(w[t - 2]) + w[t - 7] + s:SSIG0(w[t - 15]) + w[t - 16]
endfor
let a = h0
let b = h1
let c = h2
let d = h3
let e = h4
let f = h5
let g = h6
let h = h7
for t in range(0, 63)
let t1 = h + s:BSIG1(e) + s:CH(e, f, g) + s:K[t] + w[t]
let t2 = s:BSIG0(a) + s:MAJ(a, b, c)
let h = g
let g = f
let f = e
let e = d + t1
let d = c
let c = b
let b = a
let a = t1 + t2
endfor
let h0 = a + h0
let h1 = b + h1
let h2 = c + h2
let h3 = d + h3
let h4 = e + h4
let h5 = f + h5
let h6 = g + h6
let h7 = h + h7
endfor
let digest = s:uint32_to_bytes_be(h0)
let digest += s:uint32_to_bytes_be(h1)
let digest += s:uint32_to_bytes_be(h2)
let digest += s:uint32_to_bytes_be(h3)
let digest += s:uint32_to_bytes_be(h4)
let digest += s:uint32_to_bytes_be(h5)
let digest += s:uint32_to_bytes_be(h6)
let digest += s:uint32_to_bytes_be(h7)
return s:bytestohex(digest)
endfunction
function! s:CH(x, y, z)
return xor(and(a:x, a:y), and(invert(a:x), a:z))
endfunction
function! s:MAJ(x, y, z)
return xor(xor(and(a:x, a:y), and(a:x, a:z)), and(a:y, a:z))
endfunction
function! s:BSIG0(x)
return xor(xor(s:rotateright32(a:x, 2), s:rotateright32(a:x, 13)), s:rotateright32(a:x, 22))
endfunction
function! s:BSIG1(x)
return xor(xor(s:rotateright32(a:x, 6), s:rotateright32(a:x, 11)), s:rotateright32(a:x, 25))
endfunction
function! s:SSIG0(x)
return xor(xor(s:rotateright32(a:x, 7), s:rotateright32(a:x, 18)), s:rightshift32(a:x, 3))
endfunction
function! s:SSIG1(x)
return xor(xor(s:rotateright32(a:x, 17), s:rotateright32(a:x, 19)), s:rightshift32(a:x, 10))
endfunction
function! s:rotateleft32(a, offset)
return or(s:leftshift32(a:a, a:offset), s:rightshift32(a:a, 32 - a:offset))
endfunction
function! s:rotateright32(a, offset)
return or(s:rightshift32(a:a, a:offset), s:leftshift32(a:a, 32 - a:offset))
endfunction
let s:pow2 = [
\ 0x1, 0x2, 0x4, 0x8,
\ 0x10, 0x20, 0x40, 0x80,
\ 0x100, 0x200, 0x400, 0x800,
\ 0x1000, 0x2000, 0x4000, 0x8000,
\ 0x10000, 0x20000, 0x40000, 0x80000,
\ 0x100000, 0x200000, 0x400000, 0x800000,
\ 0x1000000, 0x2000000, 0x4000000, 0x8000000,
\ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
\ ]
function! s:leftshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 : a:a * s:pow2[a:n]
endfunction
function! s:rightshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 :
\ a:a < 0
\ ? (a:a - 0x80000000) / s:pow2[a:n] + 0x40000000 / s:pow2[a:n - 1]
\ : a:a / s:pow2[a:n]
endfunction
function! s:bytes_to_uint32_be(x)
return a:x[0] * 0x1000000 + a:x[1] * 0x10000 + a:x[2] * 0x100 + a:x[3]
endfunction
function! s:uint32_to_bytes_be(x)
let x0 = and(a:x, 0xFF)
let x1 = and(s:rightshift32(a:x, 8), 0xFF)
let x2 = and(s:rightshift32(a:x, 16), 0xFF)
let x3 = and(s:rightshift32(a:x, 24), 0xFF)
return [x3, x2, x1, x0]
endfunction
function! s:uint64_to_bytes_be(x)
let x0 = and(a:x[0], 0xFF)
let x1 = and(s:rightshift32(a:x[0], 8), 0xFF)
let x2 = and(s:rightshift32(a:x[0], 16), 0xFF)
let x3 = and(s:rightshift32(a:x[0], 24), 0xFF)
let x4 = and(a:x[1], 0xFF)
let x5 = and(s:rightshift32(a:x[1], 8), 0xFF)
let x6 = and(s:rightshift32(a:x[1], 16), 0xFF)
let x7 = and(s:rightshift32(a:x[1], 24), 0xFF)
return [x7, x6, x5, x4, x3, x2, x1, x0]
endfunction
function! s:bytes(seq)
if type(a:seq)
return s:strtobytes(a:seq)
elseif type(a:seq) == type([])
return a:seq
else
throw 'type error'
endif
endfunction
function! s:hextobytes(hex)
return map(split(a:hex, '..\zs'), 'str2nr(v:val, 16)')
endfunction
function! s:bytestohex(bytes)
return join(map(copy(a:bytes), 'printf("%02x", v:val)'), '')
endfunction
function! s:strtobytes(str)
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
endfunction
" sha384: http://www.ietf.org/rfc/rfc4634.txt
function! Sha384(data)
let data = (type(a:data) == type("") ? s:strtobytes(a:data) : a:data)
return s:sha384(data)
endfunction
function! Sha384Test()
let s = "abc"
let h = Sha384(s)
if h ==? 'cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
let h = Sha384(s)
if h ==? '09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
"let s = repeat("a", 1000000)
"let h = Sha384(s)
"if h ==? '9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985'
" echo printf('"%.1s..." => %s', s, h)
"else
" echoerr printf('"%.1s..." => %s', s, h)
"endif
let s = repeat("0123456701234567012345670123456701234567012345670123456701234567", 10)
let h = Sha384(s)
if h ==? '2fc64a4f500ddb6828f6a3430b8dd72a368eb7f3a8322a70bc84275b9c0b3ab00d27a5cc3c2d224aa6b61a0d79fb4596'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
endfunction
let s:K = [
\ [0xd728ae22, 0x428a2f98], [0x23ef65cd, 0x71374491], [0xec4d3b2f, 0xb5c0fbcf], [0x8189dbbc, 0xe9b5dba5],
\ [0xf348b538, 0x3956c25b], [0xb605d019, 0x59f111f1], [0xaf194f9b, 0x923f82a4], [0xda6d8118, 0xab1c5ed5],
\ [0xa3030242, 0xd807aa98], [0x45706fbe, 0x12835b01], [0x4ee4b28c, 0x243185be], [0xd5ffb4e2, 0x550c7dc3],
\ [0xf27b896f, 0x72be5d74], [0x3b1696b1, 0x80deb1fe], [0x25c71235, 0x9bdc06a7], [0xcf692694, 0xc19bf174],
\ [0x9ef14ad2, 0xe49b69c1], [0x384f25e3, 0xefbe4786], [0x8b8cd5b5, 0x0fc19dc6], [0x77ac9c65, 0x240ca1cc],
\ [0x592b0275, 0x2de92c6f], [0x6ea6e483, 0x4a7484aa], [0xbd41fbd4, 0x5cb0a9dc], [0x831153b5, 0x76f988da],
\ [0xee66dfab, 0x983e5152], [0x2db43210, 0xa831c66d], [0x98fb213f, 0xb00327c8], [0xbeef0ee4, 0xbf597fc7],
\ [0x3da88fc2, 0xc6e00bf3], [0x930aa725, 0xd5a79147], [0xe003826f, 0x06ca6351], [0x0a0e6e70, 0x14292967],
\ [0x46d22ffc, 0x27b70a85], [0x5c26c926, 0x2e1b2138], [0x5ac42aed, 0x4d2c6dfc], [0x9d95b3df, 0x53380d13],
\ [0x8baf63de, 0x650a7354], [0x3c77b2a8, 0x766a0abb], [0x47edaee6, 0x81c2c92e], [0x1482353b, 0x92722c85],
\ [0x4cf10364, 0xa2bfe8a1], [0xbc423001, 0xa81a664b], [0xd0f89791, 0xc24b8b70], [0x0654be30, 0xc76c51a3],
\ [0xd6ef5218, 0xd192e819], [0x5565a910, 0xd6990624], [0x5771202a, 0xf40e3585], [0x32bbd1b8, 0x106aa070],
\ [0xb8d2d0c8, 0x19a4c116], [0x5141ab53, 0x1e376c08], [0xdf8eeb99, 0x2748774c], [0xe19b48a8, 0x34b0bcb5],
\ [0xc5c95a63, 0x391c0cb3], [0xe3418acb, 0x4ed8aa4a], [0x7763e373, 0x5b9cca4f], [0xd6b2b8a3, 0x682e6ff3],
\ [0x5defb2fc, 0x748f82ee], [0x43172f60, 0x78a5636f], [0xa1f0ab72, 0x84c87814], [0x1a6439ec, 0x8cc70208],
\ [0x23631e28, 0x90befffa], [0xde82bde9, 0xa4506ceb], [0xb2c67915, 0xbef9a3f7], [0xe372532b, 0xc67178f2],
\ [0xea26619c, 0xca273ece], [0x21c0c207, 0xd186b8c7], [0xcde0eb1e, 0xeada7dd6], [0xee6ed178, 0xf57d4f7f],
\ [0x72176fba, 0x06f067aa], [0xa2c898a6, 0x0a637dc5], [0xbef90dae, 0x113f9804], [0x131c471b, 0x1b710b35],
\ [0x23047d84, 0x28db77f5], [0x40c72493, 0x32caab7b], [0x15c9bebc, 0x3c9ebe0a], [0x9c100d4c, 0x431d67c4],
\ [0xcb3e42b6, 0x4cc5d4be], [0xfc657e2a, 0x597f299c], [0x3ad6faec, 0x5fcb6fab], [0x4a475817, 0x6c44198c],
\ ]
function! s:sha384(bytes)
let m = a:bytes
let bitslen = len(m) * 8
let m += [0x80]
let m += repeat([0], 128 - (len(m) + 16) % 128)
let m += s:uint64_to_bytes_be([0, 0])
let m += s:uint64_to_bytes_be([bitslen, 0])
let h0 = [0xc1059ed8, 0xcbbb9d5d]
let h1 = [0x367cd507, 0x629a292a]
let h2 = [0x3070dd17, 0x9159015a]
let h3 = [0xf70e5939, 0x152fecd8]
let h4 = [0xffc00b31, 0x67332667]
let h5 = [0x68581511, 0x8eb44a87]
let h6 = [0x64f98fa7, 0xdb0c2e0d]
let h7 = [0xbefa4fa4, 0x47b5481d]
let w = repeat([0], 80)
for i in range(0, len(m) - 1, 128)
for t in range(0, 15)
let w[t] = s:bytes_to_uint64_be(m[i + t * 8 : i + t * 8 + 7])
endfor
for t in range(16, 79)
let w[t] = s:add64(s:add64(s:add64(s:SSIG1(w[t - 2]), w[t - 7]), s:SSIG0(w[t - 15])), w[t - 16])
endfor
let a = h0
let b = h1
let c = h2
let d = h3
let e = h4
let f = h5
let g = h6
let h = h7
for t in range(0, 79)
let t1 = s:add64(s:add64(s:add64(s:add64(h, s:BSIG1(e)), s:CH(e, f, g)), s:K[t]), w[t])
let t2 = s:add64(s:BSIG0(a), s:MAJ(a, b, c))
let h = g
let g = f
let f = e
let e = s:add64(d, t1)
let d = c
let c = b
let b = a
let a = s:add64(t1, t2)
endfor
let h0 = s:add64(a, h0)
let h1 = s:add64(b, h1)
let h2 = s:add64(c, h2)
let h3 = s:add64(d, h3)
let h4 = s:add64(e, h4)
let h5 = s:add64(f, h5)
let h6 = s:add64(g, h6)
let h7 = s:add64(h, h7)
endfor
let digest = s:uint64_to_bytes_be(h0)
let digest += s:uint64_to_bytes_be(h1)
let digest += s:uint64_to_bytes_be(h2)
let digest += s:uint64_to_bytes_be(h3)
let digest += s:uint64_to_bytes_be(h4)
let digest += s:uint64_to_bytes_be(h5)
return s:bytestohex(digest)
endfunction
function! s:CH(x, y, z)
return s:xor64(s:and64(a:x, a:y), s:and64(s:invert64(a:x), a:z))
endfunction
function! s:MAJ(x, y, z)
return s:xor64(s:xor64(s:and64(a:x, a:y), s:and64(a:x, a:z)), s:and64(a:y, a:z))
endfunction
function! s:BSIG0(x)
return s:xor64(s:xor64(s:rotateright64(a:x, 28), s:rotateright64(a:x, 34)), s:rotateright64(a:x, 39))
endfunction
function! s:BSIG1(x)
return s:xor64(s:xor64(s:rotateright64(a:x, 14), s:rotateright64(a:x, 18)), s:rotateright64(a:x, 41))
endfunction
function! s:SSIG0(x)
return s:xor64(s:xor64(s:rotateright64(a:x, 1), s:rotateright64(a:x, 8)), s:rightshift64(a:x, 7))
endfunction
function! s:SSIG1(x)
return s:xor64(s:xor64(s:rotateright64(a:x, 19), s:rotateright64(a:x, 61)), s:rightshift64(a:x, 6))
endfunction
function! s:cmp64(a, b)
let c = s:cmp32(a:a[1], a:b[1])
if c == 0
let c = s:cmp32(a:a[0], a:b[0])
endif
return c
endfunction
function! s:cmp32(a, b)
if (a:a >= 0 && a:b >= 0) || (a:a < 0 && a:b < 0)
return a:a < a:b ? -1 : a:a > a:b ? 1 : 0
else
return a:a < 0 ? 1 : -1
endif
endfunction
function! s:add64(a, b)
let lo = a:a[0] + a:b[0]
let c = (s:cmp32(lo, a:b[0]) < 0)
let hi = a:a[1] + a:b[1] + c
return [lo, hi]
endfunction
function! s:rotateleft64(a, offset)
return s:or64(s:leftshift64(a:a, a:offset), s:rightshift64(a:a, 64 - a:offset))
endfunction
function! s:rotateright64(a, offset)
return s:or64(s:rightshift64(a:a, a:offset), s:leftshift64(a:a, 64 - a:offset))
endfunction
function! s:invert64(x)
return [invert(a:x[0]), invert(a:x[1])]
endfunction
function! s:and64(x, y)
return [and(a:x[0], a:y[0]), and(a:x[1], a:y[1])]
endfunction
function! s:or64(x, y)
return [or(a:x[0], a:y[0]), or(a:x[1], a:y[1])]
endfunction
function! s:xor64(x, y)
return [xor(a:x[0], a:y[0]), xor(a:x[1], a:y[1])]
endfunction
let s:pow2 = [
\ 0x1, 0x2, 0x4, 0x8,
\ 0x10, 0x20, 0x40, 0x80,
\ 0x100, 0x200, 0x400, 0x800,
\ 0x1000, 0x2000, 0x4000, 0x8000,
\ 0x10000, 0x20000, 0x40000, 0x80000,
\ 0x100000, 0x200000, 0x400000, 0x800000,
\ 0x1000000, 0x2000000, 0x4000000, 0x8000000,
\ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
\ ]
function! s:leftshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 : a:a * s:pow2[a:n]
endfunction
function! s:rightshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 :
\ a:a < 0
\ ? (a:a - 0x80000000) / s:pow2[a:n] + 0x40000000 / s:pow2[a:n - 1]
\ : a:a / s:pow2[a:n]
endfunction
function! s:leftshift64(x, n)
let lo = s:leftshift32(a:x[0], a:n)
if a:n < 32
let hi = or(s:leftshift32(a:x[1], a:n), s:rightshift32(a:x[0], 32 - a:n))
else
let hi = s:leftshift32(a:x[0], a:n - 32)
endif
return [lo, hi]
endfunction
function! s:rightshift64(x, n)
let hi = s:rightshift32(a:x[1], a:n)
if a:n < 32
let lo = or(s:rightshift32(a:x[0], a:n), s:leftshift32(a:x[1], 32 - a:n))
else
let lo = s:rightshift32(a:x[1], a:n - 32)
endif
return [lo, hi]
endfunction
function! s:bytes_to_uint64_be(x)
let lo = a:x[4] * 0x1000000 + a:x[5] * 0x10000 + a:x[6] * 0x100 + a:x[7]
let hi = a:x[0] * 0x1000000 + a:x[1] * 0x10000 + a:x[2] * 0x100 + a:x[3]
return [lo, hi]
endfunction
function! s:uint64_to_bytes_be(x)
let x0 = and(a:x[0], 0xFF)
let x1 = and(s:rightshift32(a:x[0], 8), 0xFF)
let x2 = and(s:rightshift32(a:x[0], 16), 0xFF)
let x3 = and(s:rightshift32(a:x[0], 24), 0xFF)
let x4 = and(a:x[1], 0xFF)
let x5 = and(s:rightshift32(a:x[1], 8), 0xFF)
let x6 = and(s:rightshift32(a:x[1], 16), 0xFF)
let x7 = and(s:rightshift32(a:x[1], 24), 0xFF)
return [x7, x6, x5, x4, x3, x2, x1, x0]
endfunction
function! s:bytes(seq)
if type(a:seq)
return s:strtobytes(a:seq)
elseif type(a:seq) == type([])
return a:seq
else
throw 'type error'
endif
endfunction
function! s:hextobytes(hex)
return map(split(a:hex, '..\zs'), 'str2nr(v:val, 16)')
endfunction
function! s:bytestohex(bytes)
return join(map(copy(a:bytes), 'printf("%02x", v:val)'), '')
endfunction
function! s:strtobytes(str)
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
endfunction
" sha512: http://www.ietf.org/rfc/rfc4634.txt
function! Sha512(data)
let data = (type(a:data) == type("") ? s:strtobytes(a:data) : a:data)
return s:sha512(data)
endfunction
function! Sha512Test()
let s = "abc"
let h = Sha512(s)
if h ==? 'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
let s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
let h = Sha512(s)
if h ==? '8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
"let s = repeat("a", 1000000)
"let h = Sha512(s)
"if h ==? 'e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b'
" echo printf('"%.1s..." => %s', s, h)
"else
" echoerr printf('"%.1s..." => %s', s, h)
"endif
let s = repeat("0123456701234567012345670123456701234567012345670123456701234567", 10)
let h = Sha512(s)
if h ==? '89d05ba632c699c31231ded4ffc127d5a894dad412c0e024db872d1abd2ba8141a0f85072a9be1e2aa04cf33c765cb510813a39cd5a84c4acaa64d3f3fb7bae9'
echo printf('"%s" => %s', s, h)
else
echoerr printf('"%s" => %s', s, h)
endif
endfunction
let s:K = [
\ [0xd728ae22, 0x428a2f98], [0x23ef65cd, 0x71374491], [0xec4d3b2f, 0xb5c0fbcf], [0x8189dbbc, 0xe9b5dba5],
\ [0xf348b538, 0x3956c25b], [0xb605d019, 0x59f111f1], [0xaf194f9b, 0x923f82a4], [0xda6d8118, 0xab1c5ed5],
\ [0xa3030242, 0xd807aa98], [0x45706fbe, 0x12835b01], [0x4ee4b28c, 0x243185be], [0xd5ffb4e2, 0x550c7dc3],
\ [0xf27b896f, 0x72be5d74], [0x3b1696b1, 0x80deb1fe], [0x25c71235, 0x9bdc06a7], [0xcf692694, 0xc19bf174],
\ [0x9ef14ad2, 0xe49b69c1], [0x384f25e3, 0xefbe4786], [0x8b8cd5b5, 0x0fc19dc6], [0x77ac9c65, 0x240ca1cc],
\ [0x592b0275, 0x2de92c6f], [0x6ea6e483, 0x4a7484aa], [0xbd41fbd4, 0x5cb0a9dc], [0x831153b5, 0x76f988da],
\ [0xee66dfab, 0x983e5152], [0x2db43210, 0xa831c66d], [0x98fb213f, 0xb00327c8], [0xbeef0ee4, 0xbf597fc7],
\ [0x3da88fc2, 0xc6e00bf3], [0x930aa725, 0xd5a79147], [0xe003826f, 0x06ca6351], [0x0a0e6e70, 0x14292967],
\ [0x46d22ffc, 0x27b70a85], [0x5c26c926, 0x2e1b2138], [0x5ac42aed, 0x4d2c6dfc], [0x9d95b3df, 0x53380d13],
\ [0x8baf63de, 0x650a7354], [0x3c77b2a8, 0x766a0abb], [0x47edaee6, 0x81c2c92e], [0x1482353b, 0x92722c85],
\ [0x4cf10364, 0xa2bfe8a1], [0xbc423001, 0xa81a664b], [0xd0f89791, 0xc24b8b70], [0x0654be30, 0xc76c51a3],
\ [0xd6ef5218, 0xd192e819], [0x5565a910, 0xd6990624], [0x5771202a, 0xf40e3585], [0x32bbd1b8, 0x106aa070],
\ [0xb8d2d0c8, 0x19a4c116], [0x5141ab53, 0x1e376c08], [0xdf8eeb99, 0x2748774c], [0xe19b48a8, 0x34b0bcb5],
\ [0xc5c95a63, 0x391c0cb3], [0xe3418acb, 0x4ed8aa4a], [0x7763e373, 0x5b9cca4f], [0xd6b2b8a3, 0x682e6ff3],
\ [0x5defb2fc, 0x748f82ee], [0x43172f60, 0x78a5636f], [0xa1f0ab72, 0x84c87814], [0x1a6439ec, 0x8cc70208],
\ [0x23631e28, 0x90befffa], [0xde82bde9, 0xa4506ceb], [0xb2c67915, 0xbef9a3f7], [0xe372532b, 0xc67178f2],
\ [0xea26619c, 0xca273ece], [0x21c0c207, 0xd186b8c7], [0xcde0eb1e, 0xeada7dd6], [0xee6ed178, 0xf57d4f7f],
\ [0x72176fba, 0x06f067aa], [0xa2c898a6, 0x0a637dc5], [0xbef90dae, 0x113f9804], [0x131c471b, 0x1b710b35],
\ [0x23047d84, 0x28db77f5], [0x40c72493, 0x32caab7b], [0x15c9bebc, 0x3c9ebe0a], [0x9c100d4c, 0x431d67c4],
\ [0xcb3e42b6, 0x4cc5d4be], [0xfc657e2a, 0x597f299c], [0x3ad6faec, 0x5fcb6fab], [0x4a475817, 0x6c44198c],
\ ]
function! s:sha512(bytes)
let m = a:bytes
let bitslen = len(m) * 8
let m += [0x80]
let m += repeat([0], 128 - (len(m) + 16) % 128)
let m += s:uint64_to_bytes_be([0, 0])
let m += s:uint64_to_bytes_be([bitslen, 0])
let h0 = [0xf3bcc908, 0x6a09e667]
let h1 = [0x84caa73b, 0xbb67ae85]
let h2 = [0xfe94f82b, 0x3c6ef372]
let h3 = [0x5f1d36f1, 0xa54ff53a]
let h4 = [0xade682d1, 0x510e527f]
let h5 = [0x2b3e6c1f, 0x9b05688c]
let h6 = [0xfb41bd6b, 0x1f83d9ab]
let h7 = [0x137e2179, 0x5be0cd19]
let w = repeat([0], 80)
for i in range(0, len(m) - 1, 128)
for t in range(0, 15)
let w[t] = s:bytes_to_uint64_be(m[i + t * 8 : i + t * 8 + 7])
endfor
for t in range(16, 79)
let w[t] = s:add64(s:add64(s:add64(s:SSIG1(w[t - 2]), w[t - 7]), s:SSIG0(w[t - 15])), w[t - 16])
endfor
let a = h0
let b = h1
let c = h2
let d = h3
let e = h4
let f = h5
let g = h6
let h = h7
for t in range(0, 79)
let t1 = s:add64(s:add64(s:add64(s:add64(h, s:BSIG1(e)), s:CH(e, f, g)), s:K[t]), w[t])
let t2 = s:add64(s:BSIG0(a), s:MAJ(a, b, c))
let h = g
let g = f
let f = e
let e = s:add64(d, t1)
let d = c
let c = b
let b = a
let a = s:add64(t1, t2)
endfor
let h0 = s:add64(a, h0)
let h1 = s:add64(b, h1)
let h2 = s:add64(c, h2)
let h3 = s:add64(d, h3)
let h4 = s:add64(e, h4)
let h5 = s:add64(f, h5)
let h6 = s:add64(g, h6)
let h7 = s:add64(h, h7)
endfor
let digest = s:uint64_to_bytes_be(h0)
let digest += s:uint64_to_bytes_be(h1)
let digest += s:uint64_to_bytes_be(h2)
let digest += s:uint64_to_bytes_be(h3)
let digest += s:uint64_to_bytes_be(h4)
let digest += s:uint64_to_bytes_be(h5)
let digest += s:uint64_to_bytes_be(h6)
let digest += s:uint64_to_bytes_be(h7)
return s:bytestohex(digest)
endfunction
function! s:CH(x, y, z)
return s:xor64(s:and64(a:x, a:y), s:and64(s:invert64(a:x), a:z))
endfunction
function! s:MAJ(x, y, z)
return s:xor64(s:xor64(s:and64(a:x, a:y), s:and64(a:x, a:z)), s:and64(a:y, a:z))
endfunction
function! s:BSIG0(x)
return s:xor64(s:xor64(s:rotateright64(a:x, 28), s:rotateright64(a:x, 34)), s:rotateright64(a:x, 39))
endfunction
function! s:BSIG1(x)
return s:xor64(s:xor64(s:rotateright64(a:x, 14), s:rotateright64(a:x, 18)), s:rotateright64(a:x, 41))
endfunction
function! s:SSIG0(x)
return s:xor64(s:xor64(s:rotateright64(a:x, 1), s:rotateright64(a:x, 8)), s:rightshift64(a:x, 7))
endfunction
function! s:SSIG1(x)
return s:xor64(s:xor64(s:rotateright64(a:x, 19), s:rotateright64(a:x, 61)), s:rightshift64(a:x, 6))
endfunction
function! s:cmp64(a, b)
let c = s:cmp32(a:a[1], a:b[1])
if c == 0
let c = s:cmp32(a:a[0], a:b[0])
endif
return c
endfunction
function! s:cmp32(a, b)
if (a:a >= 0 && a:b >= 0) || (a:a < 0 && a:b < 0)
return a:a < a:b ? -1 : a:a > a:b ? 1 : 0
else
return a:a < 0 ? 1 : -1
endif
endfunction
function! s:add64(a, b)
let lo = a:a[0] + a:b[0]
let c = (s:cmp32(lo, a:b[0]) < 0)
let hi = a:a[1] + a:b[1] + c
return [lo, hi]
endfunction
function! s:rotateleft64(a, offset)
return s:or64(s:leftshift64(a:a, a:offset), s:rightshift64(a:a, 64 - a:offset))
endfunction
function! s:rotateright64(a, offset)
return s:or64(s:rightshift64(a:a, a:offset), s:leftshift64(a:a, 64 - a:offset))
endfunction
function! s:invert64(x)
return [invert(a:x[0]), invert(a:x[1])]
endfunction
function! s:and64(x, y)
return [and(a:x[0], a:y[0]), and(a:x[1], a:y[1])]
endfunction
function! s:or64(x, y)
return [or(a:x[0], a:y[0]), or(a:x[1], a:y[1])]
endfunction
function! s:xor64(x, y)
return [xor(a:x[0], a:y[0]), xor(a:x[1], a:y[1])]
endfunction
let s:pow2 = [
\ 0x1, 0x2, 0x4, 0x8,
\ 0x10, 0x20, 0x40, 0x80,
\ 0x100, 0x200, 0x400, 0x800,
\ 0x1000, 0x2000, 0x4000, 0x8000,
\ 0x10000, 0x20000, 0x40000, 0x80000,
\ 0x100000, 0x200000, 0x400000, 0x800000,
\ 0x1000000, 0x2000000, 0x4000000, 0x8000000,
\ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
\ ]
function! s:leftshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 : a:a * s:pow2[a:n]
endfunction
function! s:rightshift32(a, n)
return a:n == 0 ? a:a : a:n > 31 ? 0 :
\ a:a < 0
\ ? (a:a - 0x80000000) / s:pow2[a:n] + 0x40000000 / s:pow2[a:n - 1]
\ : a:a / s:pow2[a:n]
endfunction
function! s:leftshift64(x, n)
let lo = s:leftshift32(a:x[0], a:n)
if a:n < 32
let hi = or(s:leftshift32(a:x[1], a:n), s:rightshift32(a:x[0], 32 - a:n))
else
let hi = s:leftshift32(a:x[0], a:n - 32)
endif
return [lo, hi]
endfunction
function! s:rightshift64(x, n)
let hi = s:rightshift32(a:x[1], a:n)
if a:n < 32
let lo = or(s:rightshift32(a:x[0], a:n), s:leftshift32(a:x[1], 32 - a:n))
else
let lo = s:rightshift32(a:x[1], a:n - 32)
endif
return [lo, hi]
endfunction
function! s:bytes_to_uint64_be(x)
let lo = a:x[4] * 0x1000000 + a:x[5] * 0x10000 + a:x[6] * 0x100 + a:x[7]
let hi = a:x[0] * 0x1000000 + a:x[1] * 0x10000 + a:x[2] * 0x100 + a:x[3]
return [lo, hi]
endfunction
function! s:uint64_to_bytes_be(x)
let x0 = and(a:x[0], 0xFF)
let x1 = and(s:rightshift32(a:x[0], 8), 0xFF)
let x2 = and(s:rightshift32(a:x[0], 16), 0xFF)
let x3 = and(s:rightshift32(a:x[0], 24), 0xFF)
let x4 = and(a:x[1], 0xFF)
let x5 = and(s:rightshift32(a:x[1], 8), 0xFF)
let x6 = and(s:rightshift32(a:x[1], 16), 0xFF)
let x7 = and(s:rightshift32(a:x[1], 24), 0xFF)
return [x7, x6, x5, x4, x3, x2, x1, x0]
endfunction
function! s:bytes(seq)
if type(a:seq)
return s:strtobytes(a:seq)
elseif type(a:seq) == type([])
return a:seq
else
throw 'type error'
endif
endfunction
function! s:hextobytes(hex)
return map(split(a:hex, '..\zs'), 'str2nr(v:val, 16)')
endfunction
function! s:bytestohex(bytes)
return join(map(copy(a:bytes), 'printf("%02x", v:val)'), '')
endfunction
function! s:strtobytes(str)
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
endfunction
@ArashPartow
Copy link

A comprehensive list of general purpose hash functions and their implementations can found here:

https://www.partow.net/programming/hashfunctions/index.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment