我使用this example使用php openssl
库生成的密钥进行javascript加密,但$details = openssl_pkey_get_details($resource)
没有返回公共指数($details['rsa']['e']
)。
这就是我生成它的方式:
function genKeys() {
// Create the keypair
$res=openssl_pkey_new();
// Get private key
$pass = bin2hex(mcrypt_create_iv(100, MCRYPT_DEV_URANDOM));
openssl_pkey_export($res, $pk, $pass);
$details = openssl_pkey_get_details($res);
print_r($details);
$details = array('n'=>$details['rsa']['n'],'e'=>$details['rsa']['e']);
return array($pk,$details,$pass);
}
function to_hex($data)
{
return strtoupper(bin2hex($data));
}
$details = genKeys()[1];
当我使用print_r
打印$details
数组时,我得到:
Array
(
[bits] => 2048
[key] => -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt+S0ZxgyQ7BPcmz/JEa7
yEhcKDZTE9TgOF/9cW1w+quFvC43daYmyRpT3asYOm7YPGCmaQ7hUx9XKUUlEdXz
Zr1uvvDyFZdtS45+4nQ5DOI20mZoUHGV82rAMmvf5vote/JJu8Gt01ZUARfsMl+K
DtwpVDHN6LGPBOW8l8abktk1tL/oiwLSVrO2cM/IgBZETDkQpUaZxZx3yUcueEQ+
BFrtS3IYaEny938daQzElNdCaip0f68Ig0gOTPzwkzDOgyOhyjFRxx4aisGzIlXu
TFkqzIz7oC3JysgS5EhlwmsEIAelbZWpgc17HK2aWIzqlT99hB+kKv2fauxH/fgT
nQIDAQAB
-----END PUBLIC KEY-----
[rsa] => Array
(
[n] => ���g2C�Orl�$F��H\(6S��8_�qmp����.7u�&�Sݫ:n�<`�i�SW)E%��f�n����mK�~�t9�6�fhPq��j�2k���-{�I����VT�2_��)T1�豏弗ƛ��5�����V��p�ȀDL9�F�Ŝw�G.xD>Z�KrhI��iĔ�Bj*t��HL���0#��1Q����"U�LY*̌��-����He�k �m����{��X���?}��*��j�G���
[e] =>
[d] => ~����G�P�t���@��5��z�nEk�m��� qИ���i�k�%�ĨS���{/�:(��0�И<MS��ʓ�r�kڷ��lRu}q��?���V���g|�i��H��]2-X%U��R�\|9h�Xs��&g���܉9S8�\����bL�_`[.w}6��d�Ù
IroD�N�*��\�Q��3|���X�k7�mYs����.�m���Ã�#��~�ǀ�8{�L�s`�O���]�T��
��
[p] => ���ɺ;�n%\,b4�]7��)��Z���е삽�66i8a�`��P#�?.�ޙ,���sq��L�HF����{8��C ���"�
>H,���A������������H�g��̓3G�mBrY`�S�
[q] => ���.VӦ�(����hZ�jTY���3���B��ք9SuMw&.^�Ƹ�d�T!9i�u�K�#�*Fc�FY��*\�iO0b���Б]iei��� �OMDӒw,V�wӾK��r�%X��[��˓4=-�h�2
[dmp1] => �ី���X��U�ܵ���}�-#́�|~�.�=�0���SjN@����V+A�<e!$3��~�"��g�������~s�� y
x5�i��(�Y�X�;X�Tn���<w�$#�#��P�3�d�Uk�
[dmq1] => �$�!Q3��Zk�{ӗ�\����I2[*V5���&kے��yr�����b�[1gpc�y?�0Gf3��i���=א�!ܜ�7�a^܉I��a$����v�x����˲�[=��ʹW�'���%�"�B
[iqmp] => &���jx�� ������&��'��Ya�B�����)��H-�<�uĮ1��H���Fwy����Xbt[;����I�2*�6���������i�ډ���3@�;�Lt.���`h�qb�N�2�"����
)
[type] => 0
)
所以,在javascript中,当我使用:
var rsa = new RSAKey();
rsa.setPublic('<?php echo to_hex($details['rsa']['n']) ?>', '<?php echo to_hex($details['rsa']['e']) ?>');
我没有为公共指数输入任何东西,当我尝试在服务器上解密它时,它什么都不返回。
其中,因为这是我找到的唯一可能,我认为这可能是错误的原因。
我用以下方法解密它:
function prKeyDecrypt($data,$prKey,$passKey){
$data = pack('H*', $data);
$pkres = openssl_pkey_get_private($prKey,$passKey);
if (openssl_private_decrypt($data, $r, $pkres)) {
return $r;
} else {
return "error";
}
}
if(isset($_POST['data'])echo prKeyDecrypt($_POST['data'],$prKey,$passKey);
$prKey
和$passKey
都来自之前的genKeys()
声明。
是否有不同的方法来执行此操作,或者使用服务器上的php中生成的公钥信息来加密客户端上的javascript中的数据?设置得很好,所以我想使用我拥有的东西,但是如果有另一种方式可以使用它(比如不同的javascript库),那么工作比不工作:)
答案 0 :(得分:0)
这是一个有趣的谜题。这是一种获得模数和公共指数的圆形方法。
您可以找到一个用PHP here编写的简单ASN.1解析器。生成RSA密钥对后:
// Create the keypair
$res = openssl_pkey_new();
$details = openssl_pkey_get_details($res);
您可以将公钥从PEM转换为DER格式以用于ASN.1解析器,然后将其提供给解析器:
function pem2der($pem)
{
$matches = array();
preg_match('~^-----BEGIN ([A-Z ]+)-----\s*?([A-Za-z0-9+=/\r\n]+)\s*?-----END \1-----\s*$~D', $pem, $matches);
return base64_decode(str_replace(array("\r", "\n"), array('', ''), $matches[2]));
}
$der = pem2der($details['key']);
$asn = ASN_BASE::parseASNstring($der);
然后你可以进入公钥的ASN.1格式,并拉出模数和指数 - 我们直接知道在哪里找到它们。
这个特定的ASN.1解析器收集修改后的Base64格式的值,可以将其反转,然后将值转换为十六进制格式以传输到客户端:
function asn_integer_to_hex($value)
{
// The ASN.1 parser strtr'd these -- strtr them back
$bin = base64_decode(strtr($value, '-_', '+/'));
// Remove any leading 0x00 byte, too, and return hex
return bin2hex(ord($bin[0]) == 0 ? substr($bin, 1) : $bin);
}
$arr = $asn[0]->data[1]->data[0]->data;
$n = asn_integer_to_hex($arr[0]->value);
$e = asn_integer_to_hex($arr[1]->value);
这些应该与私钥中的详细信息匹配:
echo "$details n: ".bin2hex($details['rsa']['n'])."\n";
echo "$details e: ".bin2hex($details['rsa']['e'])."\n";
echo "n: ".$n."\n";
echo "e: ".$e."\n";
也就是说,如果$ details [&#39; rsa&#39;]有任何要显示的内容。我无法解释为什么[&#39; e&#39;]在您的情况下为空,但您应该能够通过解析ASN.1将指数从公钥中拉出来。
答案 1 :(得分:0)
即使指数在print_r()
中看起来是空的,但它肯定不是;获取您在问题中生成的公钥:
$key = openssl_pkey_get_public('-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt+S0ZxgyQ7BPcmz/JEa7
yEhcKDZTE9TgOF/9cW1w+quFvC43daYmyRpT3asYOm7YPGCmaQ7hUx9XKUUlEdXz
Zr1uvvDyFZdtS45+4nQ5DOI20mZoUHGV82rAMmvf5vote/JJu8Gt01ZUARfsMl+K
DtwpVDHN6LGPBOW8l8abktk1tL/oiwLSVrO2cM/IgBZETDkQpUaZxZx3yUcueEQ+
BFrtS3IYaEny938daQzElNdCaip0f68Ig0gOTPzwkzDOgyOhyjFRxx4aisGzIlXu
TFkqzIz7oC3JysgS5EhlwmsEIAelbZWpgc17HK2aWIzqlT99hB+kKv2fauxH/fgT
nQIDAQAB
-----END PUBLIC KEY-----');
$details = openssl_pkey_get_details($key);
echo bin2hex($details['rsa']['e']); // "010001"
答案 2 :(得分:0)
以下是我的工作方式(比拟议的方法简单得多);
<?php
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey('-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt+S0ZxgyQ7BPcmz/JEa7
yEhcKDZTE9TgOF/9cW1w+quFvC43daYmyRpT3asYOm7YPGCmaQ7hUx9XKUUlEdXz
Zr1uvvDyFZdtS45+4nQ5DOI20mZoUHGV82rAMmvf5vote/JJu8Gt01ZUARfsMl+K
DtwpVDHN6LGPBOW8l8abktk1tL/oiwLSVrO2cM/IgBZETDkQpUaZxZx3yUcueEQ+
BFrtS3IYaEny938daQzElNdCaip0f68Ig0gOTPzwkzDOgyOhyjFRxx4aisGzIlXu
TFkqzIz7oC3JysgS5EhlwmsEIAelbZWpgc17HK2aWIzqlT99hB+kKv2fauxH/fgT
nQIDAQAB
-----END PUBLIC KEY-----');
$publickey = $rsa->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_RAW);
echo $publickey['e'];
您需要phpseclib, a pure PHP RSA implementation来执行此操作。