很难在Google上找到对此的直接答案。
我想要收集来自用户的文字和消息,例如1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc
hello world
。
然后我希望能够以某种方式使用文本加密/解密消息,以便我可以将其保存在我的数据库中,而不用担心如果我的网站被黑客攻击,数据会被暴露,
encrypt('1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc', 'hello world')
decrypt('1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc', <encrypted_text>)
有没有一种简单的方法可以通过python实现这一点,请有人提供/指导我一个例子。
也许是如何使用诸如'1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc'
之类的种子创建公钥/私钥对的示例?
非常感谢提前:)
编辑:为了清楚起见我正在寻找一种以威慑方式加密我的用户数据而不会混淆消息的方法。
如果这意味着我必须使用文本1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc
作为种子动态生成PGP / GPG pub / pri密钥对,那么这很好,但是这样做的方法是什么?
答案 0 :(得分:17)
以下是如何在CBC模式下正确完成,包括PKCS#7填充:
import base64
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto import Random
def encrypt(key, source, encode=True):
key = SHA256.new(key).digest() # use SHA-256 over our key to get a proper-sized AES key
IV = Random.new().read(AES.block_size) # generate IV
encryptor = AES.new(key, AES.MODE_CBC, IV)
padding = AES.block_size - len(source) % AES.block_size # calculate needed padding
source += bytes([padding]) * padding # Python 2.x: source += chr(padding) * padding
data = IV + encryptor.encrypt(source) # store the IV at the beginning and encrypt
return base64.b64encode(data).decode("latin-1") if encode else data
def decrypt(key, source, decode=True):
if decode:
source = base64.b64decode(source.encode("latin-1"))
key = SHA256.new(key).digest() # use SHA-256 over our key to get a proper-sized AES key
IV = source[:AES.block_size] # extract the IV from the beginning
decryptor = AES.new(key, AES.MODE_CBC, IV)
data = decryptor.decrypt(source[AES.block_size:]) # decrypt
padding = data[-1] # pick the padding value from the end; Python 2.x: ord(data[-1])
if data[-padding:] != bytes([padding]) * padding: # Python 2.x: chr(padding) * padding
raise ValueError("Invalid padding...")
return data[:-padding] # remove the padding
它设置为使用bytes
数据,因此如果您想加密字符串或使用字符串密码,请确保在将它们传递给方法之前encode()
使用正确的编解码器。如果将encode
参数保留为True
,encrypt()
输出将为base64编码字符串,decrypt()
源也应为base64字符串。
现在,如果您将其测试为:
my_password = b"secret_AES_key_string_to_encrypt/decrypt_with"
my_data = b"input_string_to_encrypt/decrypt"
print("key: {}".format(my_password))
print("data: {}".format(my_data))
encrypted = encrypt(my_password, my_data)
print("\nenc: {}".format(encrypted))
decrypted = decrypt(my_password, encrypted)
print("dec: {}".format(decrypted))
print("\ndata match: {}".format(my_data == decrypted))
print("\nSecond round....")
encrypted = encrypt(my_password, my_data)
print("\nenc: {}".format(encrypted))
decrypted = decrypt(my_password, encrypted)
print("dec: {}".format(decrypted))
print("\ndata match: {}".format(my_data == decrypted))
您的输出类似于:
key: b'secret_AES_key_string_to_encrypt/decrypt_with'
data: b'input_string_to_encrypt/decrypt'
enc: 7roSO+P/4eYdyhCbZmraVfc305g5P8VhDBOUDGrXmHw8h5ISsS3aPTGfsTSqn9f5
dec: b'input_string_to_encrypt/decrypt'
data match: True
Second round....
enc: BQm8FeoPx1H+bztlZJYZH9foI+IKAorCXRsMjbiYQkqLWbGU3NU50OsR+L9Nuqm6
dec: b'input_string_to_encrypt/decrypt'
data match: True
证明每次相同的密钥和相同的数据仍会产生不同的密文。
现在,这比欧洲央行要好得多,但......如果你打算用它进行交流 - 不要!这更多的是解释它应该如何构建,而不是真正用于生产环境,特别是不用于通信,因为它缺少一个关键的成分 - 消息认证。随意使用它,但你不应该使用自己的加密,有经过严格审查的协议可以帮助你避免常见的陷阱,你应该使用它们。
答案 1 :(得分:1)
基于zwer的答案,但当源数恰好是16的倍数时解决了一个小错误。
代码:
from builtins import bytes
import base64
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto import Random
def encrypt(string, password):
"""
It returns an encrypted string which can be decrypted just by the
password.
"""
key = password_to_key(password)
IV = make_initialization_vector()
encryptor = AES.new(key, AES.MODE_CBC, IV)
# store the IV at the beginning and encrypt
return IV + encryptor.encrypt(pad_string(string))
def decrypt(string, password):
key = password_to_key(password)
# extract the IV from the beginning
IV = string[:AES.block_size]
decryptor = AES.new(key, AES.MODE_CBC, IV)
string = decryptor.decrypt(string[AES.block_size:])
return unpad_string(string)
def password_to_key(password):
"""
Use SHA-256 over our password to get a proper-sized AES key.
This hashes our password into a 256 bit string.
"""
return SHA256.new(password).digest()
def make_initialization_vector():
"""
An initialization vector (IV) is a fixed-size input to a cryptographic
primitive that is typically required to be random or pseudorandom.
Randomization is crucial for encryption schemes to achieve semantic
security, a property whereby repeated usage of the scheme under the
same key does not allow an attacker to infer relationships
between segments of the encrypted message.
"""
return Random.new().read(AES.block_size)
def pad_string(string, chunk_size=AES.block_size):
"""
Pad string the peculirarity that uses the first byte
is used to store how much padding is applied
"""
assert chunk_size <= 256, 'We are using one byte to represent padding'
to_pad = (chunk_size - (len(string) + 1)) % chunk_size
return bytes([to_pad]) + string + bytes([0] * to_pad)
def unpad_string(string):
to_pad = string[0]
return string[1:-to_pad]
def encode(string):
"""
Base64 encoding schemes are commonly used when there is a need to encode
binary data that needs be stored and transferred over media that are
designed to deal with textual data.
This is to ensure that the data remains intact without
modification during transport.
"""
return base64.b64encode(string).decode("latin-1")
def decode(string):
return base64.b64decode(string.encode("latin-1"))
试验:
def random_text(length):
def rand_lower():
return chr(randint(ord('a'), ord('z')))
string = ''.join([rand_lower() for _ in range(length)])
return bytes(string, encoding='utf-8')
def test_encoding():
string = random_text(100)
assert encode(string) != string
assert decode(encode(string)) == string
def test_padding():
assert len(pad_string(random_text(14))) == 16
assert len(pad_string(random_text(15))) == 16
assert len(pad_string(random_text(16))) == 32
def test_encryption():
string = random_text(100)
password = random_text(20)
assert encrypt(string, password) != string
assert decrypt(encrypt(string, password), password) == string
答案 2 :(得分:0)
您可以使用标准Python库中的两个内置函数来完成此操作。第一个是函数 ord(),它将一个unicode字符串字符作为单个输入参数,并将其转换为相应的unicode代码(整数)。提供了两个使用此函数的简单示例:
>>> ord('a')
97
>>> ord('b')
98
然后,你还有ord()的反函数: chr()。正如你可以想象它一直有效:它有一个unicode代码作为输入(整数)并获得相应的unicode字符(字符串):
>>> chr(97)
'a'
>>> chr(98)
'b'
然后你可以通过添加或减去一些任意整数来做一个简单的描述...在这种情况下,数字2:
注意:请注意不要发出非常大的值,否则你会得到一个错误ID,例如,你会得到一个负面的错误。
def encrypt(message):
newS=''
for car in message:
newS=newS+chr(ord(car)+2)
return newS
print(encrypt('hello world'))
得到结果:
jgnnq"yqtnf
现在您可以复制并通过相同的功能并生成解密功能。在这种情况下,显然需要减去2:
def decrypt(message):
newS=''
for car in message:
newS=newS+chr(ord(car)-2)
return newS
print(decrypt('jgnnq"yqtnf'))
结果将是原始消息:
'hello world'
这是加密非程序员消息的好方法。但是,任何具有一点编程知识的人都可以编写一个程序来改变我们使用的整数,直到他们发现我们刚刚添加(2)到unicode字符来加密代码......
为了避免这种情况,我会提出两个更复杂的选择。
1。第一个是最简单的:它包括根据字符的位置对chr函数应用不同的和值(例如,当每个unicode代码加2时)在字符串中占据一个偶数位置,当坐在一个奇数位置时减去3。
2. 第二个将产生最大安全性。它将包括为每个字符添加或减去每个unicode代码,以便为每个字符随机生成一个数字。它需要存储一组值来描述消息。那么,请确保第三方无法使用此数组值。
它可以解决 1 。:
def encryptHard(message):
newS=''
for i in range(len(message)):
if i%2==0:
newS=newS+chr(ord(message[i])+2)
else:
newS=newS+chr(ord(message[i])-3)
return newS
print(encryptHard('hello world'))
结果将是:
jbniqyltif
由于信息特此隐私,解密脚本显而易见,因此我不会因为应对,改变和改变两个值而烦恼。
最后,让我们对第二个更复杂的替代方案进行深入分析。有了这个,我们可以说征兵几乎是不可挽回的。我们的想法是通过在0到255之间合成的随机数来改变我们为每个unicode代码添加或减去的值(这是chr()函数允许的数字范围,所以不要尝试使用其他数字o你将肯定会收到错误。)
在这种情况下,我的建议也随机化了操作(求和或减),并避免最终的数字为0(即我们得到一个原始字符)。最后,它还会返回一个列表,其中包含已被减去的数字,这是为了解密消息所需的内容。
如果使用长度为 n 的相同消息调用此函数两次,则获得相同加密消息的可能性接近 255 ^ n ...所以不要担心(我说有点,因为所创建的算法实际上会在低端或高端值范围内生成更多重复值,例如,如果最常见的字符不在此分布的中心位置unicode caracrer set(从0到255),情况确实如此。但是,该程序虽然不完美,但可以完美地工作并保护信息。
import random as r
def encryptSuperHard(message):
newS=''
l_trans=[]
for car in message:
code=ord(car)
add_subtract=r.choice([True,False])
if add_subtract:
transpose=r.randint(0,code-1)
newS=newS+chr(code-transpose)
l_trans=l_trans+[-transpose]
else:
transpose=r.randint(code+1,255)
newS=newS+chr(code+transpose)
l_trans=l_trans+[transpose]
return newS, l_trans
print(encryptSuperHard('hello world'))
在这种情况下,我所做的这个随机加密脚本返回了这两个值元组,其中第一个值是加密消息,第二个值是&#34;转置&#34;每个角色都以外表的顺序排列。
('A0ŤłY\x10řG;,à', [-39, -53, 248, 214, -22, -16, 226, -40, -55, -64, 124])
解密,在这种情况下需要采取加密消息和列表,然后按如下方式进行:
def decryptSuperHard(encriptedS,l):
newS=''
for i in range(len(l)):
newS=newS+chr(ord(encriptedS[i])-l[i])
return newS
print(decryptSuperHard('A0ŤłY\x10řG;,à', [-39,-53,248,214,-22,-16,226,-40,-55,-64,124]))
结果可以追溯到:
你好世界
print(deccryptSuperHard('A0ŤłY\x10řG;,à', [-39, -53, 248, 214, -22, -16, 226, -40, -55, -64, 124])
答案 3 :(得分:0)
正如您所写&#34;我希望能够加密/解密消息&#34;,我使用Blowfish附加一个简单的python源(在2.7下测试)for encr / decr。
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import os
from Crypto.Cipher import Blowfish # pip install pycrypto
BS = 8
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]
def doEncrypt(phrase, key):
c1 = Blowfish.new(key, Blowfish.MODE_ECB)
return c1.encrypt(pad(phrase))
def doDecrypt(phrase, key):
c1 = Blowfish.new(key, Blowfish.MODE_ECB)
return unpad(c1.decrypt(phrase))
def testing123(phrase, key):
encrypted = doEncrypt(phrase, key)
decrypted = doDecrypt(encrypted, key)
assert phrase == decrypted, "Blowfish ECB enc/dec verification failed"
print ("Blowfish ECB enc/dec verified ok")
print ('phrase/key(hex)/enc+dec: {}/{}/{}'.format(phrase, key.encode('hex'), decrypted))
if __name__== "__main__":
phrase= 'Ala ma kota, a kot ma AIDS.'
key= os.urandom(32)
testing123(phrase, key)
答案 4 :(得分:-1)
以下是我可能感兴趣的任何人的解决方案:
from Crypto.Cipher import AES # pip install pycrypto
import base64
def cypher_aes(secret_key, msg_text, encrypt=True):
# an AES key must be either 16, 24, or 32 bytes long
# in this case we make sure the key is 32 bytes long by adding padding and/or slicing if necessary
remainder = len(secret_key) % 16
modified_key = secret_key.ljust(len(secret_key) + (16 - remainder))[:32]
print(modified_key)
# input strings must be a multiple of 16 in length
# we achieve this by adding padding if necessary
remainder = len(msg_text) % 16
modified_text = msg_text.ljust(len(msg_text) + (16 - remainder))
print(modified_text)
cipher = AES.new(modified_key, AES.MODE_ECB) # use of ECB mode in enterprise environments is very much frowned upon
if encrypt:
return base64.b64encode(cipher.encrypt(modified_text)).strip()
return cipher.decrypt(base64.b64decode(modified_text)).strip()
encrypted = cypher_aes(b'secret_AES_key_string_to_encrypt/decrypt_with', b'input_string_to_encrypt/decrypt', encrypt=True)
print(encrypted)
print()
print(cypher_aes(b'secret_AES_key_string_to_encrypt/decrypt_with', encrypted, encrypt=False))
结果:
b'secret_AES_key_string_to_encrypt'
b'input_string_to_encrypt/decrypt '
b'+IFU4e4rFWEkUlOU6sd+y8JKyyRdRbPoT/FvDBCFeuY='
b'secret_AES_key_string_to_encrypt'
b'+IFU4e4rFWEkUlOU6sd+y8JKyyRdRbPoT/FvDBCFeuY= '
b'input_string_to_encrypt/decrypt'
答案 5 :(得分:-1)
alpha = "abcdefghijklmnopqrstuvwxyz"
password = input("What is the password?:")
password = "".join([(str(ord(x)-96) if x.isalpha() else x) for x in list(password)])
password = int(password)
def encrypt(cleartext):
cyphertext = ""
for char in cleartext:
if char in alpha:
newpos = (alpha.find(char) + password) % 26
cyphertext += alpha[newpos]
else:
cyphertext += char
return cyphertext
def decrypt(cleartext):
cyphertext = ""
for char in cleartext:
if char in alpha:
newpos = (alpha.find(char) - password) % 26
cyphertext += alpha[newpos]
else:
cyphertext += char
return cyphertext
while True:
cleartext = input("Cleartext:")
cleartext = cleartext.lower()
print(encrypt(cleartext))
cleartext = input("Cyphertext:")
cleartext = cleartext.lower()
print(decrypt(cleartext))
所以我就是这样做的!