-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
__mydoc__ = """ | ||
---------------------------------------------------------------------------- | ||
MyAes.py, Ennaayattulla | ||
Tested with PyCharm Community Edition 2019.3 x64, python 3.7 | ||
Q1. Implement get_fixed_key() to return a 256-bit AES key. | ||
Q2. Implement get_random_key() to return a random 256-bit AES key. | ||
Q3. Implement AES encrypt(key, plaintext_utf8, ciphertext_file) where: | ||
- key: AES key | ||
- plaintext_utf8: plaintext in UTF8 format | ||
- ciphertext_file: file name of binary file to store the ciphertext | ||
- return: nil | ||
- assumption: use CBC mode, IV and default padding (PKCS7) | ||
Q4. Implement AES decrypt(key, ciphertext_file) where: | ||
- key: AES key | ||
- ciphertext_file: name of binary file containing the ciphertext | ||
- return: decrypted text in UTF8 | ||
- assumption: use CBC mode, IV and default padding (PKCS7) | ||
---------------------------------------------------------------------------- | ||
""" | ||
|
||
|
||
from Crypto.Cipher import AES | ||
from Crypto.Random import get_random_bytes | ||
from Crypto.Util.Padding import pad, unpad | ||
from base64 import b64encode, b64decode | ||
import random | ||
|
||
|
||
def get_fixed_key(): | ||
# use fixed AES key, 256 bits | ||
#return b"..." | ||
return b'abcdefghijklmnopqrstuvwxyz123456' | ||
|
||
|
||
def get_random_key(byte_size): | ||
""" generate random AES key, keysize = 32*8 = 256 bits""" | ||
#return get_random_bytes(...) | ||
return get_random_bytes(byte_size) | ||
|
||
|
||
def get_random_alphanumeric(Size): | ||
allchars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' | ||
return ''.join((random.choice(allchars) for i in range(int(Size)))) | ||
|
||
|
||
def get_random_iv(): | ||
return get_random_bytes(16) | ||
|
||
|
||
# AES encrypt using CBC and IV, with default padding (PKCS7) | ||
def CBC_encrypt(key, plaintext_utf8, iv): | ||
key = bytes(key, "utf-8") | ||
iv = bytes(iv, "utf-8") | ||
cipher = AES.new(key, AES.MODE_CBC, iv) | ||
ciphertext = cipher.encrypt(pad(plaintext_utf8, AES.block_size)) | ||
ciphertext = b64encode(ciphertext) | ||
return ciphertext | ||
|
||
|
||
def CBC_decrypt(key, plaintext_utf8, iv): | ||
key = bytes(key, "utf-8") | ||
iv = bytes(iv, "utf-8") | ||
plaintext_utf8 = b64decode(plaintext_utf8) | ||
cipher = AES.new(key, AES.MODE_CBC, iv) | ||
plaintext = unpad(cipher.decrypt(plaintext_utf8), AES.block_size) | ||
return plaintext | ||
|
||
|
||
def CFB_encrypt(key, plaintext_utf8, iv): | ||
key = bytes(key, "utf-8") | ||
iv = bytes(iv, "utf-8") | ||
cipher = AES.new(key, AES.MODE_CFB, iv) | ||
ciphertext = cipher.encrypt(pad(plaintext_utf8, AES.block_size)) | ||
ciphertext = b64encode(ciphertext) | ||
return ciphertext | ||
|
||
|
||
def CFB_decrypt(key, plaintext_utf8, iv): | ||
key = bytes(key, "utf-8") | ||
iv = bytes(iv, "utf-8") | ||
plaintext_utf8 = b64decode(plaintext_utf8) | ||
cipher = AES.new(key, AES.MODE_CFB, iv) | ||
plaintext = unpad(cipher.decrypt(plaintext_utf8), AES.block_size) | ||
return plaintext | ||
|
||
|
||
def OFB_encrypt(key, plaintext_utf8, iv): | ||
key = bytes(key, "utf-8") | ||
iv = bytes(iv, "utf-8") | ||
cipher = AES.new(key, AES.MODE_OFB, iv) | ||
ciphertext = cipher.encrypt(pad(plaintext_utf8, AES.block_size)) | ||
ciphertext = b64encode(ciphertext) | ||
return ciphertext | ||
|
||
|
||
def OFB_decrypt(key, plaintext_utf8, iv): | ||
key = bytes(key, "utf-8") | ||
iv = bytes(iv, "utf-8") | ||
plaintext_utf8 = b64decode(plaintext_utf8) | ||
cipher = AES.new(key, AES.MODE_OFB, iv) | ||
plaintext = unpad(cipher.decrypt(plaintext_utf8), AES.block_size) | ||
return plaintext | ||
|
||
|
||
def ECB_encrypt(key, plaintext_utf8): | ||
key = bytes(key, "utf-8") | ||
cipher = AES.new(key, AES.MODE_ECB) | ||
ciphertext = cipher.encrypt(pad(plaintext_utf8, AES.block_size)) | ||
ciphertext = b64encode(ciphertext) | ||
return ciphertext | ||
|
||
|
||
def ECB_decrypt(key, plaintext_utf8): | ||
key = bytes(key, "utf-8") | ||
plaintext_utf8 = b64decode(plaintext_utf8) | ||
cipher = AES.new(key, AES.MODE_ECB) | ||
plaintext = unpad(cipher.decrypt(plaintext_utf8), AES.block_size) | ||
return plaintext |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
__mydoc__ = """ | ||
MyAes_Test.py, Ennaayattulla | ||
Tested with PyCharm Community Edition 2019.3 x64, python 3.7 | ||
""" | ||
|
||
|
||
from MyCryptoPackage import MyAes | ||
|
||
|
||
def run_test(): | ||
print(__mydoc__) | ||
print(MyAes.__mydoc__) | ||
|
||
key = MyAes.get_random_alphanumeric(32) | ||
iv = MyAes.get_random_alphanumeric(16) | ||
plaintext_string = "Testing AES encrypt and decrypt." | ||
|
||
# encode plaintext, then encrypt | ||
ciphertext = MyAes.CBC_encrypt(key, plaintext_string.encode("utf8"), iv) | ||
|
||
# decrypt ciphertext, then decode | ||
decryptedtext_string = MyAes.CBC_decrypt(key, ciphertext, iv).decode("utf-8") | ||
|
||
print("CBC plaintext: " + plaintext_string) | ||
print("CBC ciphertext:", ciphertext) | ||
print("CBC decryptedtext: " + decryptedtext_string) | ||
|
||
ciphertext = MyAes.CFB_encrypt(key, plaintext_string.encode("utf8"), iv) | ||
|
||
# decrypt ciphertext, then decode | ||
decryptedtext_string = MyAes.CFB_decrypt(key, ciphertext, iv).decode("utf8") | ||
|
||
print("CFB plaintext: " + plaintext_string) | ||
print("CFB decryptedtext: " + decryptedtext_string) | ||
ciphertext = MyAes.OFB_encrypt(key, plaintext_string.encode("utf8"), iv) | ||
|
||
# decrypt ciphertext, then decode | ||
decryptedtext_string = MyAes.OFB_decrypt(key, ciphertext, iv).decode("utf8") | ||
|
||
print("OFB plaintext: " + plaintext_string) | ||
print("OFB decryptedtext: " + decryptedtext_string) | ||
ciphertext = MyAes.ECB_encrypt(key, plaintext_string.encode("utf8")) | ||
|
||
# decrypt ciphertext, then decode | ||
decryptedtext_string = MyAes.ECB_decrypt(key, ciphertext).decode("utf8") | ||
|
||
print("ECB plaintext: " + plaintext_string) | ||
print("ECB decryptedtext: " + decryptedtext_string) | ||
|
||
return | ||
|
||
|
||
if __name__ == "__main__": | ||
run_test() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
__mydoc__ = """ | ||
---------------------------------------------------------------------------- | ||
MyCaesarCipher.py, Ennaayattulla | ||
Tested with PyCharm Community Edition 2019.3 x64, python 3.7 | ||
MyCaesarCipher specifications: | ||
------------------------------ | ||
encrypt(key, plaintext_utf8) where: | ||
- key: Caesar key, e.g. 3 denotes shifting 3 character positions | ||
- plaintext_utf8: plaintext in UTF8 format | ||
- return: ciphertext in UTF8 format | ||
decrypt(key, ciphertext_utf8) where: | ||
- key: Caesar key, e.g. 3 denotes shifting 3 character positions | ||
- ciphertext_utf8: ciphertext in UTF8 format | ||
- return: decrypted text in UTF8 format | ||
Use/modify MyCaesarCipher_Test.py to test your implementations. | ||
Questions: | ||
---------- | ||
Q1. Implement encrypt() and decrypt() to handle only upper case, | ||
so that you get the following plaintexts and corresponding ciphertexts: | ||
plaintext: HELLO | ||
ciphertext: KHOOR | ||
decryptedtext: HELLO | ||
plaintext: Hello! | ||
ciphertext: Kello! | ||
decryptedtext: Hello! | ||
Q2. Enhance encrypt() and decrypt() to handle both upper and lower cases, | ||
so that you get the following plaintexts and corresponding ciphertexts: | ||
plaintext: HELLO | ||
ciphertext: KHOOR | ||
decryptedtext: HELLO | ||
plaintext: Hello! | ||
ciphertext: Khoor! | ||
decryptedtext: Hello! | ||
Q3. Enhance encrypt() and decrypt() to handle all base64 characters, | ||
so that you get the following plaintexts and corresponding ciphertexts: | ||
plaintext: Hello123+/= | ||
ciphertext: Khoor456ABC | ||
decryptedtext: Hello123+/= | ||
---------------------------------------------------------------------------- | ||
""" | ||
|
||
|
||
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' # Q1, Q2, Q3 | ||
|
||
|
||
def encrypt(key, plaintext_utf8): | ||
ciphertext_utf8 = "" | ||
|
||
for character in plaintext_utf8: | ||
if character in LETTERS: | ||
position = LETTERS.find(character) | ||
position += key | ||
# get the character position | ||
#position = ... # hint: use find() | ||
#position = position + ... | ||
|
||
# wrap-around if position >= length of LETTERS | ||
#if position >= len(LETTERS): | ||
#position = position - ... | ||
if position >= len(LETTERS): | ||
position -= len(LETTERS) | ||
# append encrypted character | ||
#ciphertext_utf8 = ciphertext_utf8 + ... | ||
ciphertext_utf8 += LETTERS[position] | ||
|
||
else: | ||
# append character without encrypting | ||
#ciphertext_utf8 = ciphertext_utf8 + ... | ||
ciphertext_utf8 += character | ||
|
||
return ciphertext_utf8 | ||
|
||
|
||
def decrypt(key, ciphertext_utf8): | ||
decryptedtext_utf = "" | ||
|
||
for character in ciphertext_utf8: | ||
if character in LETTERS: | ||
position = LETTERS.find(character) | ||
position -= key | ||
# get the character position | ||
#position = ... # hint: use find() | ||
#position = position - ... | ||
|
||
# wrap-around if position >= length of LETTERS | ||
#if position < 0: | ||
#position = position + ... | ||
if position < 0: | ||
position += len(LETTERS) | ||
|
||
# append encrypted character | ||
#decryptedtext_utf = decryptedtext_utf + ... | ||
decryptedtext_utf += LETTERS[position] | ||
|
||
else: | ||
# append character without encrypting | ||
#decryptedtext_utf = decryptedtext_utf + ... | ||
decryptedtext_utf += character | ||
|
||
return decryptedtext_utf |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
__mydoc__ = """ | ||
MyCaesarCipher_Test.py, Ennaayattulla | ||
Tested with PyCharm Community Edition 2019.3 x64, python 3.7 | ||
""" | ||
|
||
from MyCryptoPackage import MyCaesarCipher | ||
|
||
|
||
def run_test(): | ||
print(__mydoc__) | ||
print(MyCaesarCipher.__mydoc__) | ||
|
||
key = 3 | ||
|
||
plaintext = "HELLO" # Q1, Q2 | ||
ciphertext = MyCaesarCipher.encrypt(key, plaintext) | ||
decryptedtext = MyCaesarCipher.decrypt(key, ciphertext) | ||
print("plaintext: " + plaintext) | ||
print("ciphertext: " + ciphertext) | ||
print("decryptedtext: " + decryptedtext + "\n") | ||
|
||
plaintext = "Hello!" # Q1, Q2 | ||
ciphertext = MyCaesarCipher.encrypt(key, plaintext) | ||
decryptedtext = MyCaesarCipher.decrypt(key, ciphertext) | ||
print("plaintext: " + plaintext) | ||
print("ciphertext: " + ciphertext) | ||
print("decryptedtext: " + decryptedtext + "\n") | ||
|
||
plaintext = "Hello123+/=" # Q3 | ||
ciphertext = MyCaesarCipher.encrypt(key, plaintext) | ||
decryptedtext = MyCaesarCipher.decrypt(key, ciphertext) | ||
print("plaintext: " + plaintext) | ||
print("ciphertext: " + ciphertext) | ||
print("decryptedtext: " + decryptedtext + "\n") | ||
|
||
return | ||
|
||
|
||
if __name__ == "__main__": | ||
run_test() |