Update pycatfile.py
[PyCatFile.git] / checksum.py
blob1f06ea5fd077896ea3901729b1d7e9338370450d
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 '''
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 $
18 '''
20 from __future__ import absolute_import, division, print_function, unicode_literals, generators, with_statement, nested_scopes
21 import os
22 import binascii
23 import argparse
24 import shutil
25 import hashlib
26 import zlib
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))
34 else:
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
44 for b in msg:
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
50 else:
51 crc = crc << 1 # Just shift left
52 crc &= 0xFFFF # Ensure CRC remains 16-bit
53 return crc
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
64 def crc16(msg):
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
74 crc = initial_value
75 for b in msg:
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
81 else:
82 crc = crc << 1 # Just shift left
83 crc &= 0xFFFF # Ensure CRC remains 16-bit
84 return crc
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
93 for b in msg:
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
99 else:
100 crc <<= 1 # Just shift left if the MSB is 0
101 crc &= 0xFFFFFFFFFFFFFFFF # Ensure CRC remains 64-bit
102 return crc
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
111 for b in msg:
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
117 else:
118 crc <<= 1 # Just shift left if the MSB is 0
119 crc &= 0xFFFFFFFFFFFFFFFF # Ensure CRC remains 64-bit
120 return crc
123 def crc16_ansi_file(infile):
124 if(not os.path.exists(infile) or not os.path.isfile(infile)):
125 return False
126 filefp = open(infile, "rb")
127 checksum = format(crc16_ansi(filefp.read()) & 0xffff, '04x').lower()
128 filefp.close()
129 return checksum
132 def crc16_ccitt_file(infile):
133 if(not os.path.exists(infile) or not os.path.isfile(infile)):
134 return False
135 filefp = open(infile, "rb")
136 checksum = format(crc16_ccitt(filefp.read()) & 0xffff, '04x').lower()
137 filefp.close()
138 return checksum
141 def adler32_file(infile):
142 if(not os.path.exists(infile) or not os.path.isfile(infile)):
143 return False
144 filefp = open(infile, "rb")
145 checksum = format(zlib.adler32(filefp.read()) & 0xffffffff, '08x').lower()
146 filefp.close()
147 return checksum
150 def crc32_file(infile):
151 if(not os.path.exists(infile) or not os.path.isfile(infile)):
152 return False
153 filefp = open(infile, "rb")
154 checksum = format(zlib.crc32(filefp.read()) & 0xffffffff, '08x').lower()
155 filefp.close()
156 return checksum
159 def crc64_ecma_file(infile):
160 if(not os.path.exists(infile) or not os.path.isfile(infile)):
161 return False
162 filefp = open(infile, "rb")
163 checksum = format(crc64_ecma(filefp.read()) &
164 0xffffffffffffffff, '016x').lower()
165 filefp.close()
166 return checksum
169 def crc64_iso_file(infile):
170 if(not os.path.exists(infile) or not os.path.isfile(infile)):
171 return False
172 filefp = open(infile, "rb")
173 checksum = format(crc64_iso(filefp.read()) &
174 0xffffffffffffffff, '016x').lower()
175 filefp.close()
176 return checksum
179 def hash_file(infile, checksumtype):
180 if(checksumtype not in chksum_list_hash):
181 return False
182 if(not os.path.exists(infile) or not os.path.isfile(infile)):
183 return False
184 filefp = open(infile, "rb")
185 checksumoutstr = hashlib.new(checksumtype)
186 checksumoutstr.update(filefp.read())
187 checksum = checksumoutstr.hexdigest().lower()
188 filefp.close()
189 return checksum
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):
205 exit()
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)
209 if(not outchck):
210 exit()
211 if(not getargs.quiet):
212 print(str(outchck)+" *"+getargs.input)
213 else:
214 print(str(outchck))
215 if(getargs.checksum == "crc16_ccitt"):
216 outchck = crc16_ccitt_file(getargs.input)
217 if(not outchck):
218 exit()
219 if(not getargs.quiet):
220 print(str(outchck)+" *"+getargs.input)
221 else:
222 print(str(outchck))
223 if(getargs.checksum == "crc32"):
224 outchck = crc32_file(getargs.input)
225 if(not outchck):
226 exit()
227 if(not getargs.quiet):
228 print(str(outchck)+" *"+getargs.input)
229 else:
230 print(str(outchck))
231 if(getargs.checksum == "adler32"):
232 outchck = adler32_file(getargs.input)
233 if(not outchck):
234 exit()
235 if(not getargs.quiet):
236 print(str(outchck)+" *"+getargs.input)
237 else:
238 print(str(outchck))
239 if(getargs.checksum == "crc64_ecma"):
240 outchck = crc64_ecma_file(getargs.input)
241 if(not outchck):
242 exit()
243 if(not getargs.quiet):
244 print(str(outchck)+" *"+getargs.input)
245 else:
246 print(str(outchck))
247 if(getargs.checksum == "crc64_iso" or getargs.checksum == "crc64"):
248 outchck = crc64_iso_file(getargs.input)
249 if(not outchck):
250 exit()
251 if(not getargs.quiet):
252 print(str(outchck)+" *"+getargs.input)
253 else:
254 print(str(outchck))
255 if(getargs.checksum in chksum_list_hash):
256 outchck = hash_file(getargs.input, getargs.checksum)
257 if(not outchck):
258 exit()
259 if(not getargs.quiet):
260 print(str(outchck)+" *"+getargs.input)
261 else:
262 print(str(outchck))