Reputation: 983
I have been looking for sometime on how to encrypt and decrypt a string. But most of it is in 2.7 and anything that is using 3.2 is not letting me print it or add it to a string.
So what I'm trying to do is the following:
mystring = "Hello stackoverflow!"
encoded = encode(mystring,"password")
print(encoded)
jgAKLJK34t3g (a bunch of random letters)
decoded = decode(encoded,"password")
print(decoded)
Hello stackoverflow!
Is there anyway of doing this, using python 3.X and when the string is encoded it's still a string, not any other variable type.
Upvotes: 82
Views: 263506
Reputation: 1868
Here's a simple algorithm akin to a one time pad...for illustrative purposes how you might use one str
to encrypt another and then decrypt the cipher text.
def encode(secret: str, key: str) -> str:
"""use `key` to encrypt `secret`"""
encoded_secret_arr = []
for idx, c in enumerate(secret):
encoded_secret_arr.append(chr(ord(c) + ord(key[idx % len(key)])))
return "".join(encoded_secret_arr)
def decode(encoded_secret: str, key: str) -> str:
"""use `key` to decrypt encoded_secret)"""
secret_arr = []
for idx, c in enumerate(encoded_secret):
secret_arr.append(chr(ord(c) - ord(key[idx % len(key)])))
return "".join(secret_arr)
assert decode(encode("secret", "key"), "key") == "secret"
Upvotes: -1
Reputation: 171
Try this:
Python Cryptography Toolkit (pycrypto) is required
$ pip install pycrypto
pycrypto
package is outdated and has not been maintained since 2014.
There is a drop-in replacement package called pycryptodome
.
$ pip install pycryptodome
And the code below flawlessly works on python 3.8
Code:
from Crypto.Cipher import AES
from base64 import b64encode, b64decode
class Crypt:
def __init__(self, salt='SlTKeYOpHygTYkP3'):
self.salt = salt.encode('utf8')
self.enc_dec_method = 'utf-8'
def encrypt(self, str_to_enc, str_key):
try:
aes_obj = AES.new(str_key.encode('utf-8'), AES.MODE_CFB, self.salt)
hx_enc = aes_obj.encrypt(str_to_enc.encode('utf8'))
mret = b64encode(hx_enc).decode(self.enc_dec_method)
return mret
except ValueError as value_error:
if value_error.args[0] == 'IV must be 16 bytes long':
raise ValueError('Encryption Error: SALT must be 16 characters long')
elif value_error.args[0] == 'AES key must be either 16, 24, or 32 bytes long':
raise ValueError('Encryption Error: Encryption key must be either 16, 24, or 32 characters long')
else:
raise ValueError(value_error)
def decrypt(self, enc_str, str_key):
try:
aes_obj = AES.new(str_key.encode('utf8'), AES.MODE_CFB, self.salt)
str_tmp = b64decode(enc_str.encode(self.enc_dec_method))
str_dec = aes_obj.decrypt(str_tmp)
mret = str_dec.decode(self.enc_dec_method)
return mret
except ValueError as value_error:
if value_error.args[0] == 'IV must be 16 bytes long':
raise ValueError('Decryption Error: SALT must be 16 characters long')
elif value_error.args[0] == 'AES key must be either 16, 24, or 32 bytes long':
raise ValueError('Decryption Error: Encryption key must be either 16, 24, or 32 characters long')
else:
raise ValueError(value_error)
Usage:
test_crpt = Crypt()
test_text = """Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum."""
test_key = 'MyKey4TestingYnP'
test_enc_text = test_crpt.encrypt(test_text, test_key)
test_dec_text = test_crpt.decrypt(test_enc_text, test_key)
print(f'Encrypted:{test_enc_text} Decrypted:{test_dec_text}')
Upvotes: 17
Reputation: 1
For Encryption
def encrypt(my_key=KEY, my_iv=IV, my_plain_text=PLAIN_TEXT):
key = binascii.unhexlify('ce975de9294067470d1684442555767fcb007c5a3b89927714e449c3f66cb2a4')
iv = binascii.unhexlify('9aaecfcf7e82abb8118d8e567d42ee86')
padder = PKCS7Padder()
padded_text = padder.encode(my_plain_text)
encryptor = AES.new(key, AES.MODE_CBC, iv, segment_size=128) # Initialize encryptor
result = encryptor.encrypt(padded_text)
return {
"plain": my_plain_text,
"key": binascii.hexlify(key),
"iv": binascii.hexlify(iv),
"ciphertext": result
}
For Decryption:
def decrypt(my_key=KEY, my_iv=IV, encryptText=encrypttext):
key = binascii.unhexlify(my_key)
iv = binascii.unhexlify(my_iv)
encryptor = AES.new(key, AES.MODE_CBC, iv, segment_size=128) # Initialize encryptor
result = encryptor.decrypt(binascii.a2b_hex(encryptText))
padder = PKCS7Padder()
decryptText=padder.decode(result)
return {
"plain": encryptText,
"key": binascii.hexlify(key),
"iv": binascii.hexlify(iv),
"decryptedTest": decryptText
}
Upvotes: -4
Reputation: 8673
First, we need to install the cryptography library:
pip3 install cryptography
From the cryptography library, we need to import Fernet
and start generating a key - this key is required for symmetric encryption/decryption.
To generate a key, we call the generate_key()
method.
You need to keep this key in a safe place. If you lose the key, you won't be able to decrypt the data that was encrypted with this key.
Once we have generated a key, we need to load the key with load_key()
This is a three step process:
encrypt()
methodfrom cryptography.fernet import Fernet
def generate_key():
"""
Generates a key and save it into a file
"""
key = Fernet.generate_key()
with open("secret.key", "wb") as key_file:
key_file.write(key)
def load_key():
"""
Load the previously generated key
"""
return open("secret.key", "rb").read()
def encrypt_message(message):
"""
Encrypts a message
"""
key = load_key()
encoded_message = message.encode()
f = Fernet(key)
encrypted_message = f.encrypt(encoded_message)
print(encrypted_message)
if __name__ == "__main__":
# generate_key() # execute only once
encrypt_message("Hello stackoverflow!")
output:
b'gAAAAABgLX7Zj-kn-We2BI_c9NQhEtfJEnHUVhVqtiqjkDi5dgJafj-_8QUDyeNS2zsJTdBWg6SntRJOjOM1U5mIxxsGny7IEGqpVVdHwheTnwzSBlgpb80='
To decrypt the message, we just call the decrypt()
method from the Fernet
library. Remember, we also need to load the key as well, because the key is needed to decrypt the message.
from cryptography.fernet import Fernet
def load_key():
"""
Load the previously generated key
"""
return open("secret.key", "rb").read()
def decrypt_message(encrypted_message):
"""
Decrypts an encrypted message
"""
key = load_key()
f = Fernet(key)
decrypted_message = f.decrypt(encrypted_message)
print(decrypted_message.decode())
if __name__ == "__main__":
decrypt_message(b'gAAAAABgLX7Zj-kn-We2BI_c9NQhEtfJEnHUVhVqtiqjkDi5dgJafj-_8QUDyeNS2zsJTdBWg6SntRJOjOM1U5mIxxsGny7IEGqpVVdHwheTnwzSBlgpb80=')
output:
Hello stackoverflow!
Your password is in the secret.key
in a form similar to the password below:
B8wtXqwBA_zb2Iaz5pW8CIQIwGSYSFoBiLsVz-vTqzw=
Upvotes: 15
Reputation: 291
You can do this easily by using the library cryptocode
. Here is how you install:
pip install cryptocode
Encrypting a message (example code):
import cryptocode
encoded = cryptocode.encrypt("mystring","mypassword")
## And then to decode it:
decoded = cryptocode.decrypt(encoded, "mypassword")
Documentation can be found here
Upvotes: 16
Reputation: 191
Although its very old, but I thought of sharing another idea to do this:
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
password = ("anything")
hash_obj = SHA256.new(password.encode('utf-8'))
hkey = hash_obj.digest()
def encrypt(info):
msg = info
BLOCK_SIZE = 16
PAD = "{"
padding = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PAD
cipher = AES.new(hkey, AES.MODE_ECB)
result = cipher.encrypt(padding(msg).encode('utf-8'))
return result
msg = "Hello stackoverflow!"
cipher_text = encrypt(msg)
print(cipher_text)
def decrypt(info):
msg = info
PAD = "{"
decipher = AES.new(hkey, AES.MODE_ECB)
pt = decipher.decrypt(msg).decode('utf-8')
pad_index = pt.find(PAD)
result = pt[: pad_index]
return result
plaintext = decrypt(cipher_text)
print(plaintext)
Outputs:
> b'\xcb\x0b\x8c\xdc#\n\xdd\x80\xa6|\xacu\x1dEg;\x8e\xa2\xaf\x80\xea\x95\x80\x02\x13\x1aem\xcb\xf40\xdb'
> Hello stackoverflow!
Upvotes: 3
Reputation: 949
I had troubles compiling all the most commonly mentioned cryptography libraries on my Windows 7 system and for Python 3.5.
This is the solution that finally worked for me.
from cryptography.fernet import Fernet
key = Fernet.generate_key() #this is your "password"
cipher_suite = Fernet(key)
encoded_text = cipher_suite.encrypt(b"Hello stackoverflow!")
decoded_text = cipher_suite.decrypt(encoded_text)
Upvotes: 80
Reputation: 47
You may use Fernet as follows:
from cryptography.fernet import Fernet
key = Fernet.generate_key()
f = Fernet(key)
encrypt_value = f.encrypt(b"YourString")
f.decrypt(encrypt_value)
Upvotes: 1
Reputation: 5939
Take a look at PyCrypto. It supports Python 3.2 and does exactly what you want.
From their pip website:
>>> from Crypto.Cipher import AES
>>> obj = AES.new('This is a key123', AES.MODE_CFB, 'This is an IV456')
>>> message = "The answer is no"
>>> ciphertext = obj.encrypt(message)
>>> ciphertext
'\xd6\x83\x8dd!VT\x92\xaa`A\x05\xe0\x9b\x8b\xf1'
>>> obj2 = AES.new('This is a key123', AES.MODE_CFB, 'This is an IV456')
>>> obj2.decrypt(ciphertext)
'The answer is no'
If you want to encrypt a message of an arbitrary size use AES.MODE_CFB
instead of AES.MODE_CBC
.
Upvotes: 41