Add files via upload
[PyCatFile.git] / checksum.py
blobec2d2be4d61b67dcc0bc3927a95666dc508466d8
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 - Last Update: 4/29/2024 Ver. 0.9.0 RC 1 - Author: cooldude2k $
18 '''
20 from __future__ import absolute_import, division, print_function, unicode_literals;
21 import os, binascii, argparse, shutil, hashlib, zlib;
22 from io import open as open;
24 hashlib_guaranteed = False;
25 chksum_list = sorted(['adler32', 'crc16', 'crc16_ansi', 'crc16_ibm', 'crc16_ccitt', 'crc32', 'crc64', 'crc64_ecma', 'crc64_iso']);
26 if(hashlib_guaranteed):
27 chksum_list_hash = sorted(list(hashlib.algorithms_guaranteed));
28 else:
29 chksum_list_hash = sorted(list(hashlib.algorithms_available));
31 # initial_value can be 0xFFFF or 0x0000
32 def crc16_ansi(msg, initial_value=0xFFFF):
33 # CRC-16-IBM / CRC-16-ANSI polynomial and initial value
34 poly = 0x8005; # Polynomial for CRC-16-IBM / CRC-16-ANSI
35 crc = initial_value; # Initial value
36 for b in msg:
37 crc ^= b << 8; # XOR byte into CRC top byte
38 for _ in range(8): # Process each bit
39 if crc & 0x8000: # If the top bit is set
40 crc = (crc << 1) ^ poly; # Shift left and XOR with the polynomial
41 else:
42 crc = crc << 1; # Just shift left
43 crc &= 0xFFFF; # Ensure CRC remains 16-bit
44 return crc;
46 # initial_value can be 0xFFFF or 0x0000
47 def crc16_ibm(msg, initial_value=0xFFFF):
48 return crc16_ansi(msg, initial_value);
50 # initial_value is 0xFFFF
51 def crc16(msg):
52 return crc16_ansi(msg, 0xFFFF);
54 # initial_value can be 0xFFFF, 0x1D0F or 0x0000
55 def crc16_ccitt(msg, initial_value=0xFFFF):
56 # CRC-16-CCITT polynomial
57 poly = 0x1021; # Polynomial for CRC-16-CCITT
58 # Use the specified initial value
59 crc = initial_value;
60 for b in msg:
61 crc ^= b << 8; # XOR byte into CRC top byte
62 for _ in range(8): # Process each bit
63 if crc & 0x8000: # If the top bit is set
64 crc = (crc << 1) ^ poly; # Shift left and XOR with the polynomial
65 else:
66 crc = crc << 1; # Just shift left
67 crc &= 0xFFFF; # Ensure CRC remains 16-bit
68 return crc;
70 # initial_value can be 0x42F0E1EBA9EA3693 or 0x0000000000000000
71 def crc64_ecma(msg, initial_value=0x0000000000000000):
72 # CRC-64-ECMA polynomial and initial value
73 poly = 0x42F0E1EBA9EA3693;
74 crc = initial_value; # Initial value for CRC-64-ECMA
75 for b in msg:
76 crc ^= b << 56; # XOR byte into the most significant byte of the CRC
77 for _ in range(8): # Process each bit
78 if crc & (1 << 63): # Check if the leftmost (most significant) bit is set
79 crc = (crc << 1) ^ poly; # Shift left and XOR with poly if the MSB is 1
80 else:
81 crc <<= 1; # Just shift left if the MSB is 0
82 crc &= 0xFFFFFFFFFFFFFFFF; # Ensure CRC remains 64-bit
83 return crc;
85 # initial_value can be 0x000000000000001B or 0xFFFFFFFFFFFFFFFF
86 def crc64_iso(msg, initial_value=0xFFFFFFFFFFFFFFFF):
87 # CRC-64-ISO polynomial and initial value
88 poly = 0x000000000000001B;
89 crc = initial_value; # Common initial value for CRC-64-ISO
90 for b in msg:
91 crc ^= b << 56; # XOR byte into the most significant byte of the CRC
92 for _ in range(8): # Process each bit
93 if crc & (1 << 63): # Check if the leftmost (most significant) bit is set
94 crc = (crc << 1) ^ poly; # Shift left and XOR with poly if the MSB is 1
95 else:
96 crc <<= 1; # Just shift left if the MSB is 0
97 crc &= 0xFFFFFFFFFFFFFFFF; # Ensure CRC remains 64-bit
98 return crc;
100 def crc16_ansi_file(infile):
101 if(not os.path.exists(infile) or not os.path.isfile(infile)):
102 return False;
103 filefp = open(infile, "rb");
104 checksum = format(crc16_ansi(filefp.read()) & 0xffff, '04x').lower();
105 filefp.close();
106 return checksum;
108 def crc16_ccitt_file(infile):
109 if(not os.path.exists(infile) or not os.path.isfile(infile)):
110 return False;
111 filefp = open(infile, "rb");
112 checksum = format(crc16_ccitt(filefp.read()) & 0xffff, '04x').lower();
113 filefp.close();
114 return checksum;
116 def adler32_file(infile):
117 if(not os.path.exists(infile) or not os.path.isfile(infile)):
118 return False;
119 filefp = open(infile, "rb");
120 checksum = format(zlib.adler32(filefp.read()) & 0xffffffff, '08x').lower();
121 filefp.close();
122 return checksum;
124 def crc32_file(infile):
125 if(not os.path.exists(infile) or not os.path.isfile(infile)):
126 return False;
127 filefp = open(infile, "rb");
128 checksum = format(zlib.crc32(filefp.read()) & 0xffffffff, '08x').lower();
129 filefp.close();
130 return checksum;
132 def crc64_ecma_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(crc64_ecma(filefp.read()) & 0xffffffffffffffff, '016x').lower();
137 filefp.close();
138 return checksum;
140 def crc64_iso_file(infile):
141 if(not os.path.exists(infile) or not os.path.isfile(infile)):
142 return False;
143 filefp = open(infile, "rb");
144 checksum = format(crc64_iso(filefp.read()) & 0xffffffffffffffff, '016x').lower();
145 filefp.close();
146 return checksum;
148 def hash_file(infile, checksumtype):
149 if(checksumtype not in chksum_list_hash):
150 return False;
151 if(not os.path.exists(infile) or not os.path.isfile(infile)):
152 return False;
153 filefp = open(infile, "rb");
154 checksumoutstr = hashlib.new(checksumtype);
155 checksumoutstr.update(filefp.read());
156 checksum = checksumoutstr.hexdigest().lower();
157 filefp.close();
158 return checksum;
160 if __name__ == "__main__":
161 argparser = argparse.ArgumentParser(description="Get File Checksum", conflict_handler="resolve", add_help=True);
162 argparser.add_argument("-V", "--version", action="version", version="PyChecksum 0.0.1");
163 argparser.add_argument("-i", "-f", "--input", help="Files to checksum", required=True);
164 argparser.add_argument("-c", "-checksum", "--checksum", default="auto", help="Checksum to use", required=True);
165 argparser.add_argument("-q", "--quiet", action="store_true", help="Print only checksum");
166 getargs = argparser.parse_args();
167 if(getargs.checksum not in chksum_list + chksum_list_hash):
168 exit();
169 if(getargs.checksum in chksum_list):
170 if(getargs.checksum=="crc16_ansi" or getargs.checksum=="crc16_ibm" or getargs.checksum=="crc16"):
171 outchck = crc16_ansi_file(getargs.input);
172 if(not outchck):
173 exit();
174 if(not getargs.quiet):
175 print(str(outchck)+" *"+getargs.input);
176 else:
177 print(str(outchck));
178 if(getargs.checksum=="crc16_ccitt"):
179 outchck = crc16_ccitt_file(getargs.input);
180 if(not outchck):
181 exit();
182 if(not getargs.quiet):
183 print(str(outchck)+" *"+getargs.input);
184 else:
185 print(str(outchck));
186 if(getargs.checksum=="crc32"):
187 outchck = crc32_file(getargs.input);
188 if(not outchck):
189 exit();
190 if(not getargs.quiet):
191 print(str(outchck)+" *"+getargs.input);
192 else:
193 print(str(outchck));
194 if(getargs.checksum=="adler32"):
195 outchck = adler32_file(getargs.input);
196 if(not outchck):
197 exit();
198 if(not getargs.quiet):
199 print(str(outchck)+" *"+getargs.input);
200 else:
201 print(str(outchck));
202 if(getargs.checksum=="crc64_ecma"):
203 outchck = crc64_ecma_file(getargs.input);
204 if(not outchck):
205 exit();
206 if(not getargs.quiet):
207 print(str(outchck)+" *"+getargs.input);
208 else:
209 print(str(outchck));
210 if(getargs.checksum=="crc64_iso" or getargs.checksum=="crc64"):
211 outchck = crc64_iso_file(getargs.input);
212 if(not outchck):
213 exit();
214 if(not getargs.quiet):
215 print(str(outchck)+" *"+getargs.input);
216 else:
217 print(str(outchck));
218 if(getargs.checksum in chksum_list_hash):
219 outchck = hash_file(getargs.input, getargs.checksum);
220 if(not outchck):
221 exit();
222 if(not getargs.quiet):
223 print(str(outchck)+" *"+getargs.input);
224 else:
225 print(str(outchck));