VB.NET与PHP之间RSA的互操作性

时间:2011-04-16 07:59:30

标签: php vb.net encryption openssl rsa

我使用OpenSSL和PHP生成PEM格式的公钥/私钥。

在PHP中,我创建公钥/私钥:

// generate a 1024 bit rsa private key
$privateKey = openssl_pkey_new(array(
    'private_key_bits' => 1024,
    'private_key_type' => OPENSSL_KEYTYPE_RSA,
));
// Save Private key
openssl_pkey_export_to_file($privateKey, 'privateKey');

// get the public key 
$keyDetails = openssl_pkey_get_details($privateKey);
// Save Public key
file_put_contents('publicKey', $keyDetails['key']);

在VB.NET中我编写代码:

'Public Key
Dim sReader As String ="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxYT5RaHelEBmk4Z7ppiVaPPBns/36sdY12F/AXETJVl2SYkjc672JMz ..... zQwIDAQAB"
Dim PublicKey As Byte() = Encoding.UTF8.GetBytes(sReader)
Dim Exponent As Byte() = {1, 0, 1}

    'Create a new instance of RSACryptoServiceProvider.
    Dim RSA As New RSACryptoServiceProvider()

    'Create a new instance of RSAParameters.
    Dim RSAKeyInfo As New RSAParameters()

    'Set RSAKeyInfo to the public key values. 
    RSAKeyInfo.Modulus = PublicKey
    RSAKeyInfo.Exponent = Exponent

    'Import key parameters into RSA.
    RSA.ImportParameters(RSAKeyInfo)

    'Create a UnicodeEncoder to convert between byte array and string.
    Dim ByteConverter2 As New UnicodeEncoding()

    'Create byte arrays to hold original, encrypted, and decrypted data.
    bytPlainText = Encoding.UTF8.GetBytes("Data to Encrypt")
    bytCipherText = RSA.Encrypt(bytPlainText, False)
    Dim sEncrypt99 As String = Convert.ToBase64String(bytCipherText)

但我不能用私钥解密PHP中的“sEncrypt99”

对于测试,我在“$ encryptedData1”中复制了“sEncrypt99”

<?php
$privateKey = openssl_pkey_get_private('file://privateKey');
openssl_private_decrypt(base64_decode($encryptedData1), $sensitiveData2, $privateKey);

echo "sensitiveData = " . $sensitiveData2 . "<br>";
?>

没有错误,$ sensitiveData2为空。奇怪...... 问题出在哪儿 ?

Rem:我的英语很差,我是法国人的借口;)

2 个答案:

答案 0 :(得分:0)

我会检查公钥的openssl版本和.NET版本之间的模数和指数是否匹配。

对于1024位密钥,RSAParameters.Modulus数组必须精确为128个字节。 DER字节可能有一个前导零字节,使其成为129字节 - 确保包含它。 .NET数组必须正好是128个字节(对于1024位密钥。)

我会从openssl转储公钥,并检查数组。例如:

  1. 从PHP / OpenSSL端的私钥文件中单独获取公钥:

    $ openssl rsa -in private-key.pem -pubout -out public-key.pem

  2. 使用openssl asn1parse解析公钥:

    $ openssl asn1parse -in public-key.pem

    0:d = 0 hl = 3 l = 159 cons:SEQUENCE
    3:d = 1 hl = 2 l = 13 cons:SEQUENCE
    5:d = 2 hl = 2 l = 9 prim:OBJECT:rsaEncryption

    16:d = 2 hl = 2 l = 0 prim:NULL
    18:d = 1 hl = 3 l = 141 prim:BIT STRING

  3. 解析其中包含实际RSA公钥的BIT STRING(PKCS1 ASN.1表单):

    $ openssl asn1parse -in public-key.pem -strparse 18

        0:d=0  hl=3 l= 137 cons: SEQUENCE          
        3:d=1  hl=3 l= 129 prim: INTEGER           :B404886A7F0544C14AAE14EEE531A2D78122C9BFDB06E8C80433559A617FD159A05F8FD45500BBA63A1D07239C26BD8D32D3550D5DEAF7BF9C16D3E16BDE5A9BB56C378CB9E0E7DA9D3A5513482D74E1FDCCAC147D0E909D1B620598F710B437D50DE8F80D5F742B6DA6E2D2ED1BBEBF89A40546103A8451B59D8190633ACFA5
      135:d=1  hl=2 l=   3 prim: INTEGER           :010001
    
  4. 从B4 04 88开始的那个数组...(即你看到的密钥值)应与你在RSAParameters中设置的字节数组相匹配。我很确定这个顺序(即DER顺序)是你在RSACryptoServiceProvider模数数组中找到的(即[0] = 0xb4,[1] = 0x04等)。另外,你可以验证指数(第二个整数)上面显示为01 00 01。)

答案 1 :(得分:0)

我知道这个帖子有点过时,但我尝试完全相同的事情。我遇到了'file:// privateKey'的问题。将其废弃并使用fopen,或将密钥存储在变量中。为我工作:))