Encrypt string in Python - python

I need to encrypt a small string in Python. Is it possible to use a secret key to encrypt the string? Is there a good way to do this and achieve a reasonable encryption level using only Python libraries? Could you show me how to do this?
My knowledge about cryptography is quite basic.

Take a look at py-bcrypt. Perhaps it will meet your needs. From the web site:
py-bcrypt is a Python wrapper of OpenBSD's Blowfish password hashing code, as described in "A Future-Adaptable Password Scheme" by Niels Provos and David Mazières

KeyCzar has a nice interface and should meet your requirements. From the home page:
Keyczar is an open source cryptographic toolkit designed to make it easier and safer for devlopers to use cryptography in their applications. Keyczar supports authentication and encryption with both symmetric and asymmetric keys
crypter = Crypter.Read("/path/to/your/keys")
ciphertext = crypter.Encrypt("Secret message")

I solved this by using a lightweight XTEA library that i found on ASPN. It doesn't require any additional Python libraries and is quite simple to implement whilst acheiving a resonable encryption level.

I recently created a piece of code that does pretty much what your saying. It takes a codeword such as 'abc'gets the values (1, 2, 3) and then adds them to each letter in the word to encrypt. So if 'abc' was the codeword and 'bcd' the text to encrypt. (1+2 =3 2+3 =5 and 3+4 = 7) so the output would then be 'ceg'
codeword = input('Enter codeword : ')
codeword = codeword.replace(" ", "")
encrypt = input('Enter text to encrypt : ')
encrypt = encrypt.replace(" ", "")
j = 0
for i in codeword:
print(chr(ord(encrypt[j])+ ord(codeword[j])-96))
j+=1

Here's my code:
from cryptography.fernet import Fernet
import pyperclip
print("For this program to work, please send the file named 'pwkey' and the encrypted code to the other user.")
key = Fernet.generate_key()
file = open('pwkey', 'wb')
file.write(key)
file.close()
print('File Generated')
original = input('Enter message>>>')
message = original.encode()
f = Fernet(key)
encrypted = f.encrypt(message)
encrypted = encrypted.decode("ascii")
print('Encrypted:', encrypted)
pyperclip.copy(encrypted)
print('Please tell the other user to input the encrypted code in the Decrypt program')
print('(Code copied to Clipboard)')
print("Note: Please delete the 'pwkey' file after sending it to the other user. It
is for one-time use only.")
And decrypting
# Decrypt
from cryptography.fernet import Fernet
print("For this program to work, make sure you have the file named 'pwkey' in your Python folder and the encrypted "
"code.")
file = open('pwkey', 'rb')
key = file.read()
file.close()
print('Key Retrieved')
encrypted = input('Please input your encrypted code>>>')
encrypted = bytes(encrypted, 'utf-8')
f = Fernet(key)
decrypted = f.decrypt(encrypted)
decrypted = decrypted.decode()
print('Decrypted Message:')
print(decrypted)
print("Note: Please delete the 'pwkey' file after getting the decrypted message. It is for one-time use only.")

I would do this with the easy to use cryptocode library (https://github.com/gdavid7/cryptocode).
Encrypting and decrypting is relatively simple compared to other libraries:
## Encrypting:
>>> import cryptocode
>>> myEncryptedMessage = cryptocode.encrypt("I like trains", "password123")
>>> print(myEncryptedMessage)
M+Wykmlub0z7FhEdmA==*PvAbXRNx0SiSDHHxLsKZ5w==*ihQM/fdkgrX3G+yOItyAUQ==*QFNDmuUP1ysgo01/P2MNpg==
## Decrypting:
>>> import cryptocode
>>> myDecryptedMessage = cryptocode.decrypt("M+Wykmlub0z7FhEdmA==*PvAbXRNx0SiSDHHxLsKZ5w==*ihQM/fdkgrX3G+yOItyAUQ==*QFNDmuUP1ysgo01/P2MNpg==", "password123")
>>> print(myDecryptedMessage)
I like trains
The only large disadvantage to this library over others is that it does not have many options to change around your string compared to other cryptography libraries. But it is perfect for a lot of people who just want an abstraction, and don't need to configure custom settings.

Related

Hash won't match to dictionary when hashed with SHA512. What am I missing?

I'm trying to crack an SHA512 hash by matching it to a dictionary using python. However, I cannot get the hash to match any of the words.
I think the issue is with the salt and dictionary words being incorrectly inputted to hashlib.sha512():
I have split out the hash with shadow.split(":")[1] however I cannot correctly parse down from here, I have tried splitting on "$" to seperate the password and salt in addtion to blindly splitting on "." and "/" to no avail.
My code:
#! usr/bin/python
import hashlib
dictionary = ["apple", "orange", "egg", "lemon", "grapes", "secret", "strawberry", "password"]
shadow = "root:$6$ms32yIGN$NyXj0YofkK14MpRwFHvXQW0yvUid.slJtgxHE2EuQqgD74S/GaGGs5VCnqeC.bS0MzTf/EFS3uspQMNeepIAc.:15503:0:99999:7:::"
def testPass(cryptPass):
for word in dictionary:
salt = cryptPass.split("$")[2]
cryptWord = hashlib.sha512(salt + word).hexdigest()
print("\nhashing word: '" + word + "'' with salt: '" + salt + "' -> " + cryptWord)
if cryptWord == cryptPass :
print("[+] Found Password: " + word + "\n")
return
print("[-] Password Not Found.\n")
def main():
user = shadow.split(":")[0]
cryptPass = shadow.split(":")[1]
print("Cracking password for:" + user)
print("Hashed Password: " + cryptPass)
testPass(cryptPass)
if __name__ == '__main__':
main()
This is a challenge in the textbook Violent Python by TJ O'Connor (p23)
If i understand right the You are trying to Break Linux shadow password by brute force. which use sha512 at it's core but this is not the end of story. In order to make hashed password more resistant to brute force attacks Linux use another implementation something like Scrypt or PBKDF2 (not sure what implementation exactly does recent Linux versions use for $6$). They in essence try to hash password several times to make brute force more time consuming and CPU intensive. So, hashing with sha512 wont result in same password hash as one saved in Linux shadow file. You can use a library like crypt which you pass to it password, salt and algorithm needed as:
import crypt
password="hunter2"
hashing_scheme_with_salt="$6$ABCD1234$"
res = crypt.crypt(password, hashing_scheme_with_salt)
print(res)
# split and compare here
which will use the Needed algorithm that Linux use.
EDIT: Linux use crypt function and default to 5000 round for sha256 and sha512 since glibc 2.7 according to the documentation

Matching Signing between Python and Ruby

I have been trying for a few days to validate some message signed with a private key in python. Note that the message has been signed using Ruby.
When I sign the same message in python I can verify it no problem. Note that I have already validated that the hash are the same.
Python code:
string_to_encrypt = b"aaaaabbbbbaaaaabbbbbaaaaabbbbbCC"
sha1 = SHA.new()
sha1.update(string_to_encrypt)
# load private key
pkey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, open('./license.pem', 'rb').read())
sign_ssl = OpenSSL.crypto.sign(pkey, sha1.digest(), 'RSA-SHA1')
b64_ssl = base64.b64encode(sign_ssl)
Ruby:
string_to_encrypt = "aaaaabbbbbaaaaabbbbbaaaaabbbbbCC"
sha1 = Digest::SHA1.digest(string_to_encrypt)
#sign it
private_key_file = File.join(File.dirname(__FILE__), 'license.pem')
rsa = OpenSSL::PKey::RSA.new(File.read(private_key_file))
signed_key = rsa.private_encrypt(sha1)
#update the license string with it
x = Base64.strict_encode64(signed_key)
I would expect b64_ssl and x to contain the same value and they don't. Could someone explain to me what I missing there?
Neither of these code snippets is actually producing the correct signature.
In the Ruby OpenSSL library you want to be using the sign method, not the private_encrypt method, which is a low level operation that doesn’t do everything required to produce a valid signature.
In both libraries the sign operation performs the hashing for you, you don’t need to do this beforehand. In fact your Python code is actually hashing the data twice.
Try the following Python code:
import OpenSSL
import base64
string_to_encrypt = b"aaaaabbbbbaaaaabbbbbaaaaabbbbbCC"
# load private key
pkey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, open('./license.pem', 'rb').read())
sign_ssl = OpenSSL.crypto.sign(pkey, string_to_encrypt, 'SHA1')
b64_ssl = base64.b64encode(sign_ssl)
print(b64_ssl.decode())
which produces the same output as this Ruby code:
require 'openssl'
require 'base64'
string_to_encrypt = "aaaaabbbbbaaaaabbbbbaaaaabbbbbCC"
#sign it
private_key_file = File.join(File.dirname(__FILE__), 'license.pem')
rsa = OpenSSL::PKey::RSA.new(File.read(private_key_file))
signed_key = rsa.sign('sha1', string_to_encrypt)
#update the license string with it
x = Base64.strict_encode64(signed_key)
puts x

Python AES encryption

I am trying to get a python program that decrypts some Base64-encoded, encrypted using AES-128 in ECB mode, text.
So, I am using this tutorial: http://docs.python-guide.org/en/latest/scenarios/crypto/ to get started.
It contains this code:
from Crypto.Cipher import AES
# Encryption
encryption_suite = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
cipher_text = encryption_suite.encrypt("A really secret message. Not for prying eyes.")
# Decryption
decryption_suite = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
plain_text = decryption_suite.decrypt(cipher_text)
I have copied the code into a aes_2.py file. And, I have run it using: sudo python3 aes_2.py
I get:
Traceback (most recent call last):
File "aes_2.py", line 21, in <module>
cipher_text = encryption_suite.encrypt("A really secret message. Not for prying eyes.")
File "/usr/local/lib/python3.5/dist-packages/Crypto/Cipher/blockalgo.py", line 244, in encrypt
return self._cipher.encrypt(plaintext)
ValueError: Input strings must be a multiple of 16 in length
EDIT 1
I have a file that I was told to decrypt. I was given a key and the file and some specs on the decryption. This site decrypts it: http://aesencryption.net/ when I enter the key, 128 Bit, and the text into the site.
For this code above. I have a couple questions. What should I put for 'This is an IV456' and how do I specify what Bit level it is in this code?
You're using AES.MODE_CBC which means that your input string i.e. 'This is a key123' must be a multiple of 16 bytes.
If you want to continue using this mode then you will need to pad your string. This git repo is a great example of AES encryption using padding in CBC mode.

python function for retrieving key and encryption

M2Crypto package is not showing the 'recipient_public_key.pem' file at linux terminal.
How do I get/connect with recipient public key.
Exactly, I need to check how can I open this file through linux commands.
import M2Crypto
def encrypt():
recip = M2Crypto.RSA.load_pub_key(open('recipient_public_key.pem','rb').read())
print recip;
plaintext = whatever i need to encrypt
msg = recip.public_encrypt(plaintext,RSA.pkcs1_padding)
print msg;
after calling the function its not giving any output and even any error
i also tried as 'Will' said
pk = open('public_key.pem','rb').read()
print pk;
rsa = M2Crypto.RSA.load_pub_key(pk)
what is the mistake I am not getting?
I have never used M2Crypto, but according to the API documentation, load_pub_key expects the file name as the argument, not the key itself. Try
recip = M2Crypto.RSA.load_pub_key('recipient_public_key.pem')

Python Authentication API

I'm looking for a python library that will help me to create an authentication method for a desktop app I'm writing.
I have found several method in web framework such as django or turbogears.
I just want a kind of username-password association stored into a local file.
I can write it by myself, but I'm really it already exists and will be a better solution (I'm not very fluent with encryption).
dbr said:
def hash_password(password):
"""Returns the hashed version of a string
"""
return hasher.new( str(password) ).hexdigest()
This is a really insecure way to hash passwords. You don't want to do this. If you want to know why read the Bycrypt Paper by the guys who did the password hashing system for OpenBSD. Additionally if want a good discussion on how passwords are broken check out this interview with the author of Jack the Ripper (the popular unix password cracker).
Now B-Crypt is great but I have to admit I don't use this system because I didn't have the EKS-Blowfish algorithm available and did not want to implement it my self. I use a slightly updated version of the FreeBSD system which I will post below. The gist is this. Don't just hash the password. Salt the password then hash the password and repeat 10,000 or so times.
If that didn't make sense here is the code:
#note I am using the Python Cryptography Toolkit
from Crypto.Hash import SHA256
HASH_REPS = 50000
def __saltedhash(string, salt):
sha256 = SHA256.new()
sha256.update(string)
sha256.update(salt)
for x in xrange(HASH_REPS):
sha256.update(sha256.digest())
if x % 10: sha256.update(salt)
return sha256
def saltedhash_bin(string, salt):
"""returns the hash in binary format"""
return __saltedhash(string, salt).digest()
def saltedhash_hex(string, salt):
"""returns the hash in hex format"""
return __saltedhash(string, salt).hexdigest()
For deploying a system like this the key thing to consider is the HASH_REPS constant. This is the scalable cost factor in this system. You will need to do testing to determine what is the exceptable amount of time you want to wait for each hash to be computed versus the risk of an offline dictionary based attack on your password file.
Security is hard, and the method I present is not the best way to do this, but it is significantly better than a simple hash. Additionally it is dead simple to implement. So even you don't choose a more complex solution this isn't the worst out there.
hope this helps,
Tim
I think you should make your own authentication method as you can make it fit your application best but use a library for encryption, such as pycrypto or some other more lightweight library.
btw, if you need windows binaries for pycrypto you can get them here
Treat the following as pseudo-code..
try:
from hashlib import sha as hasher
except ImportError:
# You could probably exclude the try/except bit,
# but older Python distros dont have hashlib.
try:
import sha as hasher
except ImportError:
import md5 as hasher
def hash_password(password):
"""Returns the hashed version of a string
"""
return hasher.new( str(password) ).hexdigest()
def load_auth_file(path):
"""Loads a comma-seperated file.
Important: make sure the username
doesn't contain any commas!
"""
# Open the file, or return an empty auth list.
try:
f = open(path)
except IOError:
print "Warning: auth file not found"
return {}
ret = {}
for line in f.readlines():
split_line = line.split(",")
if len(split_line) > 2:
print "Warning: Malformed line:"
print split_line
continue # skip it..
else:
username, password = split_line
ret[username] = password
#end if
#end for
return ret
def main():
auth_file = "/home/blah/.myauth.txt"
u = raw_input("Username:")
p = raw_input("Password:") # getpass is probably better..
if auth_file.has_key(u.strip()):
if auth_file[u] == hash_password(p):
# The hash matches the stored one
print "Welcome, sir!"
Instead of using a comma-separated file, I would recommend using SQLite3 (which could be used for other settings and such.
Also, remember that this isn't very secure - if the application is local, evil users could probably just replace the ~/.myauth.txt file.. Local application auth is difficult to do well. You'll have to encrypt any data it reads using the users password, and generally be very careful.
If you want simple, then use a dictionary where the keys are the usernames and the values are the passwords (encrypted with something like SHA256). Pickle it to/from disk (as this is a desktop application, I'm assuming the overhead of keeping it in memory will be negligible).
For example:
import pickle
import hashlib
# Load from disk
pwd_file = "mypasswords"
if os.path.exists(pwd_file):
pwds = pickle.load(open(pwd_file, "rb"))
else:
pwds = {}
# Save to disk
pickle.dump(pwds, open(pwd_file, "wb"))
# Add password
pwds[username] = hashlib.sha256(password).hexdigest()
# Check password
if pwds[username] = hashlib.sha256(password).hexdigest():
print "Good"
else:
print "No match"
Note that this stores the passwords as a hash - so they are essentially unrecoverable. If you lose your password, you'd get allocated a new one, not get the old one back.
import hashlib
import random
def gen_salt():
salt_seed = str(random.getrandbits(128))
salt = hashlib.sha256(salt_seed).hexdigest()
return salt
def hash_password(password, salt):
h = hashlib.sha256()
h.update(salt)
h.update(password)
return h.hexdigest()
#in datastore
password_stored_hash = "41e2282a9c18a6c051a0636d369ad2d4727f8c70f7ddeebd11e6f49d9e6ba13c"
salt_stored = "fcc64c0c2bc30156f79c9bdcabfadcd71030775823cb993f11a4e6b01f9632c3"
password_supplied = 'password'
password_supplied_hash = hash_password(password_supplied, salt_stored)
authenticated = (password_supplied_hash == password_stored_hash)
print authenticated #True
see also gae-authenticate-to-a-3rd-party-site
Use " md5 " it's much better than base64
>>> import md5
>>> hh = md5.new()
>>> hh.update('anoop')
>>> hh.digest
<built-in method digest of _hashlib.HASH object at 0x01FE1E40>

Categories

Resources