Python/ciphers/rsa_cipher.py

152 lines
4.7 KiB
Python
Raw Normal View History

import os
import sys
from . import rsa_key_generator as rkg
2016-09-06 12:23:48 +00:00
DEFAULT_BLOCK_SIZE = 128
BYTE_SIZE = 256
2019-10-05 05:14:13 +00:00
2016-09-06 12:23:48 +00:00
def main():
2019-10-05 05:14:13 +00:00
filename = "encrypted_file.txt"
response = input(r"Encrypt\Decrypt [e\d]: ")
2016-09-06 12:23:48 +00:00
2019-10-05 05:14:13 +00:00
if response.lower().startswith("e"):
mode = "encrypt"
elif response.lower().startswith("d"):
mode = "decrypt"
2016-09-06 12:23:48 +00:00
2019-10-05 05:14:13 +00:00
if mode == "encrypt":
if not os.path.exists("rsa_pubkey.txt"):
rkg.makeKeyFiles("rsa", 1024)
2019-10-05 05:14:13 +00:00
message = input("\nEnter message: ")
pubKeyFilename = "rsa_pubkey.txt"
print("Encrypting and writing to %s..." % (filename))
2016-09-06 12:23:48 +00:00
encryptedText = encryptAndWriteToFile(filename, pubKeyFilename, message)
2019-10-05 05:14:13 +00:00
print("\nEncrypted text:")
2016-09-06 12:23:48 +00:00
print(encryptedText)
2019-10-05 05:14:13 +00:00
elif mode == "decrypt":
privKeyFilename = "rsa_privkey.txt"
print("Reading from %s and decrypting..." % (filename))
2016-09-06 12:23:48 +00:00
decryptedText = readFromFileAndDecrypt(filename, privKeyFilename)
2019-10-05 05:14:13 +00:00
print("writing decryption to rsa_decryption.txt...")
with open("rsa_decryption.txt", "w") as dec:
2016-09-06 12:23:48 +00:00
dec.write(decryptedText)
2019-10-05 05:14:13 +00:00
print("\nDecryption:")
2016-09-06 12:23:48 +00:00
print(decryptedText)
def getBlocksFromText(message: int, blockSize: int = DEFAULT_BLOCK_SIZE) -> [int]:
2019-10-05 05:14:13 +00:00
messageBytes = message.encode("ascii")
2016-09-06 12:23:48 +00:00
blockInts = []
for blockStart in range(0, len(messageBytes), blockSize):
blockInt = 0
for i in range(blockStart, min(blockStart + blockSize, len(messageBytes))):
blockInt += messageBytes[i] * (BYTE_SIZE ** (i % blockSize))
blockInts.append(blockInt)
return blockInts
def getTextFromBlocks(
blockInts: [int], messageLength: int, blockSize: int = DEFAULT_BLOCK_SIZE
) -> str:
2016-09-06 12:23:48 +00:00
message = []
for blockInt in blockInts:
blockMessage = []
for i in range(blockSize - 1, -1, -1):
if len(message) + i < messageLength:
asciiNumber = blockInt // (BYTE_SIZE ** i)
blockInt = blockInt % (BYTE_SIZE ** i)
blockMessage.insert(0, chr(asciiNumber))
message.extend(blockMessage)
2019-10-05 05:14:13 +00:00
return "".join(message)
2016-09-06 12:23:48 +00:00
def encryptMessage(
message: str, key: (int, int), blockSize: int = DEFAULT_BLOCK_SIZE
) -> [int]:
2016-09-06 12:23:48 +00:00
encryptedBlocks = []
n, e = key
for block in getBlocksFromText(message, blockSize):
encryptedBlocks.append(pow(block, e, n))
return encryptedBlocks
def decryptMessage(
encryptedBlocks: [int],
messageLength: int,
key: (int, int),
blockSize: int = DEFAULT_BLOCK_SIZE,
) -> str:
2016-09-06 12:23:48 +00:00
decryptedBlocks = []
n, d = key
for block in encryptedBlocks:
decryptedBlocks.append(pow(block, d, n))
return getTextFromBlocks(decryptedBlocks, messageLength, blockSize)
def readKeyFile(keyFilename: str) -> (int, int, int):
with open(keyFilename) as fo:
content = fo.read()
2019-10-05 05:14:13 +00:00
keySize, n, EorD = content.split(",")
2016-09-06 12:23:48 +00:00
return (int(keySize), int(n), int(EorD))
2019-10-05 05:14:13 +00:00
def encryptAndWriteToFile(
messageFilename: str,
keyFilename: str,
message: str,
blockSize: int = DEFAULT_BLOCK_SIZE,
) -> str:
2016-09-06 12:23:48 +00:00
keySize, n, e = readKeyFile(keyFilename)
if keySize < blockSize * 8:
2019-10-05 05:14:13 +00:00
sys.exit(
"ERROR: Block size is %s bits and key size is %s bits. The RSA cipher "
"requires the block size to be equal to or greater than the key size. "
"Either decrease the block size or use different keys."
2019-10-05 05:14:13 +00:00
% (blockSize * 8, keySize)
)
2016-09-06 12:23:48 +00:00
encryptedBlocks = encryptMessage(message, (n, e), blockSize)
for i in range(len(encryptedBlocks)):
encryptedBlocks[i] = str(encryptedBlocks[i])
2019-10-05 05:14:13 +00:00
encryptedContent = ",".join(encryptedBlocks)
encryptedContent = f"{len(message)}_{blockSize}_{encryptedContent}"
2019-10-05 05:14:13 +00:00
with open(messageFilename, "w") as fo:
fo.write(encryptedContent)
2016-09-06 12:23:48 +00:00
return encryptedContent
def readFromFileAndDecrypt(messageFilename: str, keyFilename: str) -> str:
2016-09-06 12:23:48 +00:00
keySize, n, d = readKeyFile(keyFilename)
with open(messageFilename) as fo:
content = fo.read()
2019-10-05 05:14:13 +00:00
messageLength, blockSize, encryptedMessage = content.split("_")
2016-09-06 12:23:48 +00:00
messageLength = int(messageLength)
blockSize = int(blockSize)
if keySize < blockSize * 8:
2019-10-05 05:14:13 +00:00
sys.exit(
"ERROR: Block size is %s bits and key size is %s bits. The RSA cipher "
"requires the block size to be equal to or greater than the key size. "
"Did you specify the correct key file and encrypted file?"
2019-10-05 05:14:13 +00:00
% (blockSize * 8, keySize)
)
2016-09-06 12:23:48 +00:00
encryptedBlocks = []
2019-10-05 05:14:13 +00:00
for block in encryptedMessage.split(","):
2016-09-06 12:23:48 +00:00
encryptedBlocks.append(int(block))
return decryptMessage(encryptedBlocks, messageLength, (n, d), blockSize)
2019-10-05 05:14:13 +00:00
if __name__ == "__main__":
2016-09-06 12:23:48 +00:00
main()