简体   繁体   中英

RSA: generate public key from n and e in Python and PHP give me two different public key

In python, I extract modulus (n) and (e) from a public key like this:

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

import rsa

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

In base64, the value of n and e are:

n:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIGqijUcytyQLcEVxC5gK4HDx7Y_c5aMJt9OOoWDfzcrifmZr0-8Q1i_LPE-4fuBLlaPl6EmgSN2wlbF_svHZV
e:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAB

And I have the following public key:

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

I tried to generate the same public key in PHP. To do this, I read this post: openssl: how can i get public key from modulus

So I wrote this code:

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

But I got this public key:

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

The difference is caused by two factors: First, the public key is displayed in the Python-code in the PKCS1-format ( [1] and [2] ), and in the PHP-code in the X.509-format ( [1] and [3] ). Secondly, there is a bug in the Base64-encoding.

  • Base64-encoding: In the Python-code the Base64 url -encoding was used and in the PHP-code only the standard Base64-encoding ( [4] ). Although the code with the Base64url-encoding isn't posted, this can be concluded from the characters - and _ occurring in the encoded data. To use Base64url-decoding (instead of Base64-decoding) in the PHP-code:

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

    must be replaced by:

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

    with ([5] ):

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

    And analogously also for the exponent.

    The PHP-code thus returns the following public key:

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

    Note: The Base64url-decoding of modulus and exponent is hexadecimal:

     modulus: 0000000000000000000000000000000000000000000000000000000000000000881aa8a351ccadc902dc115c42e602b81c3c7b63f73968c26df4e3a85837f372b89f999af4fbc4358bf2cf13ee1fb812e568f97a126812376c256c5fecbc7655 exponent: 000000000000000000000000000000000000000000010001

    The padding with the many 0 -values isn't necessary (apart from the sign-byte), contains no information and only increases the amount of data.

  • Format: The public key from the last step is identical in content and only differs in the format (X.509). The easiest way to show this is to additionally display the public key in the PKCS1-format with ( [6] ):

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

    The public key in the PKCS1-format matches the key of the Python-code. Another possibility is the direct comparison of both keys in an ASN.1 editor, eg online ( [7] ).

  • By the way: To use the public key of the Python-code also in the PHP-code, it isn't necessary to take the detour via modulus and exponent. This is much easier possible with ( [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");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM