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 - Last Update: 4/29/2024 Ver. 0.9.0 RC 1 - Author: cooldude2k $
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
));
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
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
42 crc
= crc
<< 1; # Just shift left
43 crc
&= 0xFFFF; # Ensure CRC remains 16-bit
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
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
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
66 crc
= crc
<< 1; # Just shift left
67 crc
&= 0xFFFF; # Ensure CRC remains 16-bit
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
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
81 crc
<<= 1; # Just shift left if the MSB is 0
82 crc
&= 0xFFFFFFFFFFFFFFFF; # Ensure CRC remains 64-bit
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
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
96 crc
<<= 1; # Just shift left if the MSB is 0
97 crc
&= 0xFFFFFFFFFFFFFFFF; # Ensure CRC remains 64-bit
100 def crc16_ansi_file(infile
):
101 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
103 filefp
= open(infile
, "rb");
104 checksum
= format(crc16_ansi(filefp
.read()) & 0xffff, '04x').lower();
108 def crc16_ccitt_file(infile
):
109 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
111 filefp
= open(infile
, "rb");
112 checksum
= format(crc16_ccitt(filefp
.read()) & 0xffff, '04x').lower();
116 def adler32_file(infile
):
117 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
119 filefp
= open(infile
, "rb");
120 checksum
= format(zlib
.adler32(filefp
.read()) & 0xffffffff, '08x').lower();
124 def crc32_file(infile
):
125 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
127 filefp
= open(infile
, "rb");
128 checksum
= format(zlib
.crc32(filefp
.read()) & 0xffffffff, '08x').lower();
132 def crc64_ecma_file(infile
):
133 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
135 filefp
= open(infile
, "rb");
136 checksum
= format(crc64_ecma(filefp
.read()) & 0xffffffffffffffff, '016x').lower();
140 def crc64_iso_file(infile
):
141 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
143 filefp
= open(infile
, "rb");
144 checksum
= format(crc64_iso(filefp
.read()) & 0xffffffffffffffff, '016x').lower();
148 def hash_file(infile
, checksumtype
):
149 if(checksumtype
not in chksum_list_hash
):
151 if(not os
.path
.exists(infile
) or not os
.path
.isfile(infile
)):
153 filefp
= open(infile
, "rb");
154 checksumoutstr
= hashlib
.new(checksumtype
);
155 checksumoutstr
.update(filefp
.read());
156 checksum
= checksumoutstr
.hexdigest().lower();
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
):
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);
174 if(not getargs
.quiet
):
175 print(str(outchck
)+" *"+getargs
.input);
178 if(getargs
.checksum
=="crc16_ccitt"):
179 outchck
= crc16_ccitt_file(getargs
.input);
182 if(not getargs
.quiet
):
183 print(str(outchck
)+" *"+getargs
.input);
186 if(getargs
.checksum
=="crc32"):
187 outchck
= crc32_file(getargs
.input);
190 if(not getargs
.quiet
):
191 print(str(outchck
)+" *"+getargs
.input);
194 if(getargs
.checksum
=="adler32"):
195 outchck
= adler32_file(getargs
.input);
198 if(not getargs
.quiet
):
199 print(str(outchck
)+" *"+getargs
.input);
202 if(getargs
.checksum
=="crc64_ecma"):
203 outchck
= crc64_ecma_file(getargs
.input);
206 if(not getargs
.quiet
):
207 print(str(outchck
)+" *"+getargs
.input);
210 if(getargs
.checksum
=="crc64_iso" or getargs
.checksum
=="crc64"):
211 outchck
= crc64_iso_file(getargs
.input);
214 if(not getargs
.quiet
):
215 print(str(outchck
)+" *"+getargs
.input);
218 if(getargs
.checksum
in chksum_list_hash
):
219 outchck
= hash_file(getargs
.input, getargs
.checksum
);
222 if(not getargs
.quiet
):
223 print(str(outchck
)+" *"+getargs
.input);