747 lines
24 KiB
VimL
747 lines
24 KiB
VimL
|
" sha1 digest calculator
|
||
|
" This is a port of rfc3174 sha1 function.
|
||
|
" http://www.ietf.org/rfc/rfc3174.txt
|
||
|
" Last Change: 2010-02-13
|
||
|
" Maintainer: Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com>
|
||
|
" Original Copyright:
|
||
|
" Copyright (C) The Internet Society (2001). All Rights Reserved.
|
||
|
"
|
||
|
" This document and translations of it may be copied and furnished to
|
||
|
" others, and derivative works that comment on or otherwise explain it
|
||
|
" or assist in its implementation may be prepared, copied, published
|
||
|
" and distributed, in whole or in part, without restriction of any
|
||
|
" kind, provided that the above copyright notice and this paragraph are
|
||
|
" included on all such copies and derivative works. However, this
|
||
|
" document itself may not be modified in any way, such as by removing
|
||
|
" the copyright notice or references to the Internet Society or other
|
||
|
" Internet organizations, except as needed for the purpose of
|
||
|
" developing Internet standards in which case the procedures for
|
||
|
" copyrights defined in the Internet Standards process must be
|
||
|
" followed, or as required to translate it into languages other than
|
||
|
" English.
|
||
|
"
|
||
|
" The limited permissions granted above are perpetual and will not be
|
||
|
" revoked by the Internet Society or its successors or assigns.
|
||
|
"
|
||
|
" This document and the information contained herein is provided on an
|
||
|
" "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
|
||
|
" TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
||
|
" BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
|
||
|
" HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
|
||
|
" MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
|
||
|
let s:save_cpo = &cpo
|
||
|
set cpo&vim
|
||
|
|
||
|
function! webapi#sha1#sha1(str)
|
||
|
return s:SHA1Digest(s:str2bytes(a:str))
|
||
|
endfunction
|
||
|
|
||
|
function! webapi#sha1#sha1bin(bin)
|
||
|
return s:SHA1Digest(a:bin)
|
||
|
endfunction
|
||
|
|
||
|
function! webapi#sha1#test()
|
||
|
call s:main()
|
||
|
endfunction
|
||
|
|
||
|
function! s:SHA1Digest(bytes)
|
||
|
let sha = deepcopy(s:SHA1Context, 1)
|
||
|
let Message_Digest = repeat([0], 20)
|
||
|
|
||
|
let err = s:SHA1Reset(sha)
|
||
|
if err
|
||
|
throw printf("SHA1Reset Error %d", err)
|
||
|
endif
|
||
|
|
||
|
let err = s:SHA1Input(sha, a:bytes)
|
||
|
if err
|
||
|
throw printf("SHA1Input Error %d", err)
|
||
|
endif
|
||
|
|
||
|
let err = s:SHA1Result(sha, Message_Digest)
|
||
|
if err
|
||
|
throw printf("SHA1Result Error %d", err)
|
||
|
endif
|
||
|
|
||
|
return join(map(Message_Digest, 'printf("%02x", v:val)'), '')
|
||
|
endfunction
|
||
|
|
||
|
"
|
||
|
" sha1.h
|
||
|
"
|
||
|
" Description:
|
||
|
" This is the header file for code which implements the Secure
|
||
|
" Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
|
||
|
" April 17, 1995.
|
||
|
"
|
||
|
" Many of the variable names in this code, especially the
|
||
|
" single character names, were used because those were the names
|
||
|
" used in the publication.
|
||
|
"
|
||
|
" Please read the file sha1.c for more information.
|
||
|
|
||
|
"
|
||
|
" If you do not have the ISO standard stdint.h header file, then you
|
||
|
" must typdef the following:
|
||
|
" name meaning
|
||
|
" uint32_t unsigned 32 bit integer
|
||
|
" uint8_t unsigned 8 bit integer (i.e., unsigned char)
|
||
|
" int_least16_t integer of >= 16 bits
|
||
|
"
|
||
|
"
|
||
|
|
||
|
" enum
|
||
|
let s:shaSuccess = 0
|
||
|
let s:shaNull = 1 " Null pointer parameter
|
||
|
let s:shaInputTooLong = 2 " input data too long
|
||
|
let s:shaStateError = 3 " called Input after Result
|
||
|
|
||
|
" define
|
||
|
let s:SHA1HashSize = 20
|
||
|
|
||
|
"
|
||
|
" This structure will hold context information for the SHA-1
|
||
|
" hashing operation
|
||
|
"
|
||
|
" struct
|
||
|
let s:SHA1Context = {}
|
||
|
" uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
|
||
|
let s:SHA1Context.Intermediate_Hash = repeat([0], s:SHA1HashSize / 4)
|
||
|
" uint32_t Length_Low; /* Message length in bits */
|
||
|
let s:SHA1Context.Length_Low = 0
|
||
|
" uint32_t Length_High; /* Message length in bits */
|
||
|
let s:SHA1Context.Length_High = 0
|
||
|
" /* Index into message block array */
|
||
|
" int_least16_t Message_Block_Index;
|
||
|
let s:SHA1Context.Message_Block_Index = 0
|
||
|
" uint8_t Message_Block[64]; /* 512-bit message blocks */
|
||
|
let s:SHA1Context.Message_Block = repeat([0], 64)
|
||
|
" int Computed; /* Is the digest computed? */
|
||
|
let s:SHA1Context.Computed = 0
|
||
|
" int Corrupted; /* Is the message digest corrupted? */
|
||
|
let s:SHA1Context.Corrupted = 0
|
||
|
|
||
|
"
|
||
|
" sha1.c
|
||
|
"
|
||
|
" Description:
|
||
|
" This file implements the Secure Hashing Algorithm 1 as
|
||
|
" defined in FIPS PUB 180-1 published April 17, 1995.
|
||
|
"
|
||
|
" The SHA-1, produces a 160-bit message digest for a given
|
||
|
" data stream. It should take about 2**n steps to find a
|
||
|
" message with the same digest as a given message and
|
||
|
" 2**(n/2) to find any two messages with the same digest,
|
||
|
" when n is the digest size in bits. Therefore, this
|
||
|
" algorithm can serve as a means of providing a
|
||
|
" "fingerprint" for a message.
|
||
|
"
|
||
|
" Portability Issues:
|
||
|
" SHA-1 is defined in terms of 32-bit "words". This code
|
||
|
" uses <stdint.h> (included via "sha1.h" to define 32 and 8
|
||
|
" bit unsigned integer types. If your C compiler does not
|
||
|
" support 32 bit unsigned integers, this code is not
|
||
|
" appropriate.
|
||
|
"
|
||
|
" Caveats:
|
||
|
" SHA-1 is designed to work with messages less than 2^64 bits
|
||
|
" long. Although SHA-1 allows a message digest to be generated
|
||
|
" for messages of any number of bits less than 2^64, this
|
||
|
" implementation only works with messages with a length that is
|
||
|
" a multiple of the size of an 8-bit character.
|
||
|
"
|
||
|
"
|
||
|
|
||
|
"
|
||
|
" Define the SHA1 circular left shift macro
|
||
|
"
|
||
|
"#define SHA1CircularShift(bits,word) \
|
||
|
" (((word) << (bits)) | ((word) >> (32-(bits))))
|
||
|
function s:SHA1CircularShift(bits, word)
|
||
|
return s:bitwise_or(s:bitwise_lshift(a:word, a:bits), s:bitwise_rshift(a:word, 32 - a:bits))
|
||
|
endfunction
|
||
|
|
||
|
"
|
||
|
" SHA1Reset
|
||
|
"
|
||
|
" Description:
|
||
|
" This function will initialize the SHA1Context in preparation
|
||
|
" for computing a new SHA1 message digest.
|
||
|
"
|
||
|
" Parameters:
|
||
|
" context: [in/out]
|
||
|
" The context to reset.
|
||
|
"
|
||
|
" Returns:
|
||
|
" sha Error Code.
|
||
|
"
|
||
|
"
|
||
|
" int SHA1Reset(SHA1Context *context)
|
||
|
function s:SHA1Reset(context)
|
||
|
if empty(a:context)
|
||
|
return s:shaNull
|
||
|
endif
|
||
|
|
||
|
let a:context.Length_Low = 0
|
||
|
let a:context.Length_High = 0
|
||
|
let a:context.Message_Block_Index = 0
|
||
|
|
||
|
let a:context.Intermediate_Hash[0] = 0x67452301
|
||
|
let a:context.Intermediate_Hash[1] = 0xEFCDAB89
|
||
|
let a:context.Intermediate_Hash[2] = 0x98BADCFE
|
||
|
let a:context.Intermediate_Hash[3] = 0x10325476
|
||
|
let a:context.Intermediate_Hash[4] = 0xC3D2E1F0
|
||
|
|
||
|
let a:context.Computed = 0
|
||
|
let a:context.Corrupted = 0
|
||
|
|
||
|
return s:shaSuccess
|
||
|
endfunction
|
||
|
|
||
|
"
|
||
|
" SHA1Result
|
||
|
"
|
||
|
" Description:
|
||
|
" This function will return the 160-bit message digest into the
|
||
|
" Message_Digest array provided by the caller.
|
||
|
" NOTE: The first octet of hash is stored in the 0th element,
|
||
|
" the last octet of hash in the 19th element.
|
||
|
"
|
||
|
" Parameters:
|
||
|
" context: [in/out]
|
||
|
" The context to use to calculate the SHA-1 hash.
|
||
|
" Message_Digest: [out]
|
||
|
" Where the digest is returned.
|
||
|
"
|
||
|
" Returns:
|
||
|
" sha Error Code.
|
||
|
"
|
||
|
"
|
||
|
"int SHA1Result( SHA1Context *context,
|
||
|
" uint8_t Message_Digest[SHA1HashSize])
|
||
|
function s:SHA1Result(context, Message_Digest)
|
||
|
if empty(a:context) || empty(a:Message_Digest)
|
||
|
return s:shaNull
|
||
|
endif
|
||
|
|
||
|
if a:context.Corrupted
|
||
|
return a:context.Corrupted
|
||
|
endif
|
||
|
|
||
|
if !a:context.Computed
|
||
|
call s:SHA1PadMessage(a:context)
|
||
|
for i in range(64)
|
||
|
" message may be sensitive, clear it out
|
||
|
let a:context.Message_Block[i] = 0
|
||
|
endfor
|
||
|
let a:context.Length_Low = 0 " and clear length
|
||
|
let a:context.Length_High = 0
|
||
|
let a:context.Computed = 1
|
||
|
endif
|
||
|
|
||
|
for i in range(s:SHA1HashSize)
|
||
|
let a:Message_Digest[i] = s:uint8(
|
||
|
\ s:bitwise_rshift(
|
||
|
\ a:context.Intermediate_Hash[s:bitwise_rshift(i, 2)],
|
||
|
\ 8 * (3 - s:bitwise_and(i, 0x03))
|
||
|
\ )
|
||
|
\ )
|
||
|
endfor
|
||
|
|
||
|
return s:shaSuccess
|
||
|
endfunction
|
||
|
|
||
|
"
|
||
|
" SHA1Input
|
||
|
"
|
||
|
" Description:
|
||
|
" This function accepts an array of octets as the next portion
|
||
|
" of the message.
|
||
|
"
|
||
|
" Parameters:
|
||
|
" context: [in/out]
|
||
|
" The SHA context to update
|
||
|
" message_array: [in]
|
||
|
" An array of characters representing the next portion of
|
||
|
" the message.
|
||
|
" length: [in]
|
||
|
" The length of the message in message_array
|
||
|
"
|
||
|
" Returns:
|
||
|
" sha Error Code.
|
||
|
"
|
||
|
"
|
||
|
"int SHA1Input( SHA1Context *context,
|
||
|
" const uint8_t *message_array,
|
||
|
" unsigned length)
|
||
|
function s:SHA1Input(context, message_array)
|
||
|
if !len(a:message_array)
|
||
|
return s:shaSuccess
|
||
|
endif
|
||
|
|
||
|
if empty(a:context) || empty(a:message_array)
|
||
|
return s:shaNull
|
||
|
endif
|
||
|
|
||
|
if a:context.Computed
|
||
|
let a:context.Corrupted = s:shaStateError
|
||
|
return s:shaStateError
|
||
|
endif
|
||
|
|
||
|
if a:context.Corrupted
|
||
|
return a:context.Corrupted
|
||
|
endif
|
||
|
|
||
|
for x in a:message_array
|
||
|
if a:context.Corrupted
|
||
|
break
|
||
|
endif
|
||
|
let a:context.Message_Block[a:context.Message_Block_Index] = s:bitwise_and(x, 0xFF)
|
||
|
let a:context.Message_Block_Index += 1
|
||
|
|
||
|
let a:context.Length_Low += 8
|
||
|
if a:context.Length_Low == 0
|
||
|
let a:context.Length_High += 1
|
||
|
if a:context.Length_High == 0
|
||
|
" Message is too long
|
||
|
let a:context.Corrupted = 1
|
||
|
endif
|
||
|
endif
|
||
|
|
||
|
if a:context.Message_Block_Index == 64
|
||
|
call s:SHA1ProcessMessageBlock(a:context)
|
||
|
endif
|
||
|
endfor
|
||
|
|
||
|
return s:shaSuccess
|
||
|
endfunction
|
||
|
|
||
|
"
|
||
|
" SHA1ProcessMessageBlock
|
||
|
"
|
||
|
" Description:
|
||
|
" This function will process the next 512 bits of the message
|
||
|
" stored in the Message_Block array.
|
||
|
"
|
||
|
" Parameters:
|
||
|
" None.
|
||
|
"
|
||
|
" Returns:
|
||
|
" Nothing.
|
||
|
"
|
||
|
" Comments:
|
||
|
" Many of the variable names in this code, especially the
|
||
|
" single character names, were used because those were the
|
||
|
" names used in the publication.
|
||
|
"
|
||
|
"
|
||
|
"
|
||
|
" void SHA1ProcessMessageBlock(SHA1Context *context)
|
||
|
function s:SHA1ProcessMessageBlock(context)
|
||
|
" Constants defined in SHA-1
|
||
|
let K = [
|
||
|
\ 0x5A827999,
|
||
|
\ 0x6ED9EBA1,
|
||
|
\ 0x8F1BBCDC,
|
||
|
\ 0xCA62C1D6
|
||
|
\ ]
|
||
|
let t = 0 " Loop counter
|
||
|
let temp = 0 " Temporary word value
|
||
|
let W = repeat([0], 80) " Word sequence
|
||
|
let [A, B, C, D, E] = [0, 0, 0, 0, 0] " Word buffers
|
||
|
|
||
|
"
|
||
|
" Initialize the first 16 words in the array W
|
||
|
"
|
||
|
for t in range(16)
|
||
|
let W[t] = s:bitwise_lshift(a:context.Message_Block[t * 4], 24)
|
||
|
let W[t] = s:bitwise_or(W[t], s:bitwise_lshift(a:context.Message_Block[t * 4 + 1], 16))
|
||
|
let W[t] = s:bitwise_or(W[t], s:bitwise_lshift(a:context.Message_Block[t * 4 + 2], 8))
|
||
|
let W[t] = s:bitwise_or(W[t], a:context.Message_Block[t * 4 + 3])
|
||
|
endfor
|
||
|
|
||
|
for t in range(16, 79)
|
||
|
let W[t] = s:SHA1CircularShift(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 = a:context.Intermediate_Hash[0]
|
||
|
let B = a:context.Intermediate_Hash[1]
|
||
|
let C = a:context.Intermediate_Hash[2]
|
||
|
let D = a:context.Intermediate_Hash[3]
|
||
|
let E = a:context.Intermediate_Hash[4]
|
||
|
|
||
|
for t in range(20)
|
||
|
let temp = s:SHA1CircularShift(5,A) +
|
||
|
\ s:bitwise_or(s:bitwise_and(B, C), s:bitwise_and(s:bitwise_not(B), D)) +
|
||
|
\ E + W[t] + K[0]
|
||
|
let E = D
|
||
|
let D = C
|
||
|
let C = s:SHA1CircularShift(30,B)
|
||
|
let B = A
|
||
|
let A = temp
|
||
|
endfor
|
||
|
|
||
|
for t in range(20, 39)
|
||
|
let temp = s:SHA1CircularShift(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:SHA1CircularShift(30,B)
|
||
|
let B = A
|
||
|
let A = temp
|
||
|
endfor
|
||
|
|
||
|
for t in range(40, 59)
|
||
|
let temp = s:SHA1CircularShift(5,A) +
|
||
|
\ 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
|
||
|
let C = s:SHA1CircularShift(30,B)
|
||
|
let B = A
|
||
|
let A = temp
|
||
|
endfor
|
||
|
|
||
|
for t in range(60, 79)
|
||
|
let temp = s:SHA1CircularShift(5,A) +
|
||
|
\ s:bitwise_xor(s:bitwise_xor(B, C), D) + E + W[t] + K[3]
|
||
|
let E = D
|
||
|
let D = C
|
||
|
let C = s:SHA1CircularShift(30,B)
|
||
|
let B = A
|
||
|
let A = temp
|
||
|
endfor
|
||
|
|
||
|
let a:context.Intermediate_Hash[0] += A
|
||
|
let a:context.Intermediate_Hash[1] += B
|
||
|
let a:context.Intermediate_Hash[2] += C
|
||
|
let a:context.Intermediate_Hash[3] += D
|
||
|
let a:context.Intermediate_Hash[4] += E
|
||
|
|
||
|
let a:context.Message_Block_Index = 0
|
||
|
endfunction
|
||
|
|
||
|
|
||
|
"
|
||
|
" SHA1PadMessage
|
||
|
"
|
||
|
" Description:
|
||
|
" According to the standard, the message must be padded to an even
|
||
|
" 512 bits. The first padding bit must be a '1'. The last 64
|
||
|
" bits represent the length of the original message. All bits in
|
||
|
" between should be 0. This function will pad the message
|
||
|
" according to those rules by filling the Message_Block array
|
||
|
" accordingly. It will also call the ProcessMessageBlock function
|
||
|
" provided appropriately. When it returns, it can be assumed that
|
||
|
" the message digest has been computed.
|
||
|
"
|
||
|
" Parameters:
|
||
|
" context: [in/out]
|
||
|
" The context to pad
|
||
|
" ProcessMessageBlock: [in]
|
||
|
" The appropriate SHA*ProcessMessageBlock function
|
||
|
" Returns:
|
||
|
" Nothing.
|
||
|
"
|
||
|
"
|
||
|
" void SHA1PadMessage(SHA1Context *context)
|
||
|
function s:SHA1PadMessage(context)
|
||
|
"
|
||
|
" Check to see if the current message block is too small to hold
|
||
|
" the initial padding bits and length. If so, we will pad the
|
||
|
" block, process it, and then continue padding into a second
|
||
|
" block.
|
||
|
"
|
||
|
if a:context.Message_Block_Index > 55
|
||
|
let a:context.Message_Block[a:context.Message_Block_Index] = 0x80
|
||
|
let a:context.Message_Block_Index += 1
|
||
|
while a:context.Message_Block_Index < 64
|
||
|
let a:context.Message_Block[a:context.Message_Block_Index] = 0
|
||
|
let a:context.Message_Block_Index += 1
|
||
|
endwhile
|
||
|
|
||
|
call s:SHA1ProcessMessageBlock(a:context)
|
||
|
|
||
|
while a:context.Message_Block_Index < 56
|
||
|
let a:context.Message_Block[a:context.Message_Block_Index] = 0
|
||
|
let a:context.Message_Block_Index += 1
|
||
|
endwhile
|
||
|
else
|
||
|
let a:context.Message_Block[a:context.Message_Block_Index] = 0x80
|
||
|
let a:context.Message_Block_Index += 1
|
||
|
while a:context.Message_Block_Index < 56
|
||
|
let a:context.Message_Block[a:context.Message_Block_Index] = 0
|
||
|
let a:context.Message_Block_Index += 1
|
||
|
endwhile
|
||
|
endif
|
||
|
|
||
|
"
|
||
|
" Store the message length as the last 8 octets
|
||
|
"
|
||
|
let a:context.Message_Block[56] = s:uint8(s:bitwise_rshift(a:context.Length_High, 24))
|
||
|
let a:context.Message_Block[57] = s:uint8(s:bitwise_rshift(a:context.Length_High, 16))
|
||
|
let a:context.Message_Block[58] = s:uint8(s:bitwise_rshift(a:context.Length_High, 8))
|
||
|
let a:context.Message_Block[59] = s:uint8(a:context.Length_High)
|
||
|
let a:context.Message_Block[60] = s:uint8(s:bitwise_rshift(a:context.Length_Low, 24))
|
||
|
let a:context.Message_Block[61] = s:uint8(s:bitwise_rshift(a:context.Length_Low, 16))
|
||
|
let a:context.Message_Block[62] = s:uint8(s:bitwise_rshift(a:context.Length_Low, 8))
|
||
|
let a:context.Message_Block[63] = s:uint8(a:context.Length_Low)
|
||
|
|
||
|
call s:SHA1ProcessMessageBlock(a:context)
|
||
|
endfunction
|
||
|
|
||
|
"
|
||
|
" sha1test.c
|
||
|
"
|
||
|
" Description:
|
||
|
" This file will exercise the SHA-1 code performing the three
|
||
|
" tests documented in FIPS PUB 180-1 plus one which calls
|
||
|
" SHA1Input with an exact multiple of 512 bits, plus a few
|
||
|
" error test checks.
|
||
|
"
|
||
|
" Portability Issues:
|
||
|
" None.
|
||
|
"
|
||
|
"
|
||
|
|
||
|
"
|
||
|
" Define patterns for testing
|
||
|
"
|
||
|
let s:TEST1 = "abc"
|
||
|
let s:TEST2a = "abcdbcdecdefdefgefghfghighijhi"
|
||
|
let s:TEST2b = "jkijkljklmklmnlmnomnopnopq"
|
||
|
let s:TEST2 = s:TEST2a . s:TEST2b
|
||
|
let s:TEST3 = "a"
|
||
|
let s:TEST4a = "01234567012345670123456701234567"
|
||
|
let s:TEST4b = "01234567012345670123456701234567"
|
||
|
" an exact multiple of 512 bits
|
||
|
let s:TEST4 = s:TEST4a . s:TEST4b
|
||
|
let s:testarray = [
|
||
|
\ s:TEST1,
|
||
|
\ s:TEST2,
|
||
|
\ s:TEST3,
|
||
|
\ s:TEST4
|
||
|
\ ]
|
||
|
let s:repeatcount = [1, 1, 1000000, 10]
|
||
|
let s:resultarray = [
|
||
|
\ "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D",
|
||
|
\ "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1",
|
||
|
\ "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F",
|
||
|
\ "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52"
|
||
|
\ ]
|
||
|
|
||
|
function s:main()
|
||
|
let sha = deepcopy(s:SHA1Context, 1)
|
||
|
let Message_Digest = repeat([0], 20)
|
||
|
|
||
|
"
|
||
|
" Perform SHA-1 tests
|
||
|
"
|
||
|
for j in range(len(s:testarray))
|
||
|
if j == 2
|
||
|
echo "Test 3 will take about 1 hour. Press CTRL-C to skip."
|
||
|
endif
|
||
|
echo ""
|
||
|
echo printf("Test %d: %d, '%s'",
|
||
|
\ j+1,
|
||
|
\ s:repeatcount[j],
|
||
|
\ s:testarray[j])
|
||
|
|
||
|
let err = s:SHA1Reset(sha)
|
||
|
if err
|
||
|
echo printf("SHA1Reset Error %d.", err )
|
||
|
break " out of for j loop
|
||
|
endif
|
||
|
|
||
|
try
|
||
|
for i in range(s:repeatcount[j])
|
||
|
let err = s:SHA1Input(sha, s:str2bytes(s:testarray[j]))
|
||
|
if err
|
||
|
echo printf("SHA1Input Error %d.", err )
|
||
|
break " out of for i loop */
|
||
|
endif
|
||
|
endfor
|
||
|
catch /^Vim:Interrupt$/
|
||
|
echo "Skip ..."
|
||
|
while getchar(0) | endwhile
|
||
|
continue
|
||
|
endtry
|
||
|
|
||
|
let err = s:SHA1Result(sha, Message_Digest)
|
||
|
if err
|
||
|
echo printf("SHA1Result Error %d, could not compute message digest.", err)
|
||
|
else
|
||
|
echo "\t"
|
||
|
for i in range(20)
|
||
|
echon printf("%02X ", Message_Digest[i])
|
||
|
endfor
|
||
|
echo ""
|
||
|
endif
|
||
|
echo "Should match:"
|
||
|
echo printf("\t%s", s:resultarray[j])
|
||
|
endfor
|
||
|
|
||
|
" Test some error returns
|
||
|
let err = s:SHA1Input(sha, s:str2bytes(s:testarray[1][0:0]))
|
||
|
echo printf("\nError %d. Should be %d.", err, s:shaStateError)
|
||
|
let err = s:SHA1Reset(0)
|
||
|
echo printf("\nError %d. Should be %d.", err, s:shaNull)
|
||
|
endfunction
|
||
|
|
||
|
|
||
|
|
||
|
"---------------------------------------------------------------------
|
||
|
" misc
|
||
|
function! s:str2bytes(str)
|
||
|
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
|
||
|
endfunction
|
||
|
|
||
|
function! s:cmp(a, b)
|
||
|
let a = printf("%08x", a:a)
|
||
|
let b = printf("%08x", a:b)
|
||
|
return a < b ? -1 : a > b ? 1 : 0
|
||
|
endfunction
|
||
|
|
||
|
function! s:uint8(n)
|
||
|
return s:bitwise_and(a:n, 0xFF)
|
||
|
endfunction
|
||
|
|
||
|
let s:k = [
|
||
|
\ 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,
|
||
|
\ ]
|
||
|
|
||
|
let s:and = [
|
||
|
\ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
|
||
|
\ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1],
|
||
|
\ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2],
|
||
|
\ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3],
|
||
|
\ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4],
|
||
|
\ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5],
|
||
|
\ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6],
|
||
|
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
|
||
|
\ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8],
|
||
|
\ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9],
|
||
|
\ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x8, 0x8, 0xA, 0xA, 0x8, 0x8, 0xA, 0xA],
|
||
|
\ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB, 0x8, 0x9, 0xA, 0xB],
|
||
|
\ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0xC, 0xC, 0xC, 0xC],
|
||
|
\ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x8, 0x9, 0x8, 0x9, 0xC, 0xD, 0xC, 0xD],
|
||
|
\ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x8, 0x8, 0xA, 0xA, 0xC, 0xC, 0xE, 0xE],
|
||
|
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF]
|
||
|
\ ]
|
||
|
|
||
|
let s:or = [
|
||
|
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||
|
\ [0x1, 0x1, 0x3, 0x3, 0x5, 0x5, 0x7, 0x7, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF],
|
||
|
\ [0x2, 0x3, 0x2, 0x3, 0x6, 0x7, 0x6, 0x7, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF],
|
||
|
\ [0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF],
|
||
|
\ [0x4, 0x5, 0x6, 0x7, 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF],
|
||
|
\ [0x5, 0x5, 0x7, 0x7, 0x5, 0x5, 0x7, 0x7, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF],
|
||
|
\ [0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF],
|
||
|
\ [0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF],
|
||
|
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||
|
\ [0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF],
|
||
|
\ [0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF],
|
||
|
\ [0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF],
|
||
|
\ [0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF],
|
||
|
\ [0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF],
|
||
|
\ [0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF],
|
||
|
\ [0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF]
|
||
|
\ ]
|
||
|
|
||
|
let s:xor = [
|
||
|
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||
|
\ [0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE],
|
||
|
\ [0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD],
|
||
|
\ [0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC],
|
||
|
\ [0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB],
|
||
|
\ [0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA],
|
||
|
\ [0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9],
|
||
|
\ [0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8],
|
||
|
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
|
||
|
\ [0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6],
|
||
|
\ [0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5],
|
||
|
\ [0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4],
|
||
|
\ [0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3],
|
||
|
\ [0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2],
|
||
|
\ [0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1],
|
||
|
\ [0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0]
|
||
|
\ ]
|
||
|
|
||
|
function! s:bitwise_lshift(a, n)
|
||
|
return a:a * s:k[a:n]
|
||
|
endfunction
|
||
|
|
||
|
function! s:bitwise_rshift(a, n)
|
||
|
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||
|
let a = a / s:k[a:n]
|
||
|
if a:a < 0
|
||
|
let a += 0x40000000 / s:k[a:n - 1]
|
||
|
endif
|
||
|
return a
|
||
|
endfunction
|
||
|
|
||
|
function! s:bitwise_not(a)
|
||
|
return -a:a - 1
|
||
|
endfunction
|
||
|
|
||
|
function! s:bitwise_and(a, b)
|
||
|
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||
|
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||
|
let r = 0
|
||
|
let n = 1
|
||
|
while a && b
|
||
|
let r += s:and[a % 0x10][b % 0x10] * n
|
||
|
let a = a / 0x10
|
||
|
let b = b / 0x10
|
||
|
let n = n * 0x10
|
||
|
endwhile
|
||
|
if (a:a < 0) && (a:b < 0)
|
||
|
let r += 0x80000000
|
||
|
endif
|
||
|
return r
|
||
|
endfunction
|
||
|
|
||
|
function! s:bitwise_or(a, b)
|
||
|
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||
|
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||
|
let r = 0
|
||
|
let n = 1
|
||
|
while a || b
|
||
|
let r += s:or[a % 0x10][b % 0x10] * n
|
||
|
let a = a / 0x10
|
||
|
let b = b / 0x10
|
||
|
let n = n * 0x10
|
||
|
endwhile
|
||
|
if (a:a < 0) || (a:b < 0)
|
||
|
let r += 0x80000000
|
||
|
endif
|
||
|
return r
|
||
|
endfunction
|
||
|
|
||
|
function! s:bitwise_xor(a, b)
|
||
|
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||
|
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||
|
let r = 0
|
||
|
let n = 1
|
||
|
while a || b
|
||
|
let r += s:xor[a % 0x10][b % 0x10] * n
|
||
|
let a = a / 0x10
|
||
|
let b = b / 0x10
|
||
|
let n = n * 0x10
|
||
|
endwhile
|
||
|
if (a:a < 0) != (a:b < 0)
|
||
|
let r += 0x80000000
|
||
|
endif
|
||
|
return r
|
||
|
endfunction
|
||
|
|
||
|
let &cpo = s:save_cpo
|
||
|
unlet s:save_cpo
|