diff --git a/autoload/vital/__vital__/Hash/MD5.vim b/autoload/vital/__vital__/Hash/MD5.vim index 0e57dbf80..644be170a 100644 --- a/autoload/vital/__vital__/Hash/MD5.vim +++ b/autoload/vital/__vital__/Hash/MD5.vim @@ -3,13 +3,19 @@ let s:save_cpo = &cpo set cpo&vim +function! s:_vital_created(module) abort + let a:module.name = 'MD5' + let a:module.hash_length = 128 +endfunction + function! s:_vital_loaded(V) abort let s:V = a:V - let s:bitwise = s:V.import('Bitwise') + let s:Bitwise = s:V.import('Bitwise') + let s:ByteArray = s:V.import('Data.List.Byte') endfunction function! s:_vital_depends() abort - return ['Bitwise'] + return ['Bitwise', 'Data.List.Byte'] endfunction let s:shift = [ @@ -39,16 +45,16 @@ let s:table = [ \ ] function! s:sum(data) abort - let bytes = s:_str2bytes(a:data) + let bytes = s:ByteArray.from_string(a:data) return s:sum_raw(bytes) endfunction function! s:sum_raw(bytes) abort - return s:_bytes2binstr(s:digest_raw(a:bytes)) + return s:ByteArray.to_hexstring(s:digest_raw(a:bytes)) endfunction function! s:digest(data) abort - let bytes = s:_str2bytes(a:data) + let bytes = s:ByteArray.from_string(a:data) return s:digest_raw(bytes) endfunction @@ -67,16 +73,16 @@ function! s:digest_raw(bytes) abort if has('num64') - call extend(l:padded, s:_int2bytes(64, l:orig_len)) + call extend(l:padded, s:ByteArray.endian_convert(s:ByteArray.from_int(l:orig_len, 64))) else - call extend(l:padded, s:_int2bytes(32, l:orig_len)) + call extend(l:padded, s:ByteArray.endian_convert(s:ByteArray.from_int(l:orig_len, 32))) call extend(l:padded, [0, 0, 0, 0]) endif for l:chunk_i in range(0, len(l:padded)-1, 64) let l:chunk = l:padded[l:chunk_i : l:chunk_i + 63] - let l:M = map(range(16), 's:_bytes2int32(l:chunk[(v:val*4):(v:val*4)+3])') + let l:M = map(range(16), {i,v -> s:ByteArray.to_int(s:ByteArray.endian_convert(l:chunk[(i*4) : (i*4)+3]))}) let l:A = l:a0 let l:B = l:b0 let l:C = l:c0 @@ -86,16 +92,16 @@ function! s:digest_raw(bytes) abort let l:F = 0 let l:g = 0 if 0 <= l:i && l:i <= 15 - let l:F = s:bitwise.or(s:bitwise.and(l:B, l:C), s:bitwise.and(s:bitwise.invert(l:B), l:D)) + let l:F = s:Bitwise.or(s:Bitwise.and(l:B, l:C), s:Bitwise.and(s:Bitwise.invert(l:B), l:D)) let l:g = l:i elseif 16 <= l:i && l:i <= 31 - let l:F = s:bitwise.or(s:bitwise.and(l:B, l:D), s:bitwise.and(s:bitwise.invert(l:D), l:C)) + let l:F = s:Bitwise.or(s:Bitwise.and(l:B, l:D), s:Bitwise.and(s:Bitwise.invert(l:D), l:C)) let l:g = fmod((5 * l:i) + 1, 16) elseif 32 <= l:i && l:i <= 47 - let l:F = s:bitwise.xor(l:B, s:bitwise.xor(l:C, l:D)) + let l:F = s:Bitwise.xor(l:B, s:Bitwise.xor(l:C, l:D)) let l:g = fmod((3 * l:i) + 5, 16) elseif 48 <= l:i && l:i <= 63 - let l:F = s:bitwise.xor(l:C, s:bitwise.or(l:B, s:bitwise.invert(l:D))) + let l:F = s:Bitwise.xor(l:C, s:Bitwise.or(l:B, s:Bitwise.invert(l:D))) let l:g = fmod(7 * l:i, 16) endif @@ -103,7 +109,7 @@ function! s:digest_raw(bytes) abort let l:A = l:D let l:D = l:C let l:C = l:B - let l:B = l:B + s:_leftrotate(l:F, s:shift[l:i]) + let l:B = l:B + s:Bitwise.rotate32l(l:F, s:shift[l:i]) endfor let l:a0 = l:a0 + l:A @@ -113,38 +119,14 @@ function! s:digest_raw(bytes) abort endfor let l:bytes = [] - call extend(l:bytes, s:_int2bytes(32, l:a0)) - call extend(l:bytes, s:_int2bytes(32, l:b0)) - call extend(l:bytes, s:_int2bytes(32, l:c0)) - call extend(l:bytes, s:_int2bytes(32, l:d0)) + call extend(l:bytes, s:ByteArray.endian_convert(s:ByteArray.from_int(l:a0, 32))) + call extend(l:bytes, s:ByteArray.endian_convert(s:ByteArray.from_int(l:b0, 32))) + call extend(l:bytes, s:ByteArray.endian_convert(s:ByteArray.from_int(l:c0, 32))) + call extend(l:bytes, s:ByteArray.endian_convert(s:ByteArray.from_int(l:d0, 32))) return l:bytes endfunction -function! s:_leftrotate(x, c) abort - let l:x = s:bitwise.and(a:x, 0xFFFFFFFF) - return s:bitwise.and(s:bitwise.or(s:bitwise.lshift(l:x, a:c), s:bitwise.rshift(l:x, (32-a:c))), 0xFFFFFFFF) -endfunction - -function! s:_bytes2binstr(bytes) abort - return join(map(copy(a:bytes), 'printf(''%02x'', v:val)'), '') -endfunction - -function! s:_str2bytes(str) abort - return map(range(len(a:str)), 'char2nr(a:str[v:val])') -endfunction - -function! s:_int2bytes(bits, int) abort - return map(range(a:bits / 8), 's:bitwise.and(s:bitwise.rshift(a:int, v:val * 8), 0xff)') -endfunction - -function! s:_bytes2int32(bytes) abort - return s:bitwise.or(s:bitwise.lshift(a:bytes[3], 24), - \ s:bitwise.or(s:bitwise.lshift(a:bytes[2], 16), - \ s:bitwise.or(s:bitwise.lshift(a:bytes[1], 8), - \ a:bytes[0]))) -endfunction - let &cpo = s:save_cpo unlet s:save_cpo diff --git a/autoload/vital/__vital__/Hash/SHA1.vim b/autoload/vital/__vital__/Hash/SHA1.vim index ab05e050e..09066cd61 100644 --- a/autoload/vital/__vital__/Hash/SHA1.vim +++ b/autoload/vital/__vital__/Hash/SHA1.vim @@ -8,26 +8,32 @@ let s:save_cpo = &cpo set cpo&vim +function! s:_vital_created(module) abort + let a:module.name = 'SHA1' + let a:module.hash_length = s:sha1hashsize * 8 " 160 +endfunction + function! s:_vital_loaded(V) abort let s:V = a:V - let s:bitwise = s:V.import('Bitwise') + let s:Bitwise = s:V.import('Bitwise') + let s:ByteArray = s:V.import('Data.List.Byte') endfunction function! s:_vital_depends() abort - return ['Bitwise'] + return ['Bitwise', 'Data.List.Byte'] endfunction function! s:sum(data) abort - let bytes = s:_str2bytes(a:data) + let bytes = s:ByteArray.from_string(a:data) return s:sum_raw(bytes) endfunction function! s:sum_raw(bytes) abort - return s:_bytes2binstr(s:digest_raw(a:bytes)) + return s:ByteArray.to_hexstring(s:digest_raw(a:bytes)) endfunction function! s:digest(data) abort - let bytes = s:_str2bytes(a:data) + let bytes = s:ByteArray.from_string(a:data) return s:digest_raw(bytes) endfunction @@ -77,7 +83,7 @@ let s:sha1context = { \} function! s:_sha1circular_shift(bits, word) abort - return s:bitwise.or(s:bitwise.lshift32(a:word, a:bits), s:bitwise.rshift32(a:word, 32 - a:bits)) + return s:Bitwise.rotate32l(a:word, a:bits) endfunction function! s:sha1context.init() dict abort @@ -112,10 +118,10 @@ function! s:sha1context.result(digest) dict abort endif for i in range(s:sha1hashsize) - let a:digest[i] = s:_uint8( - \ s:bitwise.rshift32( - \ self.intermediatehash[s:bitwise.rshift32(i, 2)], - \ 8 * (3 - s:bitwise.and(i, 0x03)) + let a:digest[i] = s:Bitwise.uint8( + \ s:Bitwise.rshift32( + \ self.intermediatehash[s:Bitwise.rshift32(i, 2)], + \ 8 * (3 - s:Bitwise.and(i, 0x03)) \ ) \ ) endfor @@ -144,7 +150,7 @@ function! s:sha1context.input(bytes) dict abort if self.Corrupted break endif - call self.messageblock.push(s:_uint8(x)) + call self.messageblock.push(s:Bitwise.uint8(x)) if self.messageblock.index == s:sha1blocksize call self.process() @@ -171,14 +177,14 @@ function! s:sha1context.process() dict abort " Initialize the first 16 words in the array W " for t in range(16) - let W[t] = s:bitwise.lshift32(self.messageblock.data[t * 4], 24) - let W[t] = s:bitwise.or(W[t], s:bitwise.lshift32(self.messageblock.data[t * 4 + 1], 16)) - let W[t] = s:bitwise.or(W[t], s:bitwise.lshift32(self.messageblock.data[t * 4 + 2], 8)) - let W[t] = s:bitwise.or(W[t], self.messageblock.data[t * 4 + 3]) + let W[t] = s:Bitwise.lshift32(self.messageblock.data[t * 4], 24) + let W[t] = s:Bitwise.or(W[t], s:Bitwise.lshift32(self.messageblock.data[t * 4 + 1], 16)) + let W[t] = s:Bitwise.or(W[t], s:Bitwise.lshift32(self.messageblock.data[t * 4 + 2], 8)) + let W[t] = s:Bitwise.or(W[t], self.messageblock.data[t * 4 + 3]) endfor for t in range(16, 79) - let W[t] = s:_sha1circular_shift(1, s:bitwise.xor(s:bitwise.xor(s:bitwise.xor(W[t-3], W[t-8]), W[t-14]), W[t-16])) + let W[t] = s:_sha1circular_shift(1, s:Bitwise.xor(s:Bitwise.xor(s:Bitwise.xor(W[t-3], W[t-8]), W[t-14]), W[t-16])) endfor let A = self.intermediatehash[0] @@ -189,7 +195,7 @@ function! s:sha1context.process() dict abort for t in range(20) let temp = s:_sha1circular_shift(5,A) + - \ s:bitwise.or(s:bitwise.and(B, C), s:bitwise.and(s:bitwise.invert(B), D)) + + \ s:Bitwise.or(s:Bitwise.and(B, C), s:Bitwise.and(s:Bitwise.invert(B), D)) + \ E + W[t] + K[0] let E = D let D = C @@ -199,7 +205,7 @@ function! s:sha1context.process() dict abort endfor for t in range(20, 39) - let temp = s:_sha1circular_shift(5,A) + s:bitwise.xor(s:bitwise.xor(B, C), D) + E + W[t] + K[1] + let temp = s:_sha1circular_shift(5,A) + s:Bitwise.xor(s:Bitwise.xor(B, C), D) + E + W[t] + K[1] let E = D let D = C let C = s:_sha1circular_shift(30,B) @@ -209,7 +215,7 @@ function! s:sha1context.process() dict abort for t in range(40, 59) let temp = s:_sha1circular_shift(5,A) + - \ s:bitwise.or(s:bitwise.or(s:bitwise.and(B, C), s:bitwise.and(B, D)), s:bitwise.and(C, D)) + + \ s:Bitwise.or(s:Bitwise.or(s:Bitwise.and(B, C), s:Bitwise.and(B, D)), s:Bitwise.and(C, D)) + \ E + W[t] + K[2] let E = D let D = C @@ -220,7 +226,7 @@ function! s:sha1context.process() dict abort for t in range(60, 79) let temp = s:_sha1circular_shift(5,A) + - \ s:bitwise.xor(s:bitwise.xor(B, C), D) + E + W[t] + K[3] + \ s:Bitwise.xor(s:Bitwise.xor(B, C), D) + E + W[t] + K[3] let E = D let D = C let C = s:_sha1circular_shift(30,B) @@ -266,14 +272,14 @@ function! s:sha1context.padding() dict abort " Store the message length as the last 8 octets " " as data[-8]..data[-1] - let self.messageblock.data[56] = s:_uint8(s:bitwise.rshift32(self.length.high, 24)) - let self.messageblock.data[57] = s:_uint8(s:bitwise.rshift32(self.length.high, 16)) - let self.messageblock.data[58] = s:_uint8(s:bitwise.rshift32(self.length.high, 8)) - let self.messageblock.data[59] = s:_uint8( self.length.high ) - let self.messageblock.data[60] = s:_uint8(s:bitwise.rshift32(self.length.low , 24)) - let self.messageblock.data[61] = s:_uint8(s:bitwise.rshift32(self.length.low , 16)) - let self.messageblock.data[62] = s:_uint8(s:bitwise.rshift32(self.length.low , 8)) - let self.messageblock.data[63] = s:_uint8( self.length.low ) + let self.messageblock.data[56] = s:Bitwise.uint8(s:Bitwise.rshift32(self.length.high, 24)) + let self.messageblock.data[57] = s:Bitwise.uint8(s:Bitwise.rshift32(self.length.high, 16)) + let self.messageblock.data[58] = s:Bitwise.uint8(s:Bitwise.rshift32(self.length.high, 8)) + let self.messageblock.data[59] = s:Bitwise.uint8( self.length.high ) + let self.messageblock.data[60] = s:Bitwise.uint8(s:Bitwise.rshift32(self.length.low , 24)) + let self.messageblock.data[61] = s:Bitwise.uint8(s:Bitwise.rshift32(self.length.low , 16)) + let self.messageblock.data[62] = s:Bitwise.uint8(s:Bitwise.rshift32(self.length.low , 8)) + let self.messageblock.data[63] = s:Bitwise.uint8( self.length.low ) call self.process() endfunction @@ -305,12 +311,12 @@ function! s:sha1context.length.sizeset(data) dict abort " 3.b high shift = 0x0000000l >> (32 - 3) " endif " 32/64bit work use shift - let self.high = s:_uint32(s:bitwise.rshift(len(a:data), 32 - 3)) - let self.low = s:_uint32(s:bitwise.lshift(len(a:data), 3)) + let self.high = s:Bitwise.uint32(s:Bitwise.rshift(len(a:data), 32 - 3)) + let self.low = s:Bitwise.uint32(s:Bitwise.lshift(len(a:data), 3)) " SHA1 2^64 - 1 overflow check - " 0xh0000000 is not 0, then overflow it(byte data are Vim List;it can contain 2^64 - 1 item) - if (has('num64') && (0 != s:_uint32(s:bitwise.rshift(len(a:data), 32 + (32 - 3))))) + " 0xh0000000 is not 0, then overflow it(byte data are Vim List;it can contains 2^64 - 1 item) + if (has('num64') && (0 != s:Bitwise.uint32(s:Bitwise.rshift(len(a:data), 32 + (32 - 3))))) let self.high = 0 let self.low = 0 return s:input_long @@ -318,25 +324,6 @@ function! s:sha1context.length.sizeset(data) dict abort return s:success endfunction -"--------------------------------------------------------------------- -" misc - -function! s:_uint8(n) abort - return s:bitwise.and(a:n, 0xFF) -endfunction - -function! s:_uint32(n) abort - return s:bitwise.and(a:n, 0xFFFFFFFF) -endfunction - -function! s:_str2bytes(str) abort - return map(range(len(a:str)), 'char2nr(a:str[v:val])') -endfunction - -function! s:_bytes2binstr(bytes) abort - return join(map(copy(a:bytes), 'printf(''%02x'', v:val)'), '') -endfunction - let &cpo = s:save_cpo unlet s:save_cpo diff --git a/test/Hash/MD5.vim b/test/Hash/MD5.vim index 5b89ac7ee..daf458c2a 100644 --- a/test/Hash/MD5.vim +++ b/test/Hash/MD5.vim @@ -9,6 +9,11 @@ function! s:suite.after() unlet! s:MD5 endfunction +function! s:suite.prop() abort + call s:assert.is_string(s:MD5.name) + call s:assert.is_number(s:MD5.hash_length) +endfunction + function! s:suite.encode() abort call s:assert.equal(s:MD5.sum(''), 'd41d8cd98f00b204e9800998ecf8427e') call s:assert.equal(s:MD5.sum('a'), '0cc175b9c0f1b6a831c399e269772661') diff --git a/test/Hash/SHA1.vim b/test/Hash/SHA1.vim index 75ca0b2ef..1c0dd4412 100644 --- a/test/Hash/SHA1.vim +++ b/test/Hash/SHA1.vim @@ -9,6 +9,11 @@ function! s:suite.after() unlet! s:SHA1 endfunction +function! s:suite.prop() abort + call s:assert.is_string(s:SHA1.name) + call s:assert.is_number(s:SHA1.hash_length) +endfunction + function! s:suite.encode() abort call s:assert.equal(s:SHA1.sum(''), 'da39a3ee5e6b4b0d3255bfef95601890afd80709') call s:assert.equal(s:SHA1.sum('a'), '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8') @@ -36,10 +41,10 @@ function! s:suite.encode() abort \ ] " original result " let s:resultarray = [ - " \ 'a9993e364706816aba3e25717850c26c9cd0d89d", - " \ '84983e441c3bd26ebaae4aa1f95129e5e54670f1", - " \ '34aa973cd4c4daa4f61eeb2bdbad27316534016f", - " \ 'dea356a2cddd90c7a7ecedc5ebb563934f460452" + " \ 'a9993e364706816aba3e25717850c26c9cd0d89d', + " \ '84983e441c3bd26ebaae4aa1f95129e5e54670f1', + " \ '34aa973cd4c4daa4f61eeb2bdbad27316534016f', + " \ 'dea356a2cddd90c7a7ecedc5ebb563934f460452' " \ ] " other SHA1 test site generate result