Commit | Line | Data |
---|---|---|
fb2a6083 CH |
1 | #!/usr/bin/env python3 |
2 | ||
3 | """ Encrypt a single file | |
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 | ||
fb2a6083 | 33 | def main(do_encrypt, in_file, out_file, password, comptype='gz', enctype='aes', |
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: | |
46 | read_handle = open(in_file, 'rt') | |
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 CH |
62 | else: |
63 | write_handle = open(out_file, 'wt') | |
64 | return_code = 1 | |
65 | ||
66 | # convert | |
67 | while True: | |
68 | buf = read_handle.read(bufsize) | |
69 | print('.', end='') | |
70 | if do_encrypt: | |
71 | write_handle.write(buf.encode(encoding, errors='strict')) | |
72 | else: | |
73 | write_handle.write(buf.decode(encoding, errors='replace')) | |
74 | if len(buf) < bufsize: | |
75 | if do_encrypt: | |
76 | print('successfully encrypted {} into {}' | |
77 | .format(in_file, out_file)) | |
78 | else: | |
79 | print('successfully decrypted {} into {}' | |
80 | .format(in_file, out_file)) | |
81 | break # reached EOF | |
82 | ||
83 | return_code = 0 | |
84 | ||
85 | except Exception: | |
86 | print('error encrypting file') | |
87 | print_exc() | |
88 | ||
89 | finally: | |
90 | # close everything | |
91 | if write_handle: | |
92 | try: | |
93 | write_handle.close() | |
94 | except Exception: | |
95 | return_code += 8 | |
96 | print('error closing out file') | |
97 | print_exc() | |
98 | ||
99 | if read_handle: | |
100 | try: | |
101 | read_handle.close() | |
102 | except Exception: | |
103 | return_code += 16 | |
104 | print('error closing in file') | |
105 | print_exc() | |
106 | ||
107 | # done | |
108 | return return_code | |
109 | ||
110 | ||
111 | if __name__ == '__main__': | |
112 | if len(sys.argv) < 4: | |
113 | print('file_crypt.py {enc|dec} [-c] INFILE OUTFILE PASSWORD') | |
114 | sys.exit(2) | |
115 | elif sys.argv[1] == '-h': | |
116 | print('encrypt_file.py {enc|dec} [-c] INFILE OUTFILE PASSWORD') | |
117 | sys.exit(0) | |
118 | ||
119 | comptype = 'tar' # auto-detect, not sure whether this would work | |
120 | idx = 1 | |
121 | if sys.argv[idx] == '-c': | |
122 | print('assuming gzip compression') | |
123 | comptype = 'gz' | |
124 | idx += 1 | |
125 | ||
126 | do_encrypt = None | |
127 | if sys.argv[idx] == 'enc': | |
128 | do_encrypt = True | |
129 | elif sys.argv[idx] == 'dec': | |
130 | do_encrypt = False | |
131 | else: | |
132 | print('encrypt_file.py {enc|dec} [-c] INFILE OUTFILE PASSWORD') | |
133 | sys.exit(2) | |
134 | ||
135 | if len(sys.argv) != idx+4: | |
136 | print('encrypt_file.py {enc|dec} [-c] INFILE OUTFILE PASSWORD') | |
137 | sys.exit(2) | |
138 | ||
139 | sys.exit(main(do_encrypt, sys.argv[idx+1], sys.argv[idx+2], | |
140 | sys.argv[idx+3], comptype)) |