implement volume handling for rescue mode
[python-delta-tar] / file_crypt.py
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
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', enctype='aes',
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, 'rt')
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, '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))