Python 中的 openssl_seal()

发布于 2024-08-31 18:51:58 字数 541 浏览 3 评论 0原文

要连接服务器,我发现使用 PHP,我需要使用 openssl_seal()。没关系,但我想使用 Python。我无法在等效函数中转换 openssl_seal()

你能帮助我吗?

这就是 openssl_seal() 的作用:

描述 int openssl_seal ( 字符串 $data , 字符串 &$sealed_data , 数组 &$env_keys , 数组 $pub_key_ids )

openssl_seal() 通过使用带有随机生成的 RC4 来密封(加密)数据
秘密密钥。该密钥使用每个关联的公钥进行加密
带有 pub_key_ids 中的标识符,并且每个加密密钥返回于
env_keys。这意味着一个人可以将密封数据发送给多个收件人
(前提是已获得其公钥)。每个收件人必须收到
密封的数据和使用加密的信封密钥
接收者的公钥。

To connect a server, I've found that, using PHP, I need to use openssl_seal(). That's OK, but I want to use Python. I'm not able to convert openssl_seal() in an equivalent function.

Can you help me?

This is what openssl_seal() does:

Description
int openssl_seal ( string $data , string &$sealed_data , array &$env_keys ,
array $pub_key_ids )

openssl_seal() seals (encrypts) data by using RC4 with a randomly generated
secret key. The key is encrypted with each of the public keys associated
with the identifiers in pub_key_ids and each encrypted key is returned in
env_keys. This means that one can send sealed data to multiple recipients
(provided one has obtained their public keys). Each recipient must receive
both the sealed data and the envelope key that was encrypted with the
recipient's public key.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

徒留西风 2024-09-07 18:51:58

这篇博文非常详细地描述了openssl_seal()内部发生的情况。它也有一个java实现。

由此看来,我认为使用 pyopenssl,其中包括 RC4 或更新的版本,但对于这些目的更集中tlslite

this blogpost has a very detailed description of what's going on inside openssl_seal(). It also has an implementation in java.

From this, I would think it should be relatively straightforward ("the proof left as an exercise to the reader" kind of straightforward) to do an equivalent implementation in python using pyopenssl, which includes RC4, or the newer, but for these purposes more focused tlslite.

末骤雨初歇 2024-09-07 18:51:58

openssl_seal 的作用是:

  1. 从证书中提取 public_key
  2. 生成 128 位(16 字节)长的 random_key (这将用于使用对称算法加密消息,因为它更快)
  3. 使用 PKCS #1 加密 random_key
  4. 使用以下命令加密消息ARC4 安全密码方法和 random_key(请注意,ARC4 不再被认为是安全的,PHP 强烈建议使用 cipher_algo 参数显式指定安全密码方法)
  5. 输出加密的随机密钥和加密的消息

接收方随后可以使用其私钥解密加密的随机密钥,然后使用随机密钥解密加密的消息。

由于无法通过标准库在 Python 中执行此操作,因此我将放弃我尝试过的 3 种方法:

# pyca/cryptography (cryptography.io) version
# pip install cryptography

import os

import cryptography
from cryptography import x509


message = 'Super secret secret message'
message = message.encode('utf-8')
certificate_data = open('/path/to/certificate.cer', 'r').read()
certificate_data = certificate_data.encode('utf-8')
certificate = cryptography.x509.load_pem_x509_certificate(data=certificate_data, backend=cryptography.hazmat.backends.default_backend())
public_key = certificate.public_key()
random_key = os.urandom(16)
encrypted_random_key = public_key.encrypt(plaintext=random_key, padding=cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15())
print(encrypted_random_key)
algorithm = cryptography.hazmat.primitives.ciphers.algorithms.AES(random_key)
cipher = cryptography.hazmat.primitives.ciphers.Cipher(algorithm=algorithm, mode=None, backend=cryptography.hazmat.backends.default_backend())
encryptor = cipher.encryptor()
encrypted_message = encryptor.update(message)
print(encrypted_message)

# M2Crypto version
# pip install pip install git+https://gitlab.com/m2crypto/m2crypto@python3

import M2Crypto


message = 'Super secret secret message'
message = message.encode('utf-8')
certificate = M2Crypto.X509.load_cert('/path/to/certificate.cer')
public_key = certificate.get_pubkey()
rsa_pub = public_key.get_rsa()
random_key = M2Crypto.Rand.rand_bytes(16)
encrypted_random_key = rsa_pub.public_encrypt(random_key, M2Crypto.RSA.pkcs1_padding)
print(encrypted_random_key)
cipher = M2Crypto.EVP.Cipher(alg='aes_128_cbc', key=random_key, iv=b'', op=M2Crypto.encrypt)
encrypted_message = cipher.update(message)
encrypted_message += cipher.final()
print(encrypted_message)

# PyCrypto version
# Update: PyCrypto 2.x is unmaintained, obsolete, and contains security vulnerabilities!!!
# pip install pycrypto

# Please bear in mind that PyCrypto cannot handle x509 certificates.
# You will have to extract the public_key to a pem file:
# openssl x509 -inform pem -in certificate.cer -pubkey -noout > public_key.pem

from Crypto import Random
from Crypto.Cipher import ARC4
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA


message = 'Super secret secret message'
message = message.encode('utf-8')
public_key_data = open('/path/to/public_key.pem', 'r').read()
public_key = RSA.importKey(public_key_data)
random_key = Random.new().read(16)
cipher = PKCS1_v1_5.new(public_key)
encrypted_random_key = cipher.encrypt(random_key)
print(encrypted_random_key)
cipher = ARC4.new(random_key)
encrypted_message = cipher.encrypt(message)
print(encrypted_message)

你可以在 => 查看我的帖子http://helpfulsheep.com/2017-09-01-openssl -seal-in-python/

What openssl_seal does is:

  1. Extract the public_key from the certificate
  2. Generate a 128 bits (16 bytes) long random_key (this will be used to encrypt the message using a symmetrical algorithm, since it's faster)
  3. Encrypt the random_key using PKCS #1
  4. Encrypt the message using ARC4 a secure cipher method and the random_key (Note that ARC4 is no longer considered secure and that PHP strongly recommends to explicitly specify a secure cipher method using the cipher_algo param)
  5. Output the encrypted_random_key and the encrypted_message

The receiving party can then decrypt the encrypted_random_key using their private_key and then decrypt the encrypted_message using the random_key.

Since there's no way of doing this in Python via the standard library, I'm just gonna' throw out the 3 approaches that I've tried out:

# pyca/cryptography (cryptography.io) version
# pip install cryptography

import os

import cryptography
from cryptography import x509


message = 'Super secret secret message'
message = message.encode('utf-8')
certificate_data = open('/path/to/certificate.cer', 'r').read()
certificate_data = certificate_data.encode('utf-8')
certificate = cryptography.x509.load_pem_x509_certificate(data=certificate_data, backend=cryptography.hazmat.backends.default_backend())
public_key = certificate.public_key()
random_key = os.urandom(16)
encrypted_random_key = public_key.encrypt(plaintext=random_key, padding=cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15())
print(encrypted_random_key)
algorithm = cryptography.hazmat.primitives.ciphers.algorithms.AES(random_key)
cipher = cryptography.hazmat.primitives.ciphers.Cipher(algorithm=algorithm, mode=None, backend=cryptography.hazmat.backends.default_backend())
encryptor = cipher.encryptor()
encrypted_message = encryptor.update(message)
print(encrypted_message)

.

# M2Crypto version
# pip install pip install git+https://gitlab.com/m2crypto/m2crypto@python3

import M2Crypto


message = 'Super secret secret message'
message = message.encode('utf-8')
certificate = M2Crypto.X509.load_cert('/path/to/certificate.cer')
public_key = certificate.get_pubkey()
rsa_pub = public_key.get_rsa()
random_key = M2Crypto.Rand.rand_bytes(16)
encrypted_random_key = rsa_pub.public_encrypt(random_key, M2Crypto.RSA.pkcs1_padding)
print(encrypted_random_key)
cipher = M2Crypto.EVP.Cipher(alg='aes_128_cbc', key=random_key, iv=b'', op=M2Crypto.encrypt)
encrypted_message = cipher.update(message)
encrypted_message += cipher.final()
print(encrypted_message)

.

# PyCrypto version
# Update: PyCrypto 2.x is unmaintained, obsolete, and contains security vulnerabilities!!!
# pip install pycrypto

# Please bear in mind that PyCrypto cannot handle x509 certificates.
# You will have to extract the public_key to a pem file:
# openssl x509 -inform pem -in certificate.cer -pubkey -noout > public_key.pem

from Crypto import Random
from Crypto.Cipher import ARC4
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA


message = 'Super secret secret message'
message = message.encode('utf-8')
public_key_data = open('/path/to/public_key.pem', 'r').read()
public_key = RSA.importKey(public_key_data)
random_key = Random.new().read(16)
cipher = PKCS1_v1_5.new(public_key)
encrypted_random_key = cipher.encrypt(random_key)
print(encrypted_random_key)
cipher = ARC4.new(random_key)
encrypted_message = cipher.encrypt(message)
print(encrypted_message)

You can check out my post at => http://helpfulsheep.com/2017-09-01-openssl-seal-in-python/

少年亿悲伤 2024-09-07 18:51:58

由于我还不能发表评论,我需要添加 Gabi Nagy 的答案,虽然他们的答案描述了正确的算法,但它与使用 openssl_seal() 函数不同。

OpenSSL 不会让未加密的密钥进入 OpenSSL 结构之外。它在内部某处生成密钥并将其保存在那里,只为您提供加密的密钥。关键的区别在于,当 OpenSSL 清理其结构时,它应该以安全的方式处理未加密的密钥。

Since I can't post comments yet, I need to add to Gabi Nagy's answer, that while their answer describes a correct algorithm, it is not the same as using openssl_seal() function.

OpenSSL doesn't let unencrypted key to get outside of OpenSSL structures. It generates key somewhere inside and keeps it there, giving you only encrypted key. The crucial difference is that when OpenSSL cleans it's structures, it should dispose of unencrypted key in a safe way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文