First, install the library
pip install pycrypto
Initialization vector (16 bytes), key When using + α PBKDF, a password for generating a derived key is also available. .Encryption → Binary data can be created Convert binary data (encrypted data) to Base64 or hexadecimal number, make it URL-encoded, and send it to the server
.URL decoding .Conversion of Base64 and hexadecimal numbers to binary . Prepare the same initial vector, key, etc. as the encrypted side. Rather than having the initial vector as a fixed value, it is safer to generate a different one each time by a method that only the encrypting side and the decrypting side can know. . Composite
Prepare the initial vector, salt, and password. It is recommended that the initial vector be randomly generated each time rather than a fixed value.
Here, as an example, the initial vector is digested to the current time stamp → displayed in hexadecimal number → sha512. I thought about the generation method appropriately to grasp the whole flow.
*** Please do not use the initial vector, salt and password as they are. *** ***
# -*- coding: utf-8 -*-
import base64
import urllib.parse
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Util import Padding
import requests
from datetime import datetime,timedelta,timezone
import hashlib
#Initialization vector creation(I thought about the generation method as if I used it for sha512.)Since it is converted to hexadecimal bytes type, the number of characters should be an even number.
JST = timezone(timedelta(hours=9),"JST")
now = hex(int(datetime.now(JST).timestamp()))
hs = hashlib.sha512(now.encode()).hexdigest()
hex_iv = hs[0:100]
#Since it is converted to salt hexadecimal bytes type, the number of characters should be an even number.
hex_salt = "39ccc779ab356eb43b4f37aedbc891d2f891756710b7856d21a2fd691483fb17"
secret_key = "asd@dfdfdsds"
def encrypt(plainText):
#The length of the initial vector must be 16 bytes
iv = bytes.fromhex(hex_iv)[:AES.block_size]
#Number of stretches The larger this number, the stronger the encryption strength and the slower the encryption / decryption execution speed.
secure_levels = 100
#There are no particular restrictions on salt length
salt = bytes.fromhex(hex_salt)
#Derived key generation: In the case of AES, the key length is 16 bytes(AES-128), 24 bytes(AES-192), 32bytes(AES-256)Must be one of
key = PBKDF2(password=secret_key, salt=salt, dkLen=16, count=secure_levels)
#Cipher creation
cipher = AES.new(key, AES.MODE_CBC, iv)
#Padding
data = plainText.encode()
padding = AES.block_size - len(data) % AES.block_size
data += (chr(padding) * padding).encode()
#encryption
encrypted = cipher.encrypt(data)
print(f"encrypted = {encrypted}\n")
#binary to HEX
hex_data = encrypted.hex()
print(f"hex_data : binary to HEX = {hex_data}\n")
#Base64 encoding
base64_encoded = base64.b64encode(hex_data.encode())
print(f"base64_encoded : Hex to Base64 = {base64_encoded.decode()}\n")
#URL encoding Not needed this time, but URL encoding whenever needed
# url_encoded = urllib.parse.quote(base64_encoded)
return base64_encoded
if __name__ == "__main__":
plainText = "Test the encryption."
print(f"\nPlain text = {plainText}\n")
#encryption
encrypted = encrypt(plainText)
#Send
requests.get("http://localhost:5000/get",params={"text" : encrypted,"now" : now})
# -*- coding: utf-8 -*-
import base64
import json
import urllib.parse
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Util import Padding
from flask import Flask, render_template, request
import hashlib
app = Flask(__name__)
#Salt hexadecimal number. Since it will be converted to bytes type, the number of characters should be an even number.
hex_salt = "39ccc779ab356eb43b4f37aedbc891d2f891756710b7856d21a2fd691483fb17"
secret_key = "asd@dfdfdsds"
def decrypt(base64encoded_value,now):
#URL decoding Not required this time, but URL decoding at any time if required in other languages, etc.
# url_decoded = urllib.parse.unquote(base64encoded_value)
# print(f"url_decoded = {url_decoded}")
#Base64 decoding
hex_data = base64.b64decode(base64encoded_value).decode()
print(f"hex_data : Base64 to Hex = {hex_data}\n")
# HEX → binary
encrypted_data = bytes.fromhex(hex_data)
print(f"encrypted_data : Hex to binary = {encrypted_data}\n")
#The length of the initial vector must be 16 bytes
hs = hashlib.sha512(now.encode()).hexdigest()
hex_iv = hs[0:100]
iv = bytes.fromhex(hex_iv)[:AES.block_size]
#Number of stretches The larger this number, the stronger the encryption strength and the slower the encryption / decryption execution speed.
secure_levels = 100
#There are no particular restrictions on salt length
salt = bytes.fromhex(hex_salt)
#Derivation key generation
key = PBKDF2(password=secret_key, salt=salt, dkLen=16, count=secure_levels)
#Cipher creation
cipher = AES.new(key, AES.MODE_CBC, iv)
#Composite
decrypted = cipher.decrypt(encrypted_data)
#Unpadding
response = decrypted[0: -int(decrypted[-1])].decode('utf-8')
return response
#Get Parameter Get
@app.route('/get')
def get():
text = ""
if "text" not in request.args or "now" not in request.args:
return json.dumps({"message": "send message"})
base64encoded_value = request.args.get('text')
now = request.args.get('now')
print(f"\nbase64encoded_value = {base64encoded_value}\n")
#Decryption
decrypted_data = decrypt(base64encoded_value,now)
print(f"decrypted_data = {decrypted_data}\n")
return json.dumps({"message": "OK"})
if __name__ == "__main__":
app.run(host='0.0.0.0',port=5000)
Recommended Posts