36
36
from io import BytesIO
37
37
from micropython import const
38
38
39
-
39
+ # SHA Block size and message digest sizes, in bytes.
40
40
SHA_BLOCKSIZE = 64
41
41
SHA_DIGESTSIZE = 20
42
42
43
- # initial hash value [5.3.1]
43
+ # initial hash value [FIPS 5.3.1]
44
44
K0 = const (0x5A827999 )
45
45
K1 = const (0x6ED9EBA1 )
46
46
K2 = const (0x8F1BBCDC )
47
47
K3 = const (0xCA62C1D6 )
48
48
49
49
def _getbuf (data ):
50
50
"""Converts data into ascii,
51
- returns bytes of data
51
+ returns bytes of data.
52
+ :param str bytes bytearray data: Data to convert.
53
+
52
54
"""
53
55
if isinstance (data , str ):
54
56
return data .encode ('ascii' )
@@ -59,6 +61,7 @@ def _left_rotate(n, b):
59
61
"""Left rotate a 32-bit integer, n, by b bits.
60
62
:param int n: 32-bit integer
61
63
:param int b: Desired rotation amount, in bits.
64
+
62
65
"""
63
66
return ((n << b ) | (n >> (32 - b ))) & 0xffffffff
64
67
@@ -68,8 +71,9 @@ def _hash_computation(chunk, h0, h1, h2, h3, h4):
68
71
Per FIPS [6.1.2]
69
72
:param bytes bytearray chunk: 64-bit bytearray
70
73
:param list h_tuple: List of hash values for the chunk
74
+
71
75
"""
72
- assert len (chunk ) == 64 , "Chunk should be 64-bits"
76
+ assert len (chunk ) == 64 , "Chunk size should be 64-bits"
73
77
74
78
w = [0 ] * 80
75
79
@@ -126,7 +130,7 @@ class sha1():
126
130
name = "sha1"
127
131
def __init__ (self ):
128
132
"""Construct a SHA-1 hash object.
129
-
133
+ :param bytes data: data to process
130
134
"""
131
135
# Initial Digest Variables
132
136
self ._h = (0x67452301 ,
@@ -135,7 +139,11 @@ def __init__(self):
135
139
0x10325476 ,
136
140
0xC3D2E1F0 )
137
141
142
+ # bytes object with 0 <= len < 64 used to store the end of the message
143
+ # if the message length is not congruent to 64
138
144
self ._unprocessed = b''
145
+
146
+ # Length in bytes of all data that has been processed so far
139
147
self ._msg_byte_len = 0
140
148
141
149
def _create_digest (self ):
@@ -146,20 +154,18 @@ def _create_digest(self):
146
154
message = self ._unprocessed
147
155
message_len = self ._msg_byte_len + len (message )
148
156
149
- # add trailing '1' bit (+ 0's padding) to string [§ 5.1.1]
157
+ # add trailing '1' bit (+ 0's padding) to string [FIPS 5.1.1]
150
158
message += b'\x80 '
151
159
152
160
# append 0 <= k < 512 bits '0', so that the resulting message length (in bytes)
153
161
# is congruent to 56 (mod 64)
154
162
message += b'\x00 ' * ((56 - (message_len + 1 ) % 64 ) % 64 )
155
163
156
-
157
164
# append ml, the original message length, as a 64-bit big-endian integer.
158
165
message_bit_length = message_len * 8
159
166
message += struct .pack (b'>Q' , message_bit_length )
160
167
161
168
# Process the final chunk
162
- # At this point, the length of the message is either 64 or 128 bytes.
163
169
h = _hash_computation (message [:64 ], * self ._h )
164
170
if len (message ) == 64 :
165
171
return h
@@ -173,7 +179,7 @@ def update(self, data):
173
179
# if we get a string, convert to a bytearray objects
174
180
data = _getbuf (data )
175
181
176
- # switch input to bytesio api for easier reading
182
+ # Use BytesIO for stream-like reading
177
183
if isinstance (data , (bytes , bytearray )):
178
184
data = BytesIO (data )
179
185
@@ -182,6 +188,7 @@ def update(self, data):
182
188
183
189
while len (chunk ) == 64 :
184
190
self ._h = _hash_computation (chunk , * self ._h )
191
+ # increase the length of the message by 64 bytes
185
192
self ._msg_byte_len += 64
186
193
# read the next 64 bytes
187
194
chunk = data .read (64 )
0 commit comments