|
1 |
| -#!/usr/bin/env python |
2 |
| -# -*- coding: iso-8859-1 |
3 |
| - |
4 |
| -# Note that PyPy contains also a built-in module 'sha' which will hide |
5 |
| -# this one if compiled in. |
6 |
| - |
7 |
| -"""A sample implementation of SHA-1 in pure Python. |
8 |
| -
|
9 |
| - Framework adapted from Dinu Gherman's MD5 implementation by |
10 |
| - J. Hallén and L. Creighton. SHA-1 implementation based directly on |
11 |
| - the text of the NIST standard FIPS PUB 180-1. |
12 |
| -""" |
13 |
| - |
14 |
| - |
15 |
| -__date__ = '2004-11-17' |
16 |
| -__version__ = 0.91 # Modernised by J. Hallén and L. Creighton for Pypy |
17 |
| - |
18 |
| - |
19 |
| -import struct, copy |
20 |
| - |
21 |
| - |
22 |
| -# ====================================================================== |
23 |
| -# Bit-Manipulation helpers |
24 |
| -# |
25 |
| -# _long2bytes() was contributed by Barry Warsaw |
26 |
| -# and is reused here with tiny modifications. |
27 |
| -# ====================================================================== |
28 |
| - |
29 |
| -def _long2bytesBigEndian(n, blocksize=0): |
30 |
| - """Convert a long integer to a byte string. |
31 |
| -
|
32 |
| - If optional blocksize is given and greater than zero, pad the front |
33 |
| - of the byte string with binary zeros so that the length is a multiple |
34 |
| - of blocksize. |
35 |
| - """ |
36 |
| - |
37 |
| - # After much testing, this algorithm was deemed to be the fastest. |
38 |
| - s = '' |
39 |
| - pack = struct.pack |
40 |
| - while n > 0: |
41 |
| - s = pack('>I', n & 0xffffffffL) + s |
42 |
| - n = n >> 32 |
43 |
| - |
44 |
| - # Strip off leading zeros. |
45 |
| - for i in range(len(s)): |
46 |
| - if s[i] <> '\000': |
47 |
| - break |
48 |
| - else: |
49 |
| - # Only happens when n == 0. |
50 |
| - s = '\000' |
51 |
| - i = 0 |
52 |
| - |
53 |
| - s = s[i:] |
54 |
| - |
55 |
| - # Add back some pad bytes. This could be done more efficiently |
56 |
| - # w.r.t. the de-padding being done above, but sigh... |
57 |
| - if blocksize > 0 and len(s) % blocksize: |
58 |
| - s = (blocksize - len(s) % blocksize) * '\000' + s |
59 |
| - |
60 |
| - return s |
61 |
| - |
62 |
| - |
63 |
| -def _bytelist2longBigEndian(list): |
64 |
| - "Transform a list of characters into a list of longs." |
65 |
| - |
66 |
| - imax = len(list)/4 |
67 |
| - hl = [0L] * imax |
68 |
| - |
69 |
| - j = 0 |
70 |
| - i = 0 |
71 |
| - while i < imax: |
72 |
| - b0 = long(ord(list[j])) << 24 |
73 |
| - b1 = long(ord(list[j+1])) << 16 |
74 |
| - b2 = long(ord(list[j+2])) << 8 |
75 |
| - b3 = long(ord(list[j+3])) |
76 |
| - hl[i] = b0 | b1 | b2 | b3 |
77 |
| - i = i+1 |
78 |
| - j = j+4 |
79 |
| - |
80 |
| - return hl |
81 |
| - |
82 |
| - |
83 |
| -def _rotateLeft(x, n): |
84 |
| - "Rotate x (32 bit) left n bits circularly." |
85 |
| - |
86 |
| - return (x << n) | (x >> (32-n)) |
87 |
| - |
88 |
| - |
89 |
| -# ====================================================================== |
90 |
| -# The SHA transformation functions |
91 |
| -# |
92 |
| -# ====================================================================== |
93 |
| - |
94 |
| -def f0_19(B, C, D): |
95 |
| - return (B & C) | ((~ B) & D) |
96 |
| - |
97 |
| -def f20_39(B, C, D): |
98 |
| - return B ^ C ^ D |
99 |
| - |
100 |
| -def f40_59(B, C, D): |
101 |
| - return (B & C) | (B & D) | (C & D) |
102 |
| - |
103 |
| -def f60_79(B, C, D): |
104 |
| - return B ^ C ^ D |
105 |
| - |
106 |
| - |
107 |
| -f = [f0_19, f20_39, f40_59, f60_79] |
108 |
| - |
109 |
| -# Constants to be used |
110 |
| -K = [ |
111 |
| - 0x5A827999L, # ( 0 <= t <= 19) |
112 |
| - 0x6ED9EBA1L, # (20 <= t <= 39) |
113 |
| - 0x8F1BBCDCL, # (40 <= t <= 59) |
114 |
| - 0xCA62C1D6L # (60 <= t <= 79) |
115 |
| - ] |
116 |
| - |
117 |
| -class sha: |
118 |
| - "An implementation of the MD5 hash function in pure Python." |
119 |
| - |
120 |
| - def __init__(self): |
121 |
| - "Initialisation." |
122 |
| - |
123 |
| - # Initial message length in bits(!). |
124 |
| - self.length = 0L |
125 |
| - self.count = [0, 0] |
126 |
| - |
127 |
| - # Initial empty message as a sequence of bytes (8 bit characters). |
128 |
| - self.input = [] |
129 |
| - |
130 |
| - # Call a separate init function, that can be used repeatedly |
131 |
| - # to start from scratch on the same object. |
132 |
| - self.init() |
133 |
| - |
134 |
| - |
135 |
| - def init(self): |
136 |
| - "Initialize the message-digest and set all fields to zero." |
137 |
| - |
138 |
| - self.length = 0L |
139 |
| - self.input = [] |
140 |
| - |
141 |
| - # Initial 160 bit message digest (5 times 32 bit). |
142 |
| - self.H0 = 0x67452301L |
143 |
| - self.H1 = 0xEFCDAB89L |
144 |
| - self.H2 = 0x98BADCFEL |
145 |
| - self.H3 = 0x10325476L |
146 |
| - self.H4 = 0xC3D2E1F0L |
147 |
| - |
148 |
| - def _transform(self, W): |
149 |
| - |
150 |
| - for t in range(16, 80): |
151 |
| - W.append(_rotateLeft( |
152 |
| - W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1) & 0xffffffffL) |
153 |
| - |
154 |
| - A = self.H0 |
155 |
| - B = self.H1 |
156 |
| - C = self.H2 |
157 |
| - D = self.H3 |
158 |
| - E = self.H4 |
159 |
| - |
160 |
| - """ |
161 |
| - This loop was unrolled to gain about 10% in speed |
162 |
| - for t in range(0, 80): |
163 |
| - TEMP = _rotateLeft(A, 5) + f[t/20] + E + W[t] + K[t/20] |
164 |
| - E = D |
165 |
| - D = C |
166 |
| - C = _rotateLeft(B, 30) & 0xffffffffL |
167 |
| - B = A |
168 |
| - A = TEMP & 0xffffffffL |
169 |
| - """ |
170 |
| - |
171 |
| - for t in range(0, 20): |
172 |
| - TEMP = _rotateLeft(A, 5) + ((B & C) | ((~ B) & D)) + E + W[t] + K[0] |
173 |
| - E = D |
174 |
| - D = C |
175 |
| - C = _rotateLeft(B, 30) & 0xffffffffL |
176 |
| - B = A |
177 |
| - A = TEMP & 0xffffffffL |
178 |
| - |
179 |
| - for t in range(20, 40): |
180 |
| - TEMP = _rotateLeft(A, 5) + (B ^ C ^ D) + E + W[t] + K[1] |
181 |
| - E = D |
182 |
| - D = C |
183 |
| - C = _rotateLeft(B, 30) & 0xffffffffL |
184 |
| - B = A |
185 |
| - A = TEMP & 0xffffffffL |
186 |
| - |
187 |
| - for t in range(40, 60): |
188 |
| - TEMP = _rotateLeft(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2] |
189 |
| - E = D |
190 |
| - D = C |
191 |
| - C = _rotateLeft(B, 30) & 0xffffffffL |
192 |
| - B = A |
193 |
| - A = TEMP & 0xffffffffL |
194 |
| - |
195 |
| - for t in range(60, 80): |
196 |
| - TEMP = _rotateLeft(A, 5) + (B ^ C ^ D) + E + W[t] + K[3] |
197 |
| - E = D |
198 |
| - D = C |
199 |
| - C = _rotateLeft(B, 30) & 0xffffffffL |
200 |
| - B = A |
201 |
| - A = TEMP & 0xffffffffL |
202 |
| - |
203 |
| - |
204 |
| - self.H0 = (self.H0 + A) & 0xffffffffL |
205 |
| - self.H1 = (self.H1 + B) & 0xffffffffL |
206 |
| - self.H2 = (self.H2 + C) & 0xffffffffL |
207 |
| - self.H3 = (self.H3 + D) & 0xffffffffL |
208 |
| - self.H4 = (self.H4 + E) & 0xffffffffL |
209 |
| - |
210 |
| - |
211 |
| - # Down from here all methods follow the Python Standard Library |
212 |
| - # API of the sha module. |
213 |
| - |
214 |
| - def update(self, inBuf): |
215 |
| - """Add to the current message. |
216 |
| -
|
217 |
| - Update the md5 object with the string arg. Repeated calls |
218 |
| - are equivalent to a single call with the concatenation of all |
219 |
| - the arguments, i.e. m.update(a); m.update(b) is equivalent |
220 |
| - to m.update(a+b). |
221 |
| -
|
222 |
| - The hash is immediately calculated for all full blocks. The final |
223 |
| - calculation is made in digest(). It will calculate 1-2 blocks, |
224 |
| - depending on how much padding we have to add. This allows us to |
225 |
| - keep an intermediate value for the hash, so that we only need to |
226 |
| - make minimal recalculation if we call update() to add more data |
227 |
| - to the hashed string. |
228 |
| - """ |
229 |
| - |
230 |
| - leninBuf = long(len(inBuf)) |
231 |
| - |
232 |
| - # Compute number of bytes mod 64. |
233 |
| - index = (self.count[1] >> 3) & 0x3FL |
234 |
| - |
235 |
| - # Update number of bits. |
236 |
| - self.count[1] = self.count[1] + (leninBuf << 3) |
237 |
| - if self.count[1] < (leninBuf << 3): |
238 |
| - self.count[0] = self.count[0] + 1 |
239 |
| - self.count[0] = self.count[0] + (leninBuf >> 29) |
240 |
| - |
241 |
| - partLen = 64 - index |
242 |
| - |
243 |
| - if leninBuf >= partLen: |
244 |
| - self.input[index:] = list(inBuf[:partLen]) |
245 |
| - self._transform(_bytelist2longBigEndian(self.input)) |
246 |
| - i = partLen |
247 |
| - while i + 63 < leninBuf: |
248 |
| - self._transform(_bytelist2longBigEndian(list(inBuf[i:i+64]))) |
249 |
| - i = i + 64 |
250 |
| - else: |
251 |
| - self.input = list(inBuf[i:leninBuf]) |
252 |
| - else: |
253 |
| - i = 0 |
254 |
| - self.input = self.input + list(inBuf) |
255 |
| - |
256 |
| - |
257 |
| - def digest(self): |
258 |
| - """Terminate the message-digest computation and return digest. |
259 |
| -
|
260 |
| - Return the digest of the strings passed to the update() |
261 |
| - method so far. This is a 16-byte string which may contain |
262 |
| - non-ASCII characters, including null bytes. |
263 |
| - """ |
264 |
| - |
265 |
| - H0 = self.H0 |
266 |
| - H1 = self.H1 |
267 |
| - H2 = self.H2 |
268 |
| - H3 = self.H3 |
269 |
| - H4 = self.H4 |
270 |
| - input = [] + self.input |
271 |
| - count = [] + self.count |
272 |
| - |
273 |
| - index = (self.count[1] >> 3) & 0x3fL |
274 |
| - |
275 |
| - if index < 56: |
276 |
| - padLen = 56 - index |
277 |
| - else: |
278 |
| - padLen = 120 - index |
279 |
| - |
280 |
| - padding = ['\200'] + ['\000'] * 63 |
281 |
| - self.update(padding[:padLen]) |
282 |
| - |
283 |
| - # Append length (before padding). |
284 |
| - bits = _bytelist2longBigEndian(self.input[:56]) + count |
285 |
| - |
286 |
| - self._transform(bits) |
287 |
| - |
288 |
| - # Store state in digest. |
289 |
| - digest = _long2bytesBigEndian(self.H0, 4) + \ |
290 |
| - _long2bytesBigEndian(self.H1, 4) + \ |
291 |
| - _long2bytesBigEndian(self.H2, 4) + \ |
292 |
| - _long2bytesBigEndian(self.H3, 4) + \ |
293 |
| - _long2bytesBigEndian(self.H4, 4) |
294 |
| - |
295 |
| - self.H0 = H0 |
296 |
| - self.H1 = H1 |
297 |
| - self.H2 = H2 |
298 |
| - self.H3 = H3 |
299 |
| - self.H4 = H4 |
300 |
| - self.input = input |
301 |
| - self.count = count |
302 |
| - |
303 |
| - return digest |
304 |
| - |
305 |
| - |
306 |
| - def hexdigest(self): |
307 |
| - """Terminate and return digest in HEX form. |
308 |
| -
|
309 |
| - Like digest() except the digest is returned as a string of |
310 |
| - length 32, containing only hexadecimal digits. This may be |
311 |
| - used to exchange the value safely in email or other non- |
312 |
| - binary environments. |
313 |
| - """ |
314 |
| - return ''.join(['%02x' % ord(c) for c in self.digest()]) |
315 |
| - |
316 |
| - def copy(self): |
317 |
| - """Return a clone object. |
318 |
| -
|
319 |
| - Return a copy ('clone') of the md5 object. This can be used |
320 |
| - to efficiently compute the digests of strings that share |
321 |
| - a common initial substring. |
322 |
| - """ |
323 |
| - |
324 |
| - return copy.deepcopy(self) |
325 |
| - |
326 |
| - |
327 |
| -# ====================================================================== |
328 |
| -# Mimic Python top-level functions from standard library API |
329 |
| -# for consistency with the md5 module of the standard library. |
330 |
| -# ====================================================================== |
331 |
| - |
332 |
| -# These are mandatory variables in the module. They have constant values |
333 |
| -# in the SHA standard. |
334 |
| - |
335 |
| -digest_size = digestsize = 20 |
336 |
| -blocksize = 1 |
337 |
| - |
338 |
| -def new(arg=None): |
339 |
| - """Return a new sha crypto object. |
340 |
| -
|
341 |
| - If arg is present, the method call update(arg) is made. |
342 |
| - """ |
343 |
| - |
344 |
| - crypto = sha() |
345 |
| - if arg: |
346 |
| - crypto.update(arg) |
347 |
| - |
348 |
| - return crypto |
349 |
| - |
| 1 | +#!/usr/bin/python__author__ = 'Thomas Dixon'__license__ = 'MIT'import copy, struct, sysdef new(m=None): return sha256(m)class sha256(object): _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) _h = (0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19) _output_size = 8 |
| 2 | + blocksize = 1 block_size = 64 digest_size = 32 def __init__(self, m=None): self._buffer = '' self._counter = 0 if m is not None: if type(m) is not str: raise TypeError, '%s() argument 1 must be string, not %s' % (self.__class__.__name__, type(m).__name__) self.update(m) def _rotr(self, x, y): return ((x >> y) | (x << (32-y))) & 0xFFFFFFFF def _sha256_process(self, c): w = [0]*64 w[0:15] = 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])] def update(self, m): if not m: return if type(m) is not str: raise TypeError, '%s() argument 1 must be string, not %s' % (sys._getframe().f_code.co_name, type(m).__name__) self._buffer += m self._counter += len(m) while len(self._buffer) >= 64: self._sha256_process(self._buffer[:64]) self._buffer = self._buffer[64:] def digest(self): mdi = self._counter & 0x3F length = struct.pack('!Q', self._counter<<3) if mdi < 56: padlen = 55-mdi else: padlen = 119-mdi r = self.copy() r.update('\x80'+('\x00'*padlen)+length) return ''.join([struct.pack('!L', i) for i in r._h[:self._output_size]]) def hexdigest(self): return self.digest().encode('hex') def copy(self): return copy.deepcopy(self) |
|
0 commit comments