Commit | Line | Data |
---|---|---|
fb2a6083 CH |
1 | #!/usr/bin/env python3 |
2 | ||
6a86cf3e | 3 | """ Encrypt/decrypt a single file |
fb2a6083 CH |
4 | |
5 | low-cost quick-devel badly-documented | |
6 | ||
7 | .. codeauthor:: Intra2net <info@intra2net.com> | |
8 | """ | |
9 | ||
10 | import sys | |
056a457c | 11 | from deltatar import crypto |
fb2a6083 CH |
12 | from deltatar import tarfile |
13 | from traceback import print_exc | |
14 | ||
15 | ||
056a457c PG |
16 | CRYPTO_MODE_ENCRYPT = 0 |
17 | CRYPTO_MODE_DECRYPT = 1 | |
18 | ||
19 | ||
20 | def initialize_encryption (mode, password=None, key=None, nacl=None): | |
21 | if key is None and password is None: | |
22 | raise Exception ("encryption requires either a key or a password") | |
23 | if mode == CRYPTO_MODE_ENCRYPT: | |
24 | return crypto.Encrypt (password=password, | |
25 | key=key, | |
26 | nacl=nacl, | |
27 | version=crypto.PDTCRYPT_DEFAULT_VER, | |
28 | paramversion=crypto.PDTCRYPT_DEFAULT_PVER) | |
29 | if mode == CRYPTO_MODE_DECRYPT: | |
30 | return crypto.Decrypt (password=password, key=key) | |
31 | ||
32 | ||
ed00ce08 | 33 | def main(do_encrypt, in_file, out_file, password, comptype='gz', |
e37669e3 | 34 | bufsize=tarfile.RECORDSIZE, encoding='UTF-8'): |
fb2a6083 CH |
35 | """ Main function, called when running file as script |
36 | ||
37 | see module doc for more info | |
38 | """ | |
39 | ||
40 | write_handle = read_handle = None | |
41 | return_code = 4 | |
42 | ||
43 | try: | |
44 | # open file to read | |
45 | if do_encrypt: | |
68a5e96d | 46 | read_handle = open(in_file, 'rb') |
fb2a6083 | 47 | else: |
056a457c PG |
48 | decryptor = initialize_encryption (CRYPTO_MODE_DECRYPT, |
49 | password=password) | |
50 | read_handle = tarfile._Stream(name=in_file, mode="r", | |
fb2a6083 | 51 | comptype=comptype, bufsize=bufsize, |
056a457c | 52 | fileobj=None, encryption=decryptor) |
fb2a6083 CH |
53 | return_code = 3 |
54 | ||
55 | # open file to write | |
56 | if do_encrypt: | |
056a457c PG |
57 | encryptor = initialize_encryption (CRYPTO_MODE_ENCRYPT, |
58 | password=password) | |
fb2a6083 CH |
59 | write_handle = tarfile._Stream(name=out_file, mode='w', |
60 | comptype=comptype, bufsize=bufsize, | |
056a457c | 61 | fileobj=None, encryption=encryptor) |
fb2a6083 | 62 | else: |
68a5e96d | 63 | write_handle = open(out_file, 'wb') |
fb2a6083 CH |
64 | return_code = 1 |
65 | ||
66 | # convert | |
68a5e96d | 67 | total = 0 |
fb2a6083 CH |
68 | while True: |
69 | buf = read_handle.read(bufsize) | |
68a5e96d | 70 | total += len(buf) |
fb2a6083 CH |
71 | print('.', end='') |
72 | if do_encrypt: | |
68a5e96d | 73 | write_handle.write(buf) |
fb2a6083 | 74 | else: |
68a5e96d PG |
75 | # write_handle.write(buf.decode(encoding, errors='replace')) |
76 | write_handle.write(buf) | |
fb2a6083 CH |
77 | if len(buf) < bufsize: |
78 | if do_encrypt: | |
79 | print('successfully encrypted {} into {}' | |
80 | .format(in_file, out_file)) | |
81 | else: | |
82 | print('successfully decrypted {} into {}' | |
83 | .format(in_file, out_file)) | |
84 | break # reached EOF | |
85 | ||
86 | return_code = 0 | |
87 | ||
88 | except Exception: | |
89 | print('error encrypting file') | |
90 | print_exc() | |
91 | ||
92 | finally: | |
93 | # close everything | |
94 | if write_handle: | |
95 | try: | |
96 | write_handle.close() | |
97 | except Exception: | |
98 | return_code += 8 | |
99 | print('error closing out file') | |
100 | print_exc() | |
101 | ||
102 | if read_handle: | |
103 | try: | |
104 | read_handle.close() | |
105 | except Exception: | |
106 | return_code += 16 | |
107 | print('error closing in file') | |
108 | print_exc() | |
109 | ||
110 | # done | |
111 | return return_code | |
112 | ||
113 | ||
114 | if __name__ == '__main__': | |
115 | if len(sys.argv) < 4: | |
fe646953 | 116 | print('file_crypt.py [-c] {enc|dec} INFILE OUTFILE PASSWORD') |
fb2a6083 CH |
117 | sys.exit(2) |
118 | elif sys.argv[1] == '-h': | |
fe646953 | 119 | print('file_crypt.py [-c] {enc|dec} INFILE OUTFILE PASSWORD') |
fb2a6083 CH |
120 | sys.exit(0) |
121 | ||
122 | comptype = 'tar' # auto-detect, not sure whether this would work | |
123 | idx = 1 | |
124 | if sys.argv[idx] == '-c': | |
125 | print('assuming gzip compression') | |
126 | comptype = 'gz' | |
127 | idx += 1 | |
128 | ||
129 | do_encrypt = None | |
130 | if sys.argv[idx] == 'enc': | |
131 | do_encrypt = True | |
132 | elif sys.argv[idx] == 'dec': | |
133 | do_encrypt = False | |
134 | else: | |
fe646953 | 135 | print('file_crypt.py [-c] {enc|dec} INFILE OUTFILE PASSWORD') |
fb2a6083 CH |
136 | sys.exit(2) |
137 | ||
138 | if len(sys.argv) != idx+4: | |
fe646953 | 139 | print('file_crypt.py [-c] {enc|dec} INFILE OUTFILE PASSWORD') |
fb2a6083 CH |
140 | sys.exit(2) |
141 | ||
142 | sys.exit(main(do_encrypt, sys.argv[idx+1], sys.argv[idx+2], | |
143 | sys.argv[idx+3], comptype)) |