Overview
In this era, we are concerned about data security.
We need to do a security method to protect the data, one of the solutions is using KMS from Alibaba Cloud.
KMS stands for Key Management Service, which is a secure and easy-to-use management service provided by Alibaba Cloud.
It can allow you to use keys securely, without having to spend a great deal to protect the CIA (Confidentiality, Integrity, and Availability) of our keys.
Prerequisites
- Alibaba Cloud Console/CLI
- Cloud Resources (ECS, KMS)
- Python
Implementation
Currently we have already default keys on KMS.
To implement the simulation, we need to configure the identities for our account first with CLI.
After that, we can try to see our keys with CLI by
To describe we can use this command
$ aliyun kms DescribeKey –KeyId <<YOUR KEY ID>>
We can see some KeyMetadata and RequestID.
Let’s test to encrypt our data which only filled by this texts “This is a test plaintext”.
It will result the CiphertextBlob which can be used to recognized the data or decrypt our data.
To decrypt, we just need to execute this
$ aliyun kms Decrypt –CiphertextBlob <<YOUR CIPHERTEXTBLOB>>
We can see the decrypted data plaintext as “This is a test plaintext”.
We are also able to return the plaintext and ciphertext off our dataKey by
$ aliyun kms GenerateDataKey –KeyId YOUR-KEY-ID
Now, we want to try to simulate data encryption of KMS between client and server with Python SDK.
Here is the encryption procedure:
- Create a CMK (Customer Master Key).
- Call the KMS GenerateDataKey interface to generate data keys.
- Use the plaintext data key to encrypt the file and generate a ciphertext file.
- Save the ciphertext data key and the ciphertext file.
Here is decryption procedure:
- Read the ciphertext data key and the ciphertext file.
- Call the KMS Decrypt interface to decrypt the ciphertext data key to obtain the plaintext data key.
- Use the plaintext data key to decrypt the file.
Please install these dependencies first.
$ pip3 install flask # micro web framework written in Python
$ pip3 install aliyun-python-sdk-kms # dependency package of alibaba cloud kms
$ pip3 install pycrypto # additional dependency for our program
Update this file, by change “clock” on time.clock() to “perf_counter”.
After that, create file .vimrc and update the file by add text “set paste”
For our server, create file server.py and fill with this code
from flask import Flask,request
from aliyunsdkcore import client
from aliyunsdkkms.request.v20160120 import GenerateDataKeyRequest
from aliyunsdkkms.request.v20160120 import DecryptRequest
import json,base64
from Crypto.Cipher import AES
app = Flask(__name__)
accesskeyid = "<<YOUR KEY ACCESS ID>>"
accesssecret = "<<YOUR KEY ACCESS SECRET>>"
keyid = "<<YOUR KEY ID>>"
regionid = "us-west-1"
def createdatakey():
clt = client.AcsClient(accesskeyid, accesssecret, regionid)
genrequest = GenerateDataKeyRequest.GenerateDataKeyRequest()
genrequest.set_KeyId(keyid);
genrequest.set_KeySpec("AES_256") # or AES_128
genrequest.set_accept_format("json")
genrequest.set_protocol_type("https")
genresp = clt.do_action_with_exception(genrequest)
datakeydict = json.loads(genresp)
datakey = base64.b64decode(datakeydict["Plaintext"]) #here we got the datakey with plaintext
cipherdatakey = datakeydict["CiphertextBlob"] # here we got encrypted datakey
return cipherdatakey
def decryptdata(ciphertext, cipherdatakey):
clt = client.AcsClient(accesskeyid, accesssecret, regionid)
decrequest = DecryptRequest.DecryptRequest()
decrequest.set_CiphertextBlob(cipherdatakey)
decrequest.set_accept_format("json")
decrequest.set_protocol_type("https")
decresp = clt.do_action_with_exception(decrequest)
plaintext = json.loads(decresp)
datakey = base64.b64decode(plaintext["Plaintext"]) # get plaintext datakey back
cipherfile = base64.b64decode(ciphertext)
iv = cipherfile[:AES.block_size]
aes = AES.new(datakey,AES.MODE_CBC, iv)
return aes.decrypt(cipherfile[AES.block_size:]).decode('utf-8') #use datakey to decrypt the content of file: cipherfile.txt and print it out
@app.route('/')
def index():
return 'Hello Flask!\n'
@app.route('/applyDataKey')
def applyDataKey():
return createdatakey() + "\n"
@app.route("/sendEncryptedData",methods = ['GET',"POST"])
def sendEncryptedData():
if request.method == "POST":
ciphertext = request.form["ciphertext"]
cipherdatakey = request.form["cipherdatakey"]
print ("After decryption:" + decryptdata(ciphertext, cipherdatakey))
return "decryptdata success"
return "decryptdata fail, Methods is error"
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80)
Nb. Update accesskeyid, accesssecret, keyid and regionid.
And for client, create file named client.py and fill with this code.
#!/usr/bin/python
#coding:utf-8
import sys,requests,json
from aliyunsdkcore import client
from aliyunsdkkms.request.v20160120 import DecryptRequest
from Crypto.Cipher import AES
from Crypto import Random
import base64
accesskeyid = "YOUR KEY ACCESS ID"
accesssecret = "YOUR KEY ACCESS SECRET"
regionid = "us-west-1"
def aes256pad(s):
return s + (32 - len(s) % 32) * chr(32 - len(s) % 32)
def send(ciphertext, cipherdatakey):
url = "http://<<YOUR IP>>/sendEncryptedData"
payload={'ciphertext': ciphertext,
'cipherdatakey': cipherdatakey}
files=[
]
headers = {}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
if __name__ == "__main__":
content = sys.argv[1]
cipherdatakey = sys.argv[2]
clt = client.AcsClient(accesskeyid, accesssecret, regionid)
decrequest = DecryptRequest.DecryptRequest()
decrequest.set_CiphertextBlob(cipherdatakey)
decrequest.set_accept_format("json")
decrequest.set_protocol_type("https")
decresp = clt.do_action_with_exception(decrequest)
plaintext = json.loads(decresp)
datakey = base64.b64decode(plaintext["Plaintext"]) # get plaintext datakey back
iv = Random.new().read(AES.block_size)
cipher = AES.new(datakey, AES.MODE_CBC, iv) #use daatakey to initiate an object
filedata =aes256pad(content)
cipherfile = base64.b64encode(iv + cipher.encrypt(filedata)) #encrypt the content
print(cipherfile)
send(str(cipherfile, encoding="utf-8"), cipherdatakey)
Nb. Update accesskeyid, accesssecret, yourIP, and regionid.
Run python3 server.py
Our public IP is 47.88.94.217, we can access it directly
Let’s try to obtain data key ciphertext on URI http://$host/applyDataKey
To decrypt
And we can check it from the server log.
Reference
Labex.io