2 # -*- coding: utf-8 -*-
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the Revised BSD License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 Revised BSD License for more details.
13 Copyright 2018-2024 Cool Dude 2k - http://idb.berlios.de/
14 Copyright 2018-2024 Game Maker 2k - http://intdb.sourceforge.net/
15 Copyright 2018-2024 Kazuki Przyborowski - https://github.com/KazukiPrzyborowski
17 $FileInfo: checksum.py - ast Update: 10/22/2024 Ver. 0.14.2 RC 1 - Author: cooldude2k $
20 from __future__
import absolute_import
, division
, print_function
, unicode_literals
, generators
, with_statement
, nested_scopes
27 from io
import open as open
29 hashlib_guaranteed
= False
30 chksum_list
= sorted(['adler32', 'crc16', 'crc16_ansi', 'crc16_ibm',
31 'crc16_ccitt', 'crc32', 'crc64', 'crc64_ecma', 'crc64_iso'])
32 if(hashlib_guaranteed
):
33 chksum_list_hash
= sorted(list(hashlib
.algorithms_guaranteed
))
35 chksum_list_hash
= sorted(list(hashlib
.algorithms_available
))
37 # initial_value can be 0xFFFF or 0x0000
40 def crc16_ansi(msg
, initial_value
=0xFFFF):
41 # CRC-16-IBM / CRC-16-ANSI polynomial and initial value
42 poly
= 0x8005 # Polynomial for CRC-16-IBM / CRC-16-ANSI
43 crc
= initial_value
# Initial value
45 crc ^
= b
<< 8 # XOR byte into CRC top byte
46 for _
in range(8): # Process each bit
47 if crc
& 0x8000: # If the top bit is set
48 # Shift left and XOR with the polynomial
49 crc
= (crc
<< 1) ^ poly
51 crc
= crc
<< 1 # Just shift left
52 crc
&= 0xFFFF # Ensure CRC remains 16-bit
55 # initial_value can be 0xFFFF or 0x0000
58 def crc16_ibm(msg
, initial_value
=0xFFFF):
59 return crc16_ansi(msg
, initial_value
)
61 # initial_value is 0xFFFF
65 return crc16_ansi(msg
, 0xFFFF)
67 # initial_value can be 0xFFFF, 0x1D0F or 0x0000
70 def crc16_ccitt(msg
, initial_value
=0xFFFF):
71 # CRC-16-CCITT polynomial
72 poly
= 0x1021 # Polynomial for CRC-16-CCITT
73 # Use the specified initial value
76 crc ^
= b
<< 8 # XOR byte into CRC top byte
77 for _
in range(8): # Process each bit
78 if crc
& 0x8000: # If the top bit is set
79 # Shift left and XOR with the polynomial
80 crc
= (crc
<< 1) ^ poly
82 crc
= crc
<< 1 # Just shift left
83 crc
&= 0xFFFF # Ensure CRC remains 16-bit
86 # initial_value can be 0x42F0E1EBA9EA3693 or 0x0000000000000000
89 def crc64_ecma(msg
, initial_value
=0x0000000000000000):
90 # CRC-64-ECMA polynomial and initial value
91 poly
= 0x42F0E1EBA9EA3693
92 crc
= initial_value
# Initial value for CRC-64-ECMA
94 crc ^
= b
<< 56 # XOR byte into the most significant byte of the CRC
95 for _
in range(8): # Process each bit
96 if crc
& (1 << 63): # Check if the leftmost (most significant) bit is set
97 # Shift left and XOR with poly if the MSB is 1
98 crc
= (crc
<< 1) ^ poly
100 crc
<<= 1 # Just shift left if the MSB is 0
101 crc
&= 0xFFFFFFFFFFFFFFFF # Ensure CRC remains 64-bit
104 # initial_value can be 0x000000000000001B or 0xFFFFFFFFFFFFFFFF
107 def crc64_iso(msg
, initial_value
=0xFFFFFFFFFFFFFFFF):
108 # CRC-64-ISO polynomial and initial value
109 poly
= 0x000000000000001B
110 crc
= initial_value
# Common initial value for CRC-64-ISO
112 crc ^
= b
<< 56 # XOR byte into the most significant byte of the CRC
113 for _
in range(8): # Process each bit
114 if crc
& (1 << 63): # Check if the leftmost (most significant) bit is set
115 # Shift left and XOR with poly if the MSB is 1
116 crc
= (crc
<< 1) ^ poly
118 crc
<<= 1 # Just shift left if the MSB is 0
119 crc
&= 0xFFFFFFFFFFFFFFFF # Ensure CRC remains 64-bit
123 def crc16_ansi_file(infile
):
124 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
126 filefp
= open(infile
, "rb")
127 checksum
= format(crc16_ansi(filefp
.read()) & 0xffff, '04x').lower()
132 def crc16_ccitt_file(infile
):
133 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
135 filefp
= open(infile
, "rb")
136 checksum
= format(crc16_ccitt(filefp
.read()) & 0xffff, '04x').lower()
141 def adler32_file(infile
):
142 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
144 filefp
= open(infile
, "rb")
145 checksum
= format(zlib
.adler32(filefp
.read()) & 0xffffffff, '08x').lower()
150 def crc32_file(infile
):
151 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
153 filefp
= open(infile
, "rb")
154 checksum
= format(zlib
.crc32(filefp
.read()) & 0xffffffff, '08x').lower()
159 def crc64_ecma_file(infile
):
160 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
162 filefp
= open(infile
, "rb")
163 checksum
= format(crc64_ecma(filefp
.read()) &
164 0xffffffffffffffff, '016x').lower()
169 def crc64_iso_file(infile
):
170 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
172 filefp
= open(infile
, "rb")
173 checksum
= format(crc64_iso(filefp
.read()) &
174 0xffffffffffffffff, '016x').lower()
179 def hash_file(infile
, checksumtype
):
180 if(checksumtype
not in chksum_list_hash
):
182 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
184 filefp
= open(infile
, "rb")
185 checksumoutstr
= hashlib
.new(checksumtype
)
186 checksumoutstr
.update(filefp
.read())
187 checksum
= checksumoutstr
.hexdigest().lower()
192 if __name__
== "__main__":
193 argparser
= argparse
.ArgumentParser(
194 description
="Get File Checksum", conflict_handler
="resolve", add_help
=True)
195 argparser
.add_argument(
196 "-V", "--version", action
="version", version
="PyChecksum 0.0.1")
197 argparser
.add_argument("-i", "-f", "--input",
198 help="Files to checksum", required
=True)
199 argparser
.add_argument("-c", "-checksum", "--checksum",
200 default
="auto", help="Checksum to use", required
=True)
201 argparser
.add_argument(
202 "-q", "--quiet", action
="store_true", help="Print only checksum")
203 getargs
= argparser
.parse_args()
204 if(getargs
.checksum
not in chksum_list
+ chksum_list_hash
):
206 if(getargs
.checksum
in chksum_list
):
207 if(getargs
.checksum
== "crc16_ansi" or getargs
.checksum
== "crc16_ibm" or getargs
.checksum
== "crc16"):
208 outchck
= crc16_ansi_file(getargs
.input)
211 if(not getargs
.quiet
):
212 print(str(outchck
)+" *"+getargs
.input)
215 if(getargs
.checksum
== "crc16_ccitt"):
216 outchck
= crc16_ccitt_file(getargs
.input)
219 if(not getargs
.quiet
):
220 print(str(outchck
)+" *"+getargs
.input)
223 if(getargs
.checksum
== "crc32"):
224 outchck
= crc32_file(getargs
.input)
227 if(not getargs
.quiet
):
228 print(str(outchck
)+" *"+getargs
.input)
231 if(getargs
.checksum
== "adler32"):
232 outchck
= adler32_file(getargs
.input)
235 if(not getargs
.quiet
):
236 print(str(outchck
)+" *"+getargs
.input)
239 if(getargs
.checksum
== "crc64_ecma"):
240 outchck
= crc64_ecma_file(getargs
.input)
243 if(not getargs
.quiet
):
244 print(str(outchck
)+" *"+getargs
.input)
247 if(getargs
.checksum
== "crc64_iso" or getargs
.checksum
== "crc64"):
248 outchck
= crc64_iso_file(getargs
.input)
251 if(not getargs
.quiet
):
252 print(str(outchck
)+" *"+getargs
.input)
255 if(getargs
.checksum
in chksum_list_hash
):
256 outchck
= hash_file(getargs
.input, getargs
.checksum
)
259 if(not getargs
.quiet
):
260 print(str(outchck
)+" *"+getargs
.input)