web-dev-qa-db-ja.com

PythonでRSA秘密鍵を使用して暗号化するにはどうすればよいですか?

pythonでpycryptodomeまたは他のライブラリを使用してメッセージを秘密鍵で暗号化することは可能ですか?秘密鍵で暗号化して公開鍵で復号化することは想定されていませんが、私の目的は、プライベートなもので暗号化して、メッセージが実際の作成者によって送信されたことを受信者が確認できるようにすることです。安全な暗号化よりも、ある種の難読化を探しています。メッセージが公開されるアプリを実行したいしかし、それはあなたが公開鍵を持っている場合にのみ見ることができます。私はこれを試みました:

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:これは秘密鍵ではありません。

5
Cesar Cabrera

短い答え

  • 使用しているコードでは、セキュリティ上の理由からこれを行うことはできません
  • 以下の代替コード

長い答え

私はあなたの問題に興味があったので、コードを書き始めました

しばらくすると、このスニペットを実行すると、正しく動作することがわかります。

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

しかし、最後の2行を変更すると、キーの役割]に:

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

プログラムを再実行すると、TypeError: No private key

この素晴らしい答え から引用させてください:

「結局のところ、PyCryptoは、ここで一方を他方と間違えないようにしようとしているだけです。OpenSSLまたはRuby OpenSSLを使用すると、たとえば、public_encrypt/public_decryptとprivate_encrypt/private_decryptの両方を実行できます。

[...]

結果を実際に使用できるようにするには、さらに注意が必要です。そしてそれがPyCryptoに専用の signatureパッケージ がある理由です-これはあなたが説明したことを効果的に行いますが、私が言及したことも追加で処理します "

適応 このリンク 私はあなたの質問を解決するはずの次のコードに行きました:

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

最終メモ:

  • 最後のprintsにはasciiがあります。これは、前述のとおり here "ただし、base64の場合、すべての文字が有効ですASCII characters"
  • この場合、暗号化と復号化の両方に同じ鍵(秘密鍵)を使用しているので、はい:対称になることになりますが...
  • しかし-述べたように ここ -「公開鍵は公開です-これは簡単に共有できるため、簡単に配布できます。その場合、対称暗号と共有鍵を使用する場合と比較して、付加価値はありません。 "プラス"概念的には、秘密キーを使用した "暗号化"はメッセージの署名に役立ち、公開キーを使用した "復号化"はメッセージの検証に使用されます "
  • 同じ同一の最後の原則は この答え -で表されます「通常、[...]秘密鍵で署名し、公開鍵で検証する」
3
Antonino

あなたが説明しているものはmessage signingと呼ばれ、秘密鍵/公開鍵を使用して、メッセージが要求された送信者から来たものであり、それが途中で改ざん。これらのメソッドを「発明」する必要はありません...

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

0
Mike Robinson

pycryptoは2014年から活発に開発されておらず、サポートはpython 3.3で終了しました。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
)
0
zemekeneng