简体   繁体   English

如何使用 python 中的 RSA 私钥进行加密?

[英]How can I encrypt with a RSA private key in python?

Is it possible to encrypt a message with a private key in python using pycryptodome or any other library?是否可以使用 pycryptodome 或任何其他库在 python 中使用私钥加密消息? 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

But it raises the next error: TypeError: This is not a private key.但它引发了下一个错误:TypeError:这不是私钥。

Short answer简答

  • the code that you are using doesn't allow you to do that for security reasons出于安全原因,您使用的代码不允许您这样做
  • alternative code below下面的替代代码

Long answer长答案

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 [ie the role of the keys] into:但是,如果您现在将最后两行 [即键的作用] 更改为:

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

and rerun the program you will get the TypeError: No private key并重新运行程序,你会得到TypeError: No private key

Let me quote from this great answer :让我引用这个伟大的答案

"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 只是试图防止您在这里将一个误认为另一个,例如 OpenSSL 或 Ruby OpenSSL 允许您同时执行以下操作:public_encrypt/public_decrypt 和 private_encrypt/private_decrypt

[...] [...]

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"这就是为什么 PyCrypto 中有一个专用的签名包- 这有效地完成了你所描述的,而且还处理了我提到的事情”

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()

Final notes:最后说明:

  • the last print s have ascii because as stated here "In case of base64 however, all characters are valid ASCII characters"最后print ■找ascii因为说这里“为Base64的情况下,但是,所有的字符都是有效的ASCII字符”
  • 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"这个答案中表达了相同的最后一个原则 - “通常[...]我们说用私钥签名并用公钥验证”

Looks like pycrypto has not been under active development since 2014 and support ended at python 3.3.看起来pycrypto自 2014 年以来一直没有积极开发,支持在 python 3.3 结束。 cryptography seems like the standard now. cryptography现在似乎是标准。

Using cryptography :使用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
)

What you are describing is called message signing and it uses private/public keys to verify that the message did come from the claimed sender and that it has not been tampered with en route.您所描述的称为消息签名,它使用私钥/公钥来验证消息确实来自声称的发件人,并且在途中没有被篡改。 You don't have to "invent" these methods ...你不必“发明”这些方法......

https://medium.com/@securegns/implementing-asymmetric-encryption-to-secure-your-project-35368049cb5f https://medium.com/@securegns/implementing-asymmetric-encryption-to-secure-your-project-35368049cb5f

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在python中使用RSA私钥加密数据? - How to encrypt data with RSA private key in python? 如何在Python中使用RSA私钥(非常规签名)加密数据? - How to encrypt data with RSA private key (not normal signing) in Python? 我有一个 RSA 公钥指数和模数。 如何使用 Python 加密字符串? - I have a RSA public key exponent and modulus. How can I encrypt a string using Python? 如何使用 python 从存储在 AWS 的 Secrets Manager 中的私钥生成 OpenSSH RSA 密钥? - How can I generate OpenSSH RSA key using python from the private key stored in Secrets manager in AWS? 如何使用 openssl 和 rsa 将此 python 加密函数(aes,rsa 公钥)传输到 php? - how do I transfer this python encrypt functions (aes, rsa public key) to php with openssl and rsa? 导入 rsa 私钥并加密字符串 - import rsa private key and encrypt string 如何在Python中计算RSA私钥 - How to calculate RSA private key in Python Python pyCrypto RSA加密方法使用私钥或公钥提供相同的结果 - Python pyCrypto RSA encrypt method gives same results using private or public key 如何在Python的加密模块中访问RSA私钥的组件? - How do I access the components of a private RSA key in Python's cryptography module? 如何在 python 上使用 RSA 私钥和 SHA256 进行解密 - How to use decrypt with RSA private key and SHA256 on python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM