如何使用 python 中的 RSA 私钥进行加密? [英] How can I encrypt with a RSA private key in python?

查看:102
本文介绍了如何使用 python 中的 RSA 私钥进行加密?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以使用 pycryptodome 或任何其他库在 python 中使用私钥加密消息?我知道你不应该用私钥加密并用公钥解密,但我的目的是用私钥加密,以便接收者可以确定消息是由真正的作者发送的.不仅仅是安全加密,我正在寻找某种混淆.我想做一个消息是公开的应用程序,但只有在您拥有公钥时才能看到它.我试过这样做:

Is it possible to encrypt a message with a private key in python using pycryptodome or any other library? I know that you are not supposed to encrypt with the private key and decrypt with the public key, but my purpose is to encrypt with the private one so the receiver could be sure that the message was send by the real author. More than secure encryption I'm looking for some kind of obfuscation. I want to do an app where the message is public but it can only be seen if you have the public key. I've tried to do this:

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

但它引发了下一个错误:TypeError:这不是私钥.

But it raises the next error: TypeError: This is not a private key.

推荐答案

简短回答

  • 出于安全原因,您使用的代码不允许您这样做
  • 下面的替代代码

长答案

我对你的问题很好奇,然后我开始尝试编码

I was curious about your problem and then I started to try to code

一段时间后,我意识到如果您运行此代码段,您将看到它正常工作:

After a while I realized that if you run this snippet you will see that it correctly works:

#!/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()

但是如果你现在改变最后两行[即键的作用]成:

but if you now change two of the final lines [i.e. the role of the keys] into:

    encoded = encrypt_private_key(message, private)
    decrypt_public_key(encoded, public)

然后重新运行程序你会得到TypeError: No private key

and rerun the program you will get the TypeError: No private key

让我引用这个很棒的答案:

事实证明,PyCrypto 只是试图防止您在这里将一个误认为另一个,例如 OpenSSL 或 Ruby OpenSSL 允许您同时执行:public_encrypt/public_decrypt 和 private_encrypt/private_decrypt

"As it turns out, PyCrypto is only trying to prevent you from mistaking one for the other here, OpenSSL or Ruby OpenSSL allow you for example to do both: public_encrypt/public_decrypt and private_encrypt/private_decrypt

[...]

需要注意其他事项才能使结果在实践中可用.这就是为什么有一个专用的签名包 在 PyCrypto 中 - 这有效地完成了您所描述的工作,而且还处理了我提到的事情"

Additional things need to be taken care of to make the result usable in practice. And that's why there is a dedicated signature package in PyCrypto - this effectively does what you described, but also additionally takes care of the things I mentioned"

调整此链接我找到了以下应该可以解决您问题的代码:

Adapting this link I came to the following code that should solve your 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()

最后的注释:

  • 最后一个printascii,因为正如此处然而,在 base64 的情况下,所有字符都是有效的 ASCII 字符"
  • 在这种情况下,我们使用相同的密钥 - 私有密钥 - 用于加密和解密,所以是的:我们最终会是对称的,但是...
  • 但是 - 正如 此处 所述 - 公钥是公开的 - 这是你很容易分享的东西,因此将是很容易传播.与使用对称密码和共享密钥相比,在这种情况下没有附加价值"加上从概念上讲,使用私钥加密"对于签署消息更有用,而使用公钥解密"用于验证消息"
  • 这个答案中表达了相同的最后一个原则 - 通常[...]我们说用私钥并用公钥验证"
  • the last prints have ascii because as stated here "In case of base64 however, all characters are valid ASCII characters"
  • in this case we are using the same key - the private one - both for encrypting and decrypting, so yes: we would end up to be symmetric but...
  • but - as stated here - "The public key is PUBLIC - it's something you would readily share and thus would be easily disseminated. There's no added value in that case compared to using a symmetric cipher and a shared key" plus "Conceptually, "encrypting" with the private key is more useful for signing a message whereas the "decryption" using the public key is used for verifying the message"
  • the same identical last principle is expressed in this answer - "Typically [...] we say sign with the private key and verify with the public key"

这篇关于如何使用 python 中的 RSA 私钥进行加密?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆