将 RSA 加密代码从 php 转换为 python

Converting RSA encryption code from php to python

我正在尝试连接到我的 python 应用程序中的 api。 所以 api 文档附带了 php 和 asp 示例代码,但没有 python

我很擅长 php 但没有加密经验...我正在尝试使用 [=57] 为 api 重写 python 代码=]样本.

他们将此 class 用于 RSA

 https://github.com/AlaFalaki/Pclass/blob/master/libraries/rsa.class.php

(因为它是一个 RSA 库,我猜 python RSA 库会处理这部分):

static function rsa_sign($message, $private_key, $modulus, $keylength) {
  $padded = RSA::add_PKCS1_padding($message, false, $keylength / 8);
  $number = RSA::binary_to_number($padded);
  $signed = RSA::pow_mod($number, $private_key, $modulus);
  $result = RSA::number_to_binary($signed, $keylength / 8);
  return $result;
 }

这就是问题所在 php 符号函数采用 4 个参数使用一些内部函数...但是 python rsa 有 3 个,其中之一就是哈希方法!

rsa.sign(message, priv_key, hash)
Parameters: 
  message – the message to sign. Can be an 8-bit string or a file-like object. If message has a read() method, it is assumed to be a file-like object.
     priv_key – the rsa.PrivateKey to sign with
     hash – the hash method used on the message. Use ‘MD5’, ‘SHA-1’, ‘SHA-256’, ‘SHA-384’ or ‘SHA-512’.

我尝试了一些小实验,看看我是否得到相同的输出

所以我在 php

中唱了一个简单的 text 字符串
echo base64_encode(RSA::rsa_sign(sha1("test"),$private_key,$modulus,$key_length));

我得到了

类似

dKt+4CocMNdIrtYCUr8aZykR8CpfmYUEEVONMuAPlM5mR70AoyzMhGjcEGB9fKLVC4rr5xt66w2ZmHqWO+p834rJmo9Fj57udRSY5wFs0VokMF2S2SMFn5WTYYmMBuWciRzZybWnfXcSIyp9Ibi28cdwl5hXJOMpXEJrNQLFy2s=

接下来我从他们给我的 xml 文件中提取 private_key , public_key ,模数 api 包含我的密钥(使用相同的RSA class ) 喜欢

$xmlObj = simplexml_load_string($xmlRsakey);

        $this->modulus = RSA::binary_to_number(base64_decode($xmlObj->Modulus));
        $this->public_key = RSA::binary_to_number(base64_decode($xmlObj->Exponent));
        $this->private_key = RSA::binary_to_number(base64_decode($xmlObj->D));
        $this->key_length = strlen(base64_decode($xmlObj->Modulus))*8;

我和他们一起做了一本python字典

def keys():
        obj = {
            'modulus' : "14417185111734127374105962730273......." ,
            'public_key' : "61111" ,
            'private_key' : "3739752306322843055980611965983321761993....." ,
            'key_length' : 1024 ,
        }
        return obj

并且我尝试在 python

中签署一个字符串
def sign(request):
    api  = keys()
    message = 'test'
    crypto = rsa.sign(message.encode('utf-8'), api['private_key'] , 'SHA-1')
    b64 = base64.b64encode(crypto)
    return HttpResponse(b64)

但我得到:

'str' object has no attribute 'n'

那是我失败的实验

正如我所说,我没有任何加密或 rsa 方面的经验....我想从使用过这些东西的人那里得到一些建议。

我应该放弃并使用 php 到 encrypt/decrypt 吗?

They use this class for RSA

https://github.com/AlaFalaki/Pclass/blob/master/libraries/rsa.class.php

我的建议:运行远离尖叫。

RSA 是一个安全问题的雷区。有很多事情你可以搞砸。因此,当有人 使用 BC 扩展在 PHP 中实现原语 时,这相当于赤身裸体站在行刑队面前并期望没有漏洞。

建议:Use Libsodium改为

libsodium 有 PHP 和 Python 绑定。

如果 RSA 不可避免...

如果您真的想要 RSA 而不是现代密码学,请查看 phpseclib

<?php
use 
$rsa = new RSA();

// HIGHLY RECOMMENDED FOR SECURITY:
$rsa->setEncryptionMode(RSA::ENCRYPTION_OAEP);
$rsa->setMGFHash('sha256');

$rsa->loadKey($yourPEMencodedRSAPublicKey);
$ciphertext = $rsa->encrypt($plaintext);

如果您要使用 RSA 加密,您必须遵循these cryptography rules。如果您的图书馆不允许您遵守这些规则,是时候切换到 libsodium 了。

另请注意,使用 RSA 加密大邮件既缓慢又危险:通常没有任何东西可以阻止邮件重新排序,这可能非常糟糕。

这里的解决方法是:使用对称密钥认证加密,使用RSA加密public密钥。这就是 EasyRSA 所做的,虽然我不知道任何 Python 等价物,所以我不能推荐它作为解决方案。

当然,如果你使用libsodium的crypto_box API你就不用担心了!