Est-il possible de chiffrer un message avec une clé privée en python en utilisant pycryptodome ou toute autre bibliothèque? Je sais que vous n'êtes pas censé chiffrer avec la clé privée et déchiffrer avec la clé publique, mais mon but est de chiffrer avec le privé afin que le destinataire puisse être sûr que le message a été envoyé par le véritable auteur. Plus qu'un chiffrement sécurisé, je recherche une sorte d'obscurcissement. Je veux faire une application où le message est public mais il ne peut être vu que si vous avez la clé publique. J'ai essayé de le faire:
from Crypto import Random
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64
def generate_keys():
modulus_lenght = 256 * 4
private_key = RSA.generate(modulus_lenght, Random.new().read)
public_key = private_key.publickey()
return private_key, public_key
def encrypt_private_key(a_message, private_key):
encryptor = PKCS1_OAEP.new(private_key)
encrypted_msg = encryptor.encrypt(a_message)
encoded_encrypted_msg = base64.b64encode(encrypted_msg)
return encoded_encrypted_msg
def decrypt_public_key(encoded_encrypted_msg, public_key):
encryptor = PKCS1_OAEP.new(public_key)
decoded_encrypted_msg = base64.b64decode(encoded_encrypted_msg)
decoded_decrypted_msg = encryptor.decrypt(decoded_encrypted_msg)
return decoded_decrypted_msg
private_key, public_key = generate_keys()
message = "Hello world"
encoded = encrypt_private_key(message, private_key)
decoded = decrypt_public_key(encoded, public_key)
print decoded
Mais cela soulève l'erreur suivante: TypeError: Ce n'est pas une clé privée.
Réponse courte
Réponse longue
J'étais curieux de connaître votre problème, puis j'ai commencé à essayer de coder
Après un certain temps, j'ai réalisé que si vous exécutez cet extrait, vous verrez qu'il fonctionne correctement:
#!/usr/bin/env python
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64
def generate_keys():
modulus_length = 1024
key = RSA.generate(modulus_length)
#print (key.exportKey())
pub_key = key.publickey()
#print (pub_key.exportKey())
return key, pub_key
def encrypt_private_key(a_message, private_key):
encryptor = PKCS1_OAEP.new(private_key)
encrypted_msg = encryptor.encrypt(a_message)
print(encrypted_msg)
encoded_encrypted_msg = base64.b64encode(encrypted_msg)
print(encoded_encrypted_msg)
return encoded_encrypted_msg
def decrypt_public_key(encoded_encrypted_msg, public_key):
encryptor = PKCS1_OAEP.new(public_key)
decoded_encrypted_msg = base64.b64decode(encoded_encrypted_msg)
print(decoded_encrypted_msg)
decoded_decrypted_msg = encryptor.decrypt(decoded_encrypted_msg)
print(decoded_decrypted_msg)
#return decoded_decrypted_msg
def main():
private, public = generate_keys()
print (private)
message = b'Hello world'
encoded = encrypt_private_key(message, public)
decrypt_public_key(encoded, private)
if __name__== "__main__":
main()
mais si vous changez maintenant deux des dernières lignes [c.-à-d. le rôle des touches] en:
encoded = encrypt_private_key(message, private)
decrypt_public_key(encoded, public)
et relancez le programme, vous obtiendrez le TypeError: No private key
Permettez-moi de citer cette excellente réponse :
"En fait, PyCrypto essaie seulement de vous empêcher de vous confondre ici, OpenSSL ou Ruby OpenSSL vous permet par exemple de faire les deux: public_encrypt/public_decrypt et private_encrypt/private_decrypt
[...]
Des éléments supplémentaires doivent être pris en compte pour rendre le résultat utilisable dans la pratique. Et c'est pourquoi il y a un package de signature dédié dans PyCrypto - cela fait effectivement ce que vous avez décrit, mais s'occupe également des choses que j'ai mentionnées "
Adapter ce lien Je suis arrivé au code suivant qui devrait résoudre votre question:
# RSA helper class for pycrypto
# Copyright (c) Dennis Lee
# Date 21 Mar 2017
# Description:
# Python helper class to perform RSA encryption, decryption,
# signing, verifying signatures & keys generation
# Dependencies Packages:
# pycrypto
# Documentation:
# https://www.dlitz.net/software/pycrypto/api/2.6/
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode
import rsa
hash = "SHA-256"
def newkeys(keysize):
random_generator = Random.new().read
key = RSA.generate(keysize, random_generator)
private, public = key, key.publickey()
return public, private
def importKey(externKey):
return RSA.importKey(externKey)
def getpublickey(priv_key):
return priv_key.publickey()
def encrypt(message, pub_key):
#RSA encryption protocol according to PKCS#1 OAEP
cipher = PKCS1_OAEP.new(pub_key)
return cipher.encrypt(message)
def decrypt(ciphertext, priv_key):
#RSA encryption protocol according to PKCS#1 OAEP
cipher = PKCS1_OAEP.new(priv_key)
return cipher.decrypt(ciphertext)
def sign(message, priv_key, hashAlg="SHA-256"):
global hash
hash = hashAlg
signer = PKCS1_v1_5.new(priv_key)
if (hash == "SHA-512"):
digest = SHA512.new()
Elif (hash == "SHA-384"):
digest = SHA384.new()
Elif (hash == "SHA-256"):
digest = SHA256.new()
Elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.sign(digest)
def verify(message, signature, pub_key):
signer = PKCS1_v1_5.new(pub_key)
if (hash == "SHA-512"):
digest = SHA512.new()
Elif (hash == "SHA-384"):
digest = SHA384.new()
Elif (hash == "SHA-256"):
digest = SHA256.new()
Elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.verify(digest, signature)
def main():
msg1 = b"Hello Tony, I am Jarvis!"
msg2 = b"Hello Toni, I am Jarvis!"
keysize = 2048
(public, private) = rsa.newkeys(keysize)
# https://docs.python.org/3/library/base64.html
# encodes the bytes-like object s
# returns bytes
encrypted = b64encode(rsa.encrypt(msg1, private))
# decodes the Base64 encoded bytes-like object or ASCII string s
# returns the decoded bytes
decrypted = rsa.decrypt(b64decode(encrypted), private)
signature = b64encode(rsa.sign(msg1, private, "SHA-512"))
verify = rsa.verify(msg1, b64decode(signature), public)
#print(private.exportKey('PEM'))
#print(public.exportKey('PEM'))
print("Encrypted: " + encrypted.decode('ascii'))
print("Decrypted: '%s'" % (decrypted))
print("Signature: " + signature.decode('ascii'))
print("Verify: %s" % verify)
rsa.verify(msg2, b64decode(signature), public)
if __name__== "__main__":
main()
Notes finales:
print
ont ascii
car comme indiqué ici "En cas de base64 cependant, tous les caractères sont valides ASCII caractères"Ce que vous décrivez s'appelle signature de message et utilise des clés privées/publiques pour vérifier que le message provient bien de l'expéditeur déclaré et qu'il n'a pas été falsifié en cours de route. Vous n'avez pas à "inventer" ces méthodes ...
https://medium.com/@securegns/implementing-asymmetric-encryption-to-secure-your-project-35368049cb5f
Il semble que pycrypto
n'ait pas été en développement actif depuis 2014 et le support a pris fin à python 3.3. cryptography
semble être la norme maintenant.
Utilisation de cryptography
:
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend
password = b'thepassword'
key = rsa.generate_private_key(
backend=default_backend(),
public_exponent=65537,
key_size=2048
)
private_key = key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
serialization.BestAvailableEncryption(password)
)
public_key = key.public_key().public_bytes(
serialization.Encoding.OpenSSH,
serialization.PublicFormat.OpenSSH
)