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

1""" 

2@file 

3@brief encrypt and decrypt command lines 

4""" 

5from __future__ import print_function 

6import os 

7import argparse 

8import sys 

9 

10 

11def get_parser(encrypt): # pylint: disable=W0621 

12 """ 

13 Defines the way to parse the magic command ``%encrypt`` and ``%decrypt``. 

14 

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') 

50 

51 return parser 

52 

53 

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/>`_. 

61 

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 

80 

81 if isinstance(password, str): 

82 password = bytes(password, encoding="ascii") 

83 

84 root = source 

85 local = root 

86 api = TransferAPIFile(dest) 

87 

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) 

95 

96 if fLOG: 

97 fLOG("start backup") 

98 issue = enc.start_transfering()[1] 

99 

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) 

110 

111 

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/>`_. 

118 

119 @param fLOG logging function 

120 @param args to overwrite ``sys.args`` 

121 

122 .. cmdref:: 

123 :title: Encrypt a string 

124 :cmd: pyquickhelper.cli.encryption_cli:encrypt 

125 

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 

138 

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) 

142 

143 

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/>`_. 

150 

151 @param fLOG logging function 

152 @param args to overwrite ``sys.args`` 

153 

154 .. cmdref:: 

155 :title: Decrypt a string 

156 :cmd: pyquickhelper.cli.encryption_cli:decrypt 

157 

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 

170 

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) 

176 

177 

178if __name__ == "__main__": 

179 decrypt() # pragma: no cover