bpo-32713: Fix tarfile.itn for large/negative float values. (GH-5434)
[python-delta-tar] / file_crypt.py
1 #!/usr/bin/env python3
2
3 """ Encrypt/decrypt a single file
4
5 low-cost quick-devel badly-documented
6
7 .. codeauthor:: Intra2net <info@intra2net.com>
8 """
9
10 import sys
11 from deltatar import crypto
12 from deltatar import tarfile
13 from traceback import print_exc
14
15
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
33 def main(do_encrypt, in_file, out_file, password, comptype='gz',
34          bufsize=tarfile.RECORDSIZE, encoding='UTF-8'):
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, 'rb')
47         else:
48             decryptor = initialize_encryption (CRYPTO_MODE_DECRYPT,
49                                                password=password)
50             read_handle = tarfile._Stream(name=in_file, mode="r",
51                                           comptype=comptype, bufsize=bufsize,
52                                           fileobj=None, encryption=decryptor)
53         return_code = 3
54
55         # open file to write
56         if do_encrypt:
57             encryptor = initialize_encryption (CRYPTO_MODE_ENCRYPT,
58                                                password=password)
59             write_handle = tarfile._Stream(name=out_file, mode='w',
60                                            comptype=comptype, bufsize=bufsize,
61                                            fileobj=None, encryption=encryptor)
62         else:
63             write_handle = open(out_file, 'wb')
64         return_code = 1
65
66         # convert
67         total = 0
68         while True:
69             buf = read_handle.read(bufsize)
70             total += len(buf)
71             print('.', end='')
72             if do_encrypt:
73                 write_handle.write(buf)
74             else:
75                 # write_handle.write(buf.decode(encoding, errors='replace'))
76                 write_handle.write(buf)
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:
116         print('file_crypt.py [-c] {enc|dec} INFILE OUTFILE PASSWORD')
117         sys.exit(2)
118     elif sys.argv[1] == '-h':
119         print('file_crypt.py [-c] {enc|dec} INFILE OUTFILE PASSWORD')
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:
135         print('file_crypt.py [-c] {enc|dec} INFILE OUTFILE PASSWORD')
136         sys.exit(2)
137
138     if len(sys.argv) != idx+4:
139         print('file_crypt.py [-c] {enc|dec} INFILE OUTFILE PASSWORD')
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))