RSA:在Python和PHP中从n和e生成公钥给我两个不同的公钥

2024-09-30 08:25:14 发布

您现在位置:Python中文网/ 问答频道 /正文

在python中,我从如下公钥中提取模数(n)和(e):

#! /usr/bin/python3.5
# -*- coding: utf-8 -*-

import rsa

(pubkey, privkey) = rsa.newkeys(512)
dec_n = pubkey.n
dec_e = pubkey.e

在base64中,n和e的值为:

^{pr2}$

我有以下公钥:

-----BEGIN RSA PUBLIC KEY-----
MEgCQQCIGqijUcytyQLcEVxC5gK4HDx7Y/c5aMJt9OOoWDfzcrifmZr0+8Q1i/LP
E+4fuBLlaPl6EmgSN2wlbF/svHZVAgMBAAE=
-----END RSA PUBLIC KEY-----

我尝试在PHP中生成相同的公钥。为此,我读了这篇文章:openssl: how can i get public key from modulus

所以我写了这个代码:

require_once("/var/www/phpseclib/Crypt/RSA.php");

$n = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIGqijUcytyQLcEVxC5gK4HDx7Y_c5aMJt9OOoWDfzcrifmZr0-8Q1i_LPE-4fuBLlaPl6EmgSN2wlbF_svHZV";
$e = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAB";

$rsa = new Crypt_RSA();

$modulus = new Math_BigInteger(base64_decode(urldecode($n)), 256);
$exponent = new Math_BigInteger(base64_decode(urldecode($e)), 256);

$rsa->loadKey(array('n' => $modulus, 'e' => $exponent));
$rsa->setPublicKey();

$pub_key = $rsa->getPublicKey();
print_r($pub_key);

但我有一个公钥:

-----BEGIN PUBLIC KEY-----
MFgwDQYJKoZIhvcNAQEBBQADRwAwRAI9AIgaqKNRzK3JAtwRXELmArgcPHthzlowm3046hYN/NyuJ+ZmvTxDWIs8Th+4EuVo+XoSaBI3bCVsWy8dlQIDAQAB
-----END PUBLIC KEY-----

Tags: keynewpublicrsadecend公钥begin
1条回答
网友
1楼 · 发布于 2024-09-30 08:25:14

造成这种差异的原因有两个:首先,公钥在Python代码中以PKCS1格式([1][2])显示,在PHP代码中以X.509格式([1][3])显示。其次,Base64编码中有一个错误。在

  • Base64编码:在Python代码中,使用了Base64url-编码,而在PHP代码中仅使用标准Base64编码([4])。虽然使用Base64url编码的代码没有被发布,但这可以从编码数据中出现的字符-和{}来推断。要在PHP代码中使用Base64url解码(而不是Base64解码):

    $modulus = new Math_BigInteger(base64_decode(urldecode($n)), 256);
    

    必须替换为:

    ^{pr2}$

    使用([5]):

    function base64url_decode( $data ){
        return base64_decode( strtr( $data, '-_', '+/') . str_repeat('=', 3 - ( 3 + strlen( $data )) % 4 ));
    }
    

    同样地,指数也是如此。在

    因此,PHP代码返回以下公钥:

      -BEGIN PUBLIC KEY  -
    MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIgaqKNRzK3JAtwRXELmArgcPHtj9zlo
    wm3046hYN/NyuJ+ZmvT7xDWL8s8T7h+4EuVo+XoSaBI3bCVsX+y8dlUCAwEAAQ==
      -END PUBLIC KEY  -
    

    注意:模数和指数的Base64url解码为十六进制:

    modulus : 0000000000000000000000000000000000000000000000000000000000000000881aa8a351ccadc902dc115c42e602b81c3c7b63f73968c26df4e3a85837f372b89f999af4fbc4358bf2cf13ee1fb812e568f97a126812376c256c5fecbc7655
    
    exponent: 000000000000000000000000000000000000000000010001
    

    用许多0-值填充是不必要的(除了符号字节),它不包含任何信息,只会增加数据量。

  • 格式:最后一步的公钥内容相同,只是格式不同(X.509)。最简单的方法是使用([6])以PKCS1格式另外显示公钥:

    $pub_key = $rsa->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
    print($pub_key . "\n");
    

    PKCS1格式的公钥与Python代码的密钥相匹配。另一种可能是在ASN.1编辑器中直接比较这两个键,例如联机([7])。

  • 顺便说一下:要在PHP代码中也使用Python代码的公钥,不需要通过模数和指数绕道。使用([6])更容易实现这一点:

    $rsa = new Crypt_RSA();
    
    $keydata = "  -BEGIN RSA PUBLIC KEY  -\n
    MEgCQQCIGqijUcytyQLcEVxC5gK4HDx7Y/c5aMJt9OOoWDfzcrifmZr0+8Q1i/LP
    E+4fuBLlaPl6EmgSN2wlbF/svHZVAgMBAAE=
    \n  -END RSA PUBLIC KEY  -";
    
    $rsa->loadKey($keydata);
    $rsa->setPublicKey();
    
    $pub_key = $rsa->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
    print($pub_key . "\n");
    
    $pub_key = $rsa->getPublicKey();
    print($pub_key . "\n");
    

相关问题 更多 >

    热门问题