derive test skeleton for disaster rescue mode
[python-delta-tar] / file_crypt.py
CommitLineData
fb2a6083
CH
1#!/usr/bin/env python3
2
3""" Encrypt a single file
4
5low-cost quick-devel badly-documented
6
7.. codeauthor:: Intra2net <info@intra2net.com>
8"""
9
10import sys
056a457c 11from deltatar import crypto
fb2a6083
CH
12from deltatar import tarfile
13from traceback import print_exc
14
15
056a457c
PG
16CRYPTO_MODE_ENCRYPT = 0
17CRYPTO_MODE_DECRYPT = 1
18
19
20def 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 33def 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
111if __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))