"Programação de criptografia Python" Notas de leitura (2)

Capítulo 4 Criptografia assimétrica

Por meio de uma senha, uma chave pública e uma chave privada são geradas
e, em seguida, a chave pública criptografa o texto para formar um texto cifrado e a chave privada descriptografa o texto cifrado para obter o texto

RSAComo um dos algoritmos clássicos de criptografia assimétrica, está quase desatualizado, mas você pode entender alguns conceitos básicos aprendendo RSA

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend

# 生成一个私钥
private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048,backend=default_backend())# 参数就这样设定,文档建议
# 从私钥中提取公钥
public_key = private_key.public_key()
# 把私钥转成字节,这一次不加密它
private_key_bytes = private_key.private_bytes(encoding=serialization.Encoding.PEM,
                                              format=serialization.PrivateFormat.TraditionalOpenSSL,
                                              encryption_algorithm=serialization.NoEncryption()
                                            )
# 把公钥转成字节
public_key_bytes = public_key.public_bytes(encoding=serialization.Encoding.PEM,
                                           format=serialization.PublicFormat.SubjectPublicKeyInfo)

# 把私钥字节转回key
private_key = serialization.load_pem_private_key(private_key_bytes,backend=default_backend(),password=None)
public_key = serialization.load_pem_public_key(public_key_bytes,backend=default_backend())

insira a descrição da imagem aqui
A chave pública é derivada da chave privada

4.2 Erros RSA

A fórmula do modelo matemático criptografado cé o texto cifrado e ma mensagem, e os parâmetros restantes são a chave pública e a chave privada

  c ≡ me ( mod n ) \ c ≡ m^e(mod\space n) cme (modn) 

  m ≡ cd ( mod n ) \ m ≡ c^d(mod\space n) mcA conversão de d (modn) 
para código pode ser referida como segue

O código a seguir é apenas para teste e não pode ser usado em nenhum ambiente de produção

import gmpy2, os, binascii
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization

def simple_rsa_encrypt(m, publickey):
    numbers = publickey.public_numbers()
    return gmpy2.powmod(m, numbers.e, numbers.n)

def simple_rsa_decrypt(c, privatekey):
    numbers = privatekey.private_numbers()
    return gmpy2.powmod(c, numbers.d, numbers.public_numbers.n)
    
def int_to_byte(i):
    i = int(i)
    return i.to_bytes((i.bit_length()+7)//8,byteorder='big')

def bytes_to_int(b):
    return int.from_bytes(b,byteorder='big')

to_bytesExistem 3 parâmetros no método,

bytesO primeiro número é para especificar quantos bytes converter
e o segundo é byteorder, que é especificado bigou littlesim
insira a descrição da imagem aqui

O terceiro signedparâmetro indica que bytescorresponde a um número com sinal ou sem sinal int, este é booleanum valor que pode ser omitido
junto com o código acima

def main():
    public_key_file = None
    private_key_file = None
    public_key = None
    private_key = None
    while True:
        print("Simple RSA Crypto")
        print("--------------------")
        print("\tprviate key file: {}".format(private_key_file))
        print("\tpublic key file: {}".format(public_key_file))
        print("\t1. Encrypt Message.")
        print("\t2. Decrypt Message.")
        print("\t3. Load public key file.")
        print("\t4. Load private key file.")
        print("\t5. Create and load new public and private key files.")
        print("\t6. Quit.\n")
        choice = input(">> ")
        if choice == '1':
            if not public_key:
                print("\nNo public key loaded\n")
            else:
                message = input("\nPlaintext: ").encode()# 字符串encode之后可以转为一个整数
                message_as_int = bytes_to_int(message)
                cipher_as_int = simple_rsa_encrypt(message_as_int, public_key)
                cipher = int_to_bytes(cipher_as_int)
                print("\nCiphertext (hexlified): {}\n".format(binascii.hexlify(cipher)))# binascii.hexlify返回一个数据的16进制表示
        elif choice == '2':
            if not private_key:
                print("\nNo private key loaded\n")
            else:
                cipher_hex = input("\nCiphertext (hexlified): ").encode()
                cipher = binascii.unhexlify(cipher_hex)
                cipher_as_int = bytes_to_int(cipher)
                message_as_int = simple_rsa_decrypt(cipher_as_int, private_key)
                message = int_to_bytes(message_as_int)
                print("\nPlaintext: {}\n".format(message))
        elif choice == '3':
            public_key_file_temp = input("\nEnter public key file: ")
            if not os.path.exists(public_key_file_temp):
                print("File {} does not exist.")
            else:
                with open(public_key_file_temp, "rb") as public_key_file_object:
                    public_key = serialization.load_pem_public_key(
                                     public_key_file_object.read(),
                                     backend=default_backend())
                    public_key_file = public_key_file_temp
                    print("\nPublic Key file loaded.\n")

                    # unload private key if any
                    private_key_file = None
                    private_key = None
        elif choice == '4':
            private_key_file_temp = input("\nEnter private key file: ")
            if not os.path.exists(private_key_file_temp):
                print("File {} does not exist.")
            else:
                with open(private_key_file_temp, "rb") as private_key_file_object:
                    private_key = serialization.load_pem_private_key(
                                     private_key_file_object.read(),
                                     backend=default_backend(),
                                     password=None)
                    private_key_file = private_key_file_temp
                    print("\nPrivate Key file loaded.\n")

                    # load public key for private key
                    # (unload previous public key if any)
                    public_key = private_key.public_key()
                    public_key_file = None
        elif choice == '5':
            private_key_file_temp = input("\nEnter a file name for new private key: ")
            public_key_file_temp  = input("\nEnter a file name for a new public key: ")
            if os.path.exists(private_key_file_temp) or os.path.exists(public_key_file_temp):
                print("File already exists.")
            else:
                with open(private_key_file_temp, "wb+") as private_key_file_obj:
                    with open(public_key_file_temp, "wb+") as public_key_file_obj:

                        private_key = rsa.generate_private_key(
                                          public_exponent=65537,
                                          key_size=2048,
                                          backend=default_backend()
                                      )
                        public_key = private_key.public_key()

                        private_key_bytes = private_key.private_bytes(
                            encoding=serialization.Encoding.PEM,
                            format=serialization.PrivateFormat.TraditionalOpenSSL,
                            encryption_algorithm=serialization.NoEncryption()
                        )
                        private_key_file_obj.write(private_key_bytes)
                        public_key_bytes = public_key.public_bytes(
                            encoding=serialization.Encoding.PEM,
                            format=serialization.PublicFormat.SubjectPublicKeyInfo
                        )
                        public_key_file_obj.write(public_key_bytes)

                        public_key_file = None
                        private_key_file = private_key_file_temp
        elif choice == '6':
            print("\n\nTerminaing. This program will self destruct in 5 seconds.\n")
            break
        else:
            print("\n\nUnknown option {}.\n".format(choice))

if __name__ == '__main__':
    main()

Etapas:
1. Selecione 5, insira o nome do arquivo, my_private_key_file.pem, my_public_key_file.pem, e salve a chave pública e a chave privada nesses dois arquivos.
2. Depois que A obtiver o arquivo de chave pública, selecione 3para carregar o arquivo de chave pública
. 3. Selecione 1, A precisa para responder Ba hot dogs", usará a chave pública anterior para criptografar esta mensagem e retornará o texto cifrado criptografado. Essas mensagens são criptografadas por A , mas não podem ser descriptografadas porque A não possui uma chave privada. A envia o texto cifrado gerado para B

Ciphertext (hexlified): b'a8d6b19f7661fa7bcc11476df13c7c0a151db81967308afc083d9223d2492b3e139fab519b419b7dcf14c8a856ec8ff3701d9ebdf520ec4584172acd34d9d2c9e216d6abbf9697e641185104c52dedf72115ecfcf6ee34a504ed983c7bce463d5e8963d1d4111bced4c937816e52e7ce986e57bedfe5896a5d5a133c29f3f2006ac480dca589f5938092b0ac8bbad91fb20572429d079be4a8d2583c187ba3f22a6cd7b5779d6589fef39b3595363427c4c19e1a4ac78b3e62d56d17810fff1f74385f03db4051841cd6d48ff70dfc406954e50fd4aa33f392aaf510c4bb3341e3f406f68ff8b97db34821add1464f85f770b12303fa3d207650561ed3a81ab3'

4. Selecione 4, B carregue o arquivo de chave privada
5. Selecione 2, insira apenas o conteúdo entre aspas do texto cifrado acima

4.6 preenchimento de passe

4.6.2 Ataque de texto cifrado escolhido (CCA)

Esta seção significa que o método acima é fácil de decifrar, de acordo com um monte de fórmulas matemáticas, blá blá, blá blá,

4.6.3 Ataque de modo comum

nO parâmetro é o módulo, se a mesma RSAmensagem for criptografada com duas nchaves públicas diferentes com o mesmo módulo, ela pode ser descriptografada sem usar a chave privada

4.7 Preenchimento

cryptographyO uso de nenhum preenchimento é proibido em RSA, mas a biblioteca OpenSSL permite o
uso OAEPde preenchimento ideal para criptografia assimétrica

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

def main():
    message = b'test'
    
    private_key = rsa.generate_private_key(
          public_exponent=65537,
          key_size=2048,
          backend=default_backend()
      )
    public_key = private_key.public_key()
    
    ciphertext1 = public_key.encrypt(
        message,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None # rarely used. Just leave it 'None'
        )
    )
    
    ###
    # WARNING: PKCS #1 v1.5 is obsolete and has vulnerabilities
    # DO NOT USE EXCEPT WITH LEGACY PROTOCOLS
    ciphertext2 = public_key.encrypt(
        message,
        padding.PKCS1v15()
    )
    
    recovered1 = private_key.decrypt(
    ciphertext1,
     padding.OAEP(
         mgf=padding.MGF1(algorithm=hashes.SHA256()),
         algorithm=hashes.SHA256(),
         label=None # rarely used. Just leave it 'None'
     ))
       
    recovered2 = private_key.decrypt(
    ciphertext2,
     padding.PKCS1v15()
 )
    
    print("Plaintext: {}".format(message))
    print("Ciphertext with PKCS #1 v1.5 padding (hexlified): {}".format(ciphertext1.hex()))
    print("Ciphertext with OAEP padding (hexlified): {}".format(ciphertext2.hex()))
    print("Recovered 1: {}".format(recovered1))
    print("Recovered 2: {}".format(recovered2))
    if ciphertext1 != ciphertext2 and recovered1 == message and recovered2 == message:
        print("[PASS]")
    
if __name__=="__main__":
    main()

padding.PKCS1v15()Inseguro
é executado repetidamente, o texto cifrado para ambos os esquemas de preenchimento mudará cada vez que
o preenchimento garante que a entrada seja sempre um tamanho fixo: a entrada para o módulo bit
RSAcriptografado (modulo-size 2048) sempre será 256bytes. Duas discussões
sobre (1) Os parâmetros são geralmente , o uso não aumentará a segurança, então ignore temporariamente (2) a necessidade de usar o algoritmo de hash, mais seguroOAEP
labelNonelabel
OAEPSHA256

A computação quântica está chegando, agora a maioria dos algoritmos assimétricos será fácil de decifrar, o RSA será decifrado

Capítulo 5 Integridade da Mensagem, Assinaturas e Certificados

5.2 MAC, HMAC, CBC-MAC

O MAC (Message Authentication Code) é um mecanismo de autenticação utilizado tanto por entidades de comunicação como uma ferramenta para garantir a integridade dos dados da mensagem. Aqui estão 2 métodos

5.2.1 HMAC

HMAC é um código de autenticação de mensagem baseado em hash
Algoritmo de hash, para a mesma entrada, a saída é a mesma, a mesma em todos os computadores
Para o algoritmo sem chave, a mesma entrada sempre dá a mesma saída, usando a chave é Ganhou 't porque a saída depende da entrada e da chave

Acho que você gosta

Origin blog.csdn.net/weixin_44831720/article/details/123201112
Recomendado
Clasificación