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

Введение

Примеры

  • 4

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

    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' 
  • 3

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

    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'} 
  • 6

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

    Алгоритм 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.

  • 1

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

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

    Вы можете использовать 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()) 
  • 0

    Симметричное шифрование с использованием 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:]) 
  • 0

    Генерация подписи 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 в примерах должны работать , если вы хотите использовать этот. В настоящее время , кажется, мало причин , чтобы использовать его , однако.

  • 0

    Асимметричное шифрование 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 схему шифрования, это один не рекомендуется для новых протоколов , однако в связи с известными оговорками .

Синтаксис

Параметры

Примечания