-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsha1.rb
131 lines (108 loc) · 3.49 KB
/
sha1.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# A pure ruby implementation of SHA1
# by Alex Ross (http://alex.rosiba.com)
# This SHA1 implementation is FREE. No warranty, copyright, or license. Just don't hurt yourself.
module SHA1
IV = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
def SHA1.circular_shift(bits,word)
0xFFFFFFFF & (((word) << (bits)) | ((word) >> (32-(bits))))
end
def SHA1.compress(words, chain)
constants = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6]
16.upto(79) do |t|
words[t] = circular_shift(1,words[t-3] ^ words[t-8] ^ words[t-14] ^ words[t-16])
end
aa = chain[0]
bb = chain[1]
cc = chain[2]
dd = chain[3]
ee = chain[4]
0.upto(19) do |t|
tt = 0xFFFFFFFF & (circular_shift(5,aa) + ((bb & cc) | ((~bb) & dd)) + ee + words[t] + constants[0])
ee = dd
dd = cc
cc = circular_shift(30,bb)
bb = aa
aa = tt
end
20.upto(39) do |t|
tt = 0xFFFFFFFF & (circular_shift(5,aa) + (bb ^ cc ^ dd) + ee + words[t] + constants[1])
ee = dd
dd = cc
cc = circular_shift(30,bb)
bb = aa
aa = tt
end
40.upto(59) do |t|
tt = 0xFFFFFFFF & (circular_shift(5,aa) + ((bb & cc) | (bb & dd) | (cc & dd)) + ee + words[t] + constants[2])
ee = dd
dd = cc
cc = circular_shift(30,bb)
bb = aa
aa = tt
end
60.upto(79) do |t|
tt = 0xFFFFFFFF & (circular_shift(5,aa) + (bb ^ cc ^ dd) + ee + words[t] + constants[3])
ee = dd
dd = cc
cc = circular_shift(30,bb)
bb = aa
aa = tt
end
return [0xFFFFFFFF & (chain[0] + aa),
0xFFFFFFFF & (chain[1] + bb),
0xFFFFFFFF & (chain[2] + cc),
0xFFFFFFFF & (chain[3] + dd),
0xFFFFFFFF & (chain[4] + ee)]
end
def SHA1.hexdigest(message)
fill = "\x00"*(64 - (message.length+9)%64) # should probably first be one 1 according to specifications
length = "\x00" * 4 + [message.length*8].pack("N*") # four zero bytes + four bytes where message length is written in bits
# the following call sometimes returns:
# incompatible character encodings: UTF-8 and ASCII-8BIT
words = (message.force_encoding('UTF-8') + "\x80" + fill + length.force_encoding('UTF-8')).unpack("N*")
#words = (message.force_encoding('UTF-8') + "\x80" + fill).unpack("N*") # ascii-8bit, utf-8
#words = (fill + "\x80" + message).unpack("N*")
#words = (message).unpack("N*")
#puts words.join(",")
#s = ("\x80" + fill).unpack("N*")
#for i in s
# words.push(i)
#end
#words.push(0)
#words.push(message.length*8)
chain = IV
0.upto(words.length/16-1) do |t|
#puts words[t*16,16].join(",")
chain = compress(words[t*16,16],chain)
end
a = chain.map{|c| "%08x"%c}.join("")
a
end
end
def test_sha1
# Tests from http://www.ietf.org/rfc/rfc3174.txt
tests=[
"abc",
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
# really huge string
"a"*1000000,
# exactly multiple of 512 bits
"0123456701234567012345670123456701234567012345670123456701234567"*10
]
known = [
"a9993e364706816aba3e25717850c26c9cd0d89d",
"84983e441c3bd26ebaae4aa1f95129e5e54670f1",
"34aa973cd4c4daa4f61eeb2bdbad27316534016f",
"dea356a2cddd90c7a7ecedc5ebb563934f460452"
]
0.upto(3) do |i|
sha1 = SHA1.hexdigest(tests[i])
raise "FAILED" if sha1 != known[i]
puts "#{i}."
end
puts "PASSED"
end
#test_sha1()
def authSHA1(key, m)
return SHA1.hexdigest(key + m)
end