der*_*end 8 python encryption cryptography
很难在Google上找到对此的直接答案.
我想要从用户那里收集一段文字和一条消息1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc
hello world
.
然后我希望能够以某种方式使用文本加密/解密消息,以便我可以将其保存在我的数据库中,而不用担心如果我的网站被黑客攻击,数据会被暴露,
encrypt('1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc', 'hello world')
decrypt('1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc', <encrypted_text>)
有没有一种简单的方法来实现这一点与python,请有人提供/指导我的一个例子.
也许是如何使用诸如'1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc'
?之类的种子创建公钥/私钥对的示例?
提前谢谢了 :)
编辑:只是要明确我正在寻找一种方法来加密我的用户数据以一种威慑的方式不混淆消息.
如果这意味着我必须通过使用文本1PWP7a6xgoYx81VZocrDr5okEEcnqKkyDc
作为种子来动态生成PGP/GPG pub/pri密钥对,那么这很好,但是这样做的方法是什么?
zwe*_*wer 22
以下是如何在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
Run Code Online (Sandbox Code Playgroud)
它设置为使用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))
Run Code Online (Sandbox Code Playgroud)
你的输出类似于:
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
Run Code Online (Sandbox Code Playgroud)
证明相同的密钥和相同的数据每次仍然产生不同的密文.
现在,这比欧洲央行要好得多,但是......如果你打算用它进行交流 - 不要!这更多的是解释它应该如何构建,而不是真正用于生产环境,特别是不用于通信,因为它缺少一个关键的成分 - 消息认证.随意使用它,但你不应该使用自己的加密,有经过严格审查的协议可以帮助你避免常见的陷阱,你应该使用它们.
小智 7
基于 zwer 的答案,但显示了一个示例,尝试处理源文本恰好是 16 ( AES.block_size
)的倍数的情况。但是@zwer 在评论中解释了此代码如何通过不适当填充源文本来破坏文本的加密,从而使您的管道不安全。
代码:
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"))
Run Code Online (Sandbox Code Playgroud)
测试:
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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
22599 次 |
最近记录: |