Coverage for pyquickhelper/cli/encryption_cli.py: 100%
54 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-03 02:21 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-03 02:21 +0200
1"""
2@file
3@brief encrypt and decrypt command lines
4"""
5from __future__ import print_function
6import os
7import argparse
8import sys
11def get_parser(encrypt): # pylint: disable=W0621
12 """
13 Defines the way to parse the magic command ``%encrypt`` and ``%decrypt``.
15 @param encrypt encrypt or decrypt
16 @return parser
17 """
18 task = "encrypt" if encrypt else "decrypt"
19 parser = argparse.ArgumentParser(prog=task,
20 description=f'{task} a folder.' +
21 '\nFor a second run, the program looks into file status' +
22 '\nto avoid crypting same file gain, it does only modified files' +
23 '\nit does not work well in Python 2.7 with pycryptodome.')
24 parser.add_argument(
25 'source',
26 help=f'folder to {task}')
27 parser.add_argument(
28 'dest',
29 help=f'location of the {task}ed files')
30 parser.add_argument(
31 'password',
32 help='password, usually an ascii string with 16x characters')
33 if encrypt:
34 parser.add_argument(
35 '-s',
36 '--status',
37 default="crypt_status.txt",
38 help='to keep track of what was done')
39 parser.add_argument(
40 '-m',
41 '--map',
42 default="crypt_map.txt",
43 help='mapping between raw files and crypted files')
44 else:
45 parser.add_argument(
46 '-r',
47 '--regex',
48 default="",
49 help='the script can retrieve only a subpart of the data defined by a regular expression')
51 return parser
54def do_main(source, dest, password, encrypt, # pylint: disable=W0621
55 crypt_file, crypt_map, regex=None, fLOG=None):
56 """
57 Encrypts or decrypts a folder, see @see cl EncryptedBackup.
58 The function relies on module :epkg:`pycrypto`, :epkg:`cryptography`,
59 algoritm `AES <https://fr.wikipedia.org/wiki/Advanced_Encryption_Standard>`_,
60 `Fernet <https://cryptography.io/en/latest/fernet/>`_.
62 @param source source of files to encrypt or decrypt
63 @param dest destination
64 @param password password
65 @param encrypt boolean, True to encrypt
66 @param crypt_file encrypted file
67 @param crypt_map @see cl EncryptedBackup
68 @param regex regular expression to filter in files to retrieve
69 @param fLOG logging function
70 """
71 if not os.path.exists(source):
72 raise FileNotFoundError(source) # pragma: no cover
73 try:
74 from pyquickhelper.filehelper import EncryptedBackup, TransferAPIFile, FileTreeNode
75 except ImportError: # pragma: no cover
76 folder = os.path.normpath(os.path.join(
77 os.path.abspath(os.path.dirname(__file__)), "..", ".."))
78 sys.path.append(folder)
79 from pyquickhelper.filehelper import EncryptedBackup, TransferAPIFile, FileTreeNode
81 if isinstance(password, str):
82 password = bytes(password, encoding="ascii")
84 root = source
85 local = root
86 api = TransferAPIFile(dest)
88 if encrypt:
89 if fLOG:
90 fLOG("looking for file in", root)
91 ft = FileTreeNode(root, repository=False, fLOG=fLOG, log1=True)
92 enc = EncryptedBackup(key=password, file_tree_node=ft,
93 transfer_api=api, root_local=local, file_status=crypt_file,
94 file_map=crypt_map, fLOG=fLOG)
96 if fLOG:
97 fLOG("start backup")
98 issue = enc.start_transfering()[1]
100 for file, exc in issue:
101 if fLOG: # pragma: no cover
102 fLOG(f"{file} -- {exc}")
103 else:
104 enc = EncryptedBackup(key=password, file_tree_node=None,
105 transfer_api=api, root_local=None, file_status=None,
106 file_map=None, fLOG=fLOG)
107 if fLOG:
108 fLOG("start restoration")
109 enc.retrieve_all(source, regex=regex)
112def encrypt(fLOG=print, args=None):
113 """
114 Encrypts using class @see cl EncryptedBackup.
115 The function relies on module :epkg:`pycrypto`, :epkg:`cryptography`,
116 algoritm `AES <https://fr.wikipedia.org/wiki/Advanced_Encryption_Standard>`_,
117 `Fernet <https://cryptography.io/en/latest/fernet/>`_.
119 @param fLOG logging function
120 @param args to overwrite ``sys.args``
122 .. cmdref::
123 :title: Encrypt a string
124 :cmd: pyquickhelper.cli.encryption_cli:encrypt
126 Encrypts a string from the command line.
127 """
128 parser = get_parser(True)
129 if args is not None and args == ['--help']:
130 fLOG(parser.format_help())
131 else:
132 try:
133 args = parser.parse_args(args=args)
134 except SystemExit: # pragma: no cover
135 if fLOG:
136 fLOG(parser.format_usage())
137 args = None
139 if args is not None:
140 do_main(source=args.source, dest=args.dest, password=args.password,
141 encrypt=True, crypt_file=args.status, crypt_map=args.map, fLOG=fLOG)
144def decrypt(fLOG=print, args=None):
145 """
146 Decrypts using class @see cl EncryptedBackup.
147 The function relies on module :epkg:`pycrypto`, :epkg:`cryptography`,
148 algoritm `AES <https://fr.wikipedia.org/wiki/Advanced_Encryption_Standard>`_,
149 `Fernet <https://cryptography.io/en/latest/fernet/>`_.
151 @param fLOG logging function
152 @param args to overwrite ``sys.args``
154 .. cmdref::
155 :title: Decrypt a string
156 :cmd: pyquickhelper.cli.encryption_cli:decrypt
158 Decrypts an encrypted string from the command line.
159 """
160 parser = get_parser(False)
161 if args is not None and args == ['--help']:
162 fLOG(parser.format_help())
163 else:
164 try:
165 args = parser.parse_args(args=args)
166 except SystemExit: # pragma: no cover
167 if fLOG:
168 fLOG(parser.format_usage())
169 args = None
171 if args is not None:
172 do_main(source=args.dest, dest=args.source, password=args.password,
173 encrypt=False, crypt_file=None, crypt_map=None,
174 regex=args.regex if args.regex else None,
175 fLOG=fLOG)
178if __name__ == "__main__":
179 decrypt() # pragma: no cover