I will create a python code to encrpyt some sensitive information in a file. The code will collect a paraphrase from the user for each record, to generate a key to encrypt the info. And when user wants to retrieve the encrypted info, user must provide the paraphrase.
Python Code
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | import os import sys try : from Crypto.Cipher import AES except ModuleNotFoundError as me: print ( "pip3 install pycryptodome" ) raise exit() from Crypto.Util.Padding import pad, unpad from Crypto. Hash import SHA1 ### AES-128 Encrpytion and Decryption ### ############################################ def encrypt(raw_bytes, key): # Create an AES cipher object with the key # and AES.MODE_ECB mode cipher = AES.new(key, AES.MODE_ECB) # Pad the raw_bytes and encrypt it padded = pad(raw_bytes, AES.block_size) ciphertext = cipher.encrypt(padded) return ciphertext def decrypt(ciphertext, key): # Create an AES cipher object with the key # and AES.MODE_ECB mode cipher = AES.new(key, AES.MODE_ECB) # Decrypt the ciphertext and remove the padding try : unpadded = cipher.decrypt(ciphertext) decrypted_data = unpad(unpadded, AES.block_size) except ValueError as ve: if hasattr (ve, 'message' ): raise ValueError(e.message) else : raise ValueError(ve) return decrypted_data ### Main ### ############################################ def create_key(txt): # Find the hash of the tezt hash = SHA1.new(txt.strip().encode( 'ASCII' )) # Key-length accepted: 16, 24, and 32 bytes. keybytes = hash .digest()[: 16 ] return keybytes def store(about, encinfo, fname = 'secured.lckr' ): prefix = '<rec>' suffix = '</rec>' rec = f '\r\n{prefix}`{about}`{encinfo}`{suffix}' # get the current working directory cwd = os.getcwd() file_path = os.path.join(cwd,fname) # Open the file in write mode with open (file_path, 'a' ) as file : # Write content to the file file .write(rec) print ( "Saved" ) def read_from_locker(filename = 'secured.lckr' ): # get the current working directory cwd = os.getcwd() file_path = os.path.join(cwd,filename) whole_data = "" try : with open (file_path, 'r' ) as fp: whole_data = fp.readlines() except FileNotFoundError as fe: print (f 'No records' ) exit() return whole_data def list_rec(): prefix = '<rec>' suffix = '</rec>' serial_number = 0 records = [] data_dump = read_from_locker(); # List the records print ( "\nSl." , "\t" , "About" ) for line in data_dump: if len (line) > ( len (prefix) + len (suffix)): words = line.split( '`' ) if ( words[ 0 ].lstrip() = = prefix and words[ 3 ].rstrip() = = suffix ): records.append(words) print (serial_number, "\t" , words[ 1 ]) serial_number + = 1 return records def get_sensitive_info(encrypted_info): try : paraphrase = input ( 'Enter the paraphrase to retrieve the sensitive info:' ) except EOFError: exit() key = create_key(paraphrase) dcryptd_info = "" try : # Convert hex string to bytes object encr_bytes = bytes.fromhex(encrypted_info) # Decryption dcryptd_info = decrypt(encr_bytes, key) except ValueError as ve: print (ve) else : if isinstance (dcryptd_info, bytes): dcryptd_info = dcryptd_info.decode( "ASCII" ) print (f 'info = {dcryptd_info}' ) try : input ( "\n Press any key to exit" ) except EOFError: exit() def select_rec(): records = list_rec() print ( "Press any other key to Exit \n" ) try : rec_str = input ( 'Select a Sl. to show sensitive info:' ) rec_id = int (rec_str) except Exception as e: exit() except EOFError: exit() if (rec_id> = 0 and rec_id< len (records)): get_sensitive_info(records[rec_id][ 2 ]) else : print (f 'Invalid Sl.' ) def store_rec(): try : paraphrase = input ( 'Enter the paraphrase to encrypt the sensitive info:' ) senstv_info = input ( 'Enter the sensitive info:' ) senstv_info = senstv_info.strip() about = input ( 'Enter a name to identify:' ).strip() except EOFError: exit() key = create_key(paraphrase) senstvInfoBytes = senstv_info.encode( 'ASCII' ) # Encryption encryptd_info = encrypt(senstvInfoBytes, key). hex () store(about, encryptd_info) def main_menu(): print ( "1. \t List Records" ) print ( "2. \t Store a Sensitive Info" ) print ( "Press any other key to Exit" ) try : menu_no = input ( 'Select a menu number:' ) if (menu_no = = 1 or menu_no = = '1' ): select_rec() elif (menu_no = = 2 or menu_no = = '2' ): store_rec() else : exit() except EOFError: exit() ## Secure Store Main Menu ## ########################## main_menu() |
import os import sys try: from Crypto.Cipher import AES except ModuleNotFoundError as me: print("pip3 install pycryptodome") raise exit() from Crypto.Util.Padding import pad, unpad from Crypto.Hash import SHA1 ### AES-128 Encrpytion and Decryption ### ############################################ def encrypt(raw_bytes, key): # Create an AES cipher object with the key # and AES.MODE_ECB mode cipher = AES.new(key, AES.MODE_ECB) # Pad the raw_bytes and encrypt it padded = pad(raw_bytes, AES.block_size) ciphertext = cipher.encrypt(padded) return ciphertext def decrypt(ciphertext, key): # Create an AES cipher object with the key # and AES.MODE_ECB mode cipher = AES.new(key, AES.MODE_ECB) # Decrypt the ciphertext and remove the padding try: unpadded = cipher.decrypt(ciphertext) decrypted_data = unpad(unpadded, AES.block_size) except ValueError as ve: if hasattr(ve, 'message'): raise ValueError(e.message) else: raise ValueError(ve) return decrypted_data ### Main ### ############################################ def create_key(txt): # Find the hash of the tezt hash = SHA1.new(txt.strip().encode('ASCII')) # Key-length accepted: 16, 24, and 32 bytes. keybytes = hash.digest()[:16] return keybytes def store(about, encinfo, fname='secured.lckr'): prefix='<rec>' suffix='</rec>' rec = f'\r\n{prefix}`{about}`{encinfo}`{suffix}' # get the current working directory cwd = os.getcwd() file_path = os.path.join(cwd,fname) # Open the file in write mode with open(file_path, 'a') as file: # Write content to the file file.write(rec) print("Saved") def read_from_locker(filename='secured.lckr'): # get the current working directory cwd = os.getcwd() file_path = os.path.join(cwd,filename) whole_data = "" try: with open(file_path, 'r') as fp: whole_data = fp.readlines() except FileNotFoundError as fe: print(f'No records') exit() return whole_data def list_rec(): prefix='<rec>' suffix='</rec>' serial_number = 0 records = [] data_dump = read_from_locker(); # List the records print("\nSl.", "\t", "About") for line in data_dump: if len(line) > (len(prefix) + len(suffix)): words = line.split('`') if( words[0].lstrip()==prefix and words[3].rstrip()==suffix ): records.append(words) print(serial_number, "\t", words[1]) serial_number +=1 return records def get_sensitive_info(encrypted_info): try: paraphrase=input('Enter the paraphrase to retrieve the sensitive info:') except EOFError: exit() key = create_key(paraphrase) dcryptd_info = "" try: # Convert hex string to bytes object encr_bytes = bytes.fromhex(encrypted_info) # Decryption dcryptd_info = decrypt(encr_bytes, key) except ValueError as ve: print(ve) else: if isinstance(dcryptd_info, bytes): dcryptd_info = dcryptd_info.decode("ASCII") print(f'info = {dcryptd_info}') try: input("\n Press any key to exit") except EOFError: exit() def select_rec(): records = list_rec() print("Press any other key to Exit \n") try: rec_str=input('Select a Sl. to show sensitive info:') rec_id=int(rec_str) except Exception as e: exit() except EOFError: exit() if(rec_id>=0 and rec_id<len(records)): get_sensitive_info(records[rec_id][2]) else: print(f'Invalid Sl.') def store_rec(): try: paraphrase=input('Enter the paraphrase to encrypt the sensitive info:') senstv_info=input('Enter the sensitive info:') senstv_info = senstv_info.strip() about=input('Enter a name to identify:').strip() except EOFError: exit() key = create_key(paraphrase) senstvInfoBytes = senstv_info.encode('ASCII') # Encryption encryptd_info = encrypt(senstvInfoBytes, key).hex() store(about, encryptd_info) def main_menu(): print("1. \t List Records") print("2. \t Store a Sensitive Info") print("Press any other key to Exit") try: menu_no = input('Select a menu number:') if(menu_no==1 or menu_no=='1'): select_rec() elif(menu_no==2 or menu_no=='2'): store_rec() else: exit() except EOFError: exit() ## Secure Store Main Menu ## ########################## main_menu()
Execute the Python Code
python secureStore.py
Batch Script
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | @ ECHO OFF SETLOCAL ENABLEEXTENSIONS SETLOCAL ENABLEDELAYEDEXPANSION REM ENABLEDELAYEDEXPANSION would allow !var! to expand REM the variable var at execution time. REM The variables is usually expanded at input time, REM but when inside of a FOR loop, REM its assigned with value during initialization. REM This expansion of variable at the input time, REM causes counter variables not to increment REM or decrement in FOR loop. REM Parent Directory of secureStore Code SET parent=%~dp0 REM Get the path of python executable REM If more than one path of python.exe exists, REM select the 1st one SET /A once=0 FOR /F "usebackq delims=" %%i IN (`where python.exe`) DO ( IF /I !once! EQU 0 ( SET pyPath=%%i SET /A once=1 ) ) REM echo %pyPath% cd %parent% REM For supporting “double-click” execution REM from Windows Explorer SET /A noninteractive=0 ECHO %CMDCMDLINE% | FINDSTR /L /I %parent% > NUL 2>&1 IF % ERRORLEVEL % == 0 SET /A noninteractive=1 REM Run the app "%pyPath%" secureStore.py IF ERRORLEVEL 1 ( REM If Some Error occured running the app REM Re Run the app to capture the error "%pyPath%" secureStore.py 2> NUL | findstr /LI "pip3 install pycryptodome" IF ERRORLEVEL 0 ( REM If Crypto module is not installed ECHO Installing Crypto Library pip3 install pycryptodome IF ERRORLEVEL 0 ( REM After successful installation of Crypto Library REM Run the app again "%pyPath%" secureStore.py ) ) ) IF /I !noninteractive! EQU 1 ( REM Paused the CMD.exe to show the output before exiting REM For bat script, double clicked from Win Explorer PAUSE ) ENDLOCAL EXIT /B 0 |
@ECHO OFF SETLOCAL ENABLEEXTENSIONS SETLOCAL ENABLEDELAYEDEXPANSION REM ENABLEDELAYEDEXPANSION would allow !var! to expand REM the variable var at execution time. REM The variables is usually expanded at input time, REM but when inside of a FOR loop, REM its assigned with value during initialization. REM This expansion of variable at the input time, REM causes counter variables not to increment REM or decrement in FOR loop. REM Parent Directory of secureStore Code SET parent=%~dp0 REM Get the path of python executable REM If more than one path of python.exe exists, REM select the 1st one SET /A once=0 FOR /F "usebackq delims=" %%i IN (`where python.exe`) DO ( IF /I !once! EQU 0 ( SET pyPath=%%i SET /A once=1 ) ) REM echo %pyPath% cd %parent% REM For supporting “double-click” execution REM from Windows Explorer SET /A noninteractive=0 ECHO %CMDCMDLINE% | FINDSTR /L /I %parent% >NUL 2>&1 IF %ERRORLEVEL% == 0 SET /A noninteractive=1 REM Run the app "%pyPath%" secureStore.py IF ERRORLEVEL 1 ( REM If Some Error occured running the app REM Re Run the app to capture the error "%pyPath%" secureStore.py 2>NUL | findstr /LI "pip3 install pycryptodome" IF ERRORLEVEL 0 ( REM If Crypto module is not installed ECHO Installing Crypto Library pip3 install pycryptodome IF ERRORLEVEL 0 ( REM After successful installation of Crypto Library REM Run the app again "%pyPath%" secureStore.py ) ) ) IF /I !noninteractive! EQU 1 ( REM Paused the CMD.exe to show the output before exiting REM For bat script, double clicked from Win Explorer PAUSE ) ENDLOCAL EXIT /B 0
Place this batch script in the same folder as python code. Also create a shortcut for this batch script in Desktop, Programs Menu, etc.
Now when you double click on the secureStore.bat or its shortcut, it will execute the python code and show in command prompt.
Understanding the Batch Script
Line 1: @ECHO OFF : This instruction prevents cmd.exe from displaying all the batch commands that is executed. Without @ECHO OFF, the output would be like the image below
Line 20: FOR /F "usebackq delims=" %%i IN (`where python.exe`) DO (
It parses the output of the command inside the IN () block and for each output line, the DO () block is executed.
usebackq option specifies that `backquoted text` is executed as command, 'single quoted text' as literal string and "double quoted text" as filenames.
delims=NULL option specifies that output is not tokenised using any delimiter, so the output is passed as a whole line.
%%i is the variable which stores the output line for each output line iterated.
Line 21: IF /I !once! EQU 0 (
This instruction checks if once variable equals to 0, if true run the command in (commands) block
Line 32: ECHO %CMDCMDLINE% | FINDSTR /L /I %parent% >NUL 2>&1
%CMDCMDLINE% is built-in variable that contains the path of the command which invoked the cmd.exe. IF a batch script is executed from already running cmd.exe then CMDCMDLINE value would be "C:\Windows\System32\cmd.exe" and if the batch script was run by double-clicking on it, then CMDCMDLINE would be "C:\WINDOWS\system32\cmd.exe /c ""\projects\SecureStoreApp\secureStore.bat" ""
The '|' pipe operator is to pass the output of the LHS command to as an input of the RHS command.
FINDSTR command searches for the value in parent variable in the CMDCMDLINE variable and if its not found, then built-in ERRORLEVEL variable is set as 1 or else the ERRORLEVE variable is assigned 0 (success).
/I option makes the search case-insensitive.
/L option instructs to use the search string literally instead of as any regular expression string.
>NUL 2>&1 instructs the outputs from the FINDSTR to be redirected to NULL file descriptor and also the instructs the STDERR output to be redirected to STDOUT (where STDOUT is already redirected to NULL). So this instructs no output to be displayed for this line command.
Line 41-45: If running the python code, throws an error since a module is not found, then FINDSTR is used to find the exact module not available and try to install that library required.