Документация по Python

Безопасность и криптография

В: Документация по Python

Введение

Примеры

Расчет дайджеста сообщения

hashlib модуль позволяет создавать дайджест сообщения генераторов с помощью new метода. Эти генераторы превратят произвольную строку в дайджест фиксированной длины:

 import hashlib

h = hashlib.new('sha256')
h.update(b'Nobody expects the Spanish Inquisition.')
h.digest()
# ==> b'.\xdf\xda\xdaVR[\x12\x90\xff\x16\xfb\x17D\xcf\xb4\x82\xdd)\x14\xff\xbc\xb6Iy\x0c\x0eX\x9eF-='

 

Обратите внимание , что вы можете вызвать update произвольное число раз перед вызовом digest , который полезен для хеширования большого файла кусок на кусок. Вы также можете получить дайджест в шестнадцатеричном формате с помощью hexdigest :

 h.hexdigest()
# ==> '2edfdada56525b1290ff16fb1744cfb482dd2914ffbcb649790c0e589e462d3d' 

Доступные алгоритмы хеширования

hashlib.new требует имени алгоритма при вызове его для создания генератора. Для того, чтобы выяснить , какие алгоритмы доступны в интерпретаторе текущего Python, используйте hashlib.algorithms_available :

 import hashlib
hashlib.algorithms_available
# ==> {'sha256', 'DSA-SHA', 'SHA512', 'SHA224', 'dsaWithSHA', 'SHA', 'RIPEMD160', 'ecdsa-with-SHA1', 'sha1', 'SHA384', 'md5', 'SHA1', 'MD5', 'MD4', 'SHA256', 'sha384', 'md4', 'ripemd160', 'sha224', 'sha512', 'DSA', 'dsaEncryption', 'sha', 'whirlpool'}

 

Возвращаемый список будет варьироваться в зависимости от платформы и переводчика; Убедитесь, что ваш алгоритм доступен.

Есть также некоторые алгоритмы, которые гарантированно будут доступны на всех платформах и переводчиков, которые доступны с помощью hashlib.algorithms_guaranteed :

 hashlib.algorithms_guaranteed
# ==> {'sha256', 'sha384', 'sha1', 'sha224', 'md5', 'sha512'} 

Безопасное хеширование паролей

Алгоритм PBKDF2 разоблачена hashlib модуль может быть использован для выполнения безопасного хэширования паролей. Хотя этот алгоритм не может предотвратить атаки методом перебора для восстановления исходного пароля из сохраненного хэша, он делает такие атаки очень дорогими.

 import hashlib
import os

salt = os.urandom(16)
hash = hashlib.pbkdf2_hmac('sha256', b'password', salt, 100000)

 

PBKDF2 может работать с любым алгоритмом дайджеста, в приведенном выше примере используется SHA256, который обычно рекомендуется. Случайная соль должна храниться вместе с хешированным паролем, она понадобится вам снова, чтобы сравнить введенный пароль с сохраненным хешем. Важно, чтобы каждый пароль хешировался с разной солью. Что касается количества раундов, рекомендуется установить его как можно выше для вашего приложения .

Если вы хотите , чтобы результат в шестнадцатеричном, вы можете использовать binascii модуль:

 import binascii
hexhash = binascii.hexlify(hash)

 

Примечание: В то время как PBKDF2 не плохо, Bcrypt и особенно Scrypt считаются сильнее против грубой силы нападения. В настоящее время они не являются частью стандартной библиотеки Python.

Хеширование файлов

Хеш - это функция, которая преобразует последовательность байтов переменной длины в последовательность фиксированной длины. Хэширование файлов может быть полезным по многим причинам. Хэши можно использовать для проверки идентичности двух файлов или проверки того, что содержимое файла не было повреждено или изменено.

Вы можете использовать hashlib для создания хэша файла:

 import hashlib

hasher = hashlib.new('sha256')
with open('myfile', 'r') as f:
    contents = f.read()
    hasher.update(contents)

print hasher.hexdigest() 

Для больших файлов можно использовать буфер фиксированной длины:

 import hashlib
SIZE = 65536
hasher = hashlib.new('sha256')
with open('myfile', 'r') as f:
    buffer = f.read(SIZE)
    while len(buffer) > 0:
        hasher.update(buffer)
        buffer = f.read(SIZE)
print(hasher.hexdigest()) 

Симметричное шифрование с использованием pycrypto

Встроенные функции шифрования Python в настоящее время ограничены хешированием. Шифрование необходим модуль стороннего как PyCrypto.Например, он обеспечивает алгоритм AES , который считается состоянием искусства для симметричного шифрования. Следующий код зашифрует данное сообщение с использованием ключевой фразы:

import hashlib
import math
import os

from Crypto.Cipher import AES

IV_SIZE = 16    # 128 bit, fixed for the AES algorithm
KEY_SIZE = 32   # 256 bit meaning AES-256, can also be 128 or 192 bits
SALT_SIZE = 16  # This size is arbitrary

cleartext = b'Lorem ipsum'
password = b'highly secure encryption password'
salt = os.urandom(SALT_SIZE)
derived = hashlib.pbkdf2_hmac('sha256', password, salt, 100000,
                              dklen=IV_SIZE + KEY_SIZE)
iv = derived[0:IV_SIZE]
key = derived[IV_SIZE:]

encrypted = salt + AES.new(key, AES.MODE_CFB, iv).encrypt(cleartext)


Алгоритм AES принимает три параметра: ключ шифрования, вектор инициализации (IV) и фактическое сообщение, которое должно быть зашифровано. Если у вас есть случайно сгенерированный ключ AES, то вы можете использовать его напрямую и просто сгенерировать случайный вектор инициализации. Однако парольная фраза не имеет правильного размера, и не рекомендуется использовать ее напрямую, поскольку она не является действительно случайной и, следовательно, имеет сравнительно небольшую энтропию. Вместо этого мы используем встроенную реализацию алгоритма PBKDF2 генерировать 128 битный вектор инициализации и 256 битного ключа шифрования из пароля.

Обратите внимание на случайную соль, которая важна для каждого вектора инициализации и ключа для каждого зашифрованного сообщения. Это, в частности, гарантирует, что два одинаковых сообщения не приведут к одинаковому зашифрованному тексту, но также предотвращает повторное использование злоумышленниками работы, потраченной на угадывание одной парольной фразы для сообщений, зашифрованных другой парольной фразой. Эта соль должна храниться вместе с зашифрованным сообщением, чтобы получить тот же вектор инициализации и ключ для дешифрования.

Следующий код снова расшифрует наше сообщение:

 salt = encrypted[0:SALT_SIZE]
derived = hashlib.pbkdf2_hmac('sha256', password, salt, 100000,
                              dklen=IV_SIZE + KEY_SIZE)
iv = derived[0:IV_SIZE]
key = derived[IV_SIZE:]
cleartext = AES.new(key, AES.MODE_CFB, iv).decrypt(encrypted[SALT_SIZE:]) 

Генерация подписи RSA с использованием pycrypto

RSA ) может быть использован для создания сообщения подписи. Действительная подпись может быть сгенерирована только с доступом к закрытому ключу RSA, проверка с другой стороны возможна только с помощью соответствующего открытого ключа. Поэтому, пока другая сторона знает ваш открытый ключ, она может проверить сообщение, которое вы подписали и не изменило - например, этот подход используется для электронной почты. В настоящее время модуль третьей стороной , как PyCrypto требуется для этой функциональности.

 import errno

from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5

message = b'This message is from me, I promise.'

try:
    with open('privkey.pem', 'r') as f:
        key = RSA.importKey(f.read())
except IOError as e:
    if e.errno != errno.ENOENT:
        raise
    # No private key, generate a new one. This can take a few seconds.
    key = RSA.generate(4096)
    with open('privkey.pem', 'wb') as f:
        f.write(key.exportKey('PEM'))
    with open('pubkey.pem', 'wb') as f:
        f.write(key.publickey().exportKey('PEM'))

hasher = SHA256.new(message)
signer = PKCS1_v1_5.new(key)
signature = signer.sign(hasher)

 

Проверка подписи работает аналогично, но использует открытый ключ, а не закрытый ключ:

 with open('pubkey.pem', 'rb') as f:
    key = RSA.importKey(f.read())
hasher = SHA256.new(message)
verifier = PKCS1_v1_5.new(key)
if verifier.verify(hasher, signature):
    print('Nice, the signature is valid!')
else:
    print('No, the message was signed with the wrong private key or modified')

 

Примечание: Приведенные выше примеры использования PKCS # 1 v1.5 алгоритм подписи , который является очень распространенным явлением. PyCrypto также реализует новую PKCS # 1 алгоритм PSS, заменив PKCS1_v1_5 на PKCS1_PSS в примерах должны работать , если вы хотите использовать этот. В настоящее время , кажется, мало причин , чтобы использовать его , однако.

Асимметричное шифрование RSA с использованием pycrypto

Преимущество асимметричного шифрования заключается в том, что сообщение может быть зашифровано без обмена секретным ключом с получателем сообщения. Отправителю просто нужно знать открытый ключ получателя, это позволяет зашифровать сообщение таким образом, что только назначенный получатель (имеющий соответствующий закрытый ключ) может расшифровать его. В настоящее время модуль третьей стороной , как PyCrypto требуется для этой функциональности.

 from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA

message = b'This is a very secret message.'

with open('pubkey.pem', 'rb') as f:
    key = RSA.importKey(f.read())
cipher = PKCS1_OAEP.new(key)
encrypted = cipher.encrypt(message)

 

Получатель может расшифровать сообщение, если у него есть правильный закрытый ключ:

 with open('privkey.pem', 'rb') as f:
    key = RSA.importKey(f.read())
cipher = PKCS1_OAEP.new(key)
decrypted = cipher.decrypt(encrypted)

 

Примечание: Приведенные выше примеры использования PKCS # 1 схема шифрования OAEP. PyCrypto также реализует PKCS # 1 v1.5 схему шифрования, это один не рекомендуется для новых протоколов , однако в связи с известными оговорками .

Синтаксис

Параметры

Примечания

Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.