2016-09-06 82 views
2

我有麻烦在PHP解密使用RSA一些数据,我在JS已经加密:OpenSSL的解密JSBN加密

一些数据(32字节,对于RSA足够短)使用JSEncrypt加密客户端和服务器的公钥。

服务器使用其解密:

openssl_private_decrypt(BASE64_DECODE($ result_obj [ '数据']),$解密,$ pkcs_private_key);

但是,这返回44bytes,很明显这是错误的!我已经逐字节地检查过了,似乎它几乎是在解密字符串中的某些位置删除字节,但并不那么简单。

我检查了填充openssl支持,它使用PKCS#1v1.5type1,而JSEncrypt似乎使用PKCS#1v1.5type2。这可能是问题吗?我见过使用PKCS#1v1.5type2的openssl存在问题的人,因此,我们可以使用此填充,但我无法弄清楚......如何解决任何帮助!

编辑:为了更详细地说明的加密系统:

的数据进行加密的客户端是一个32字节数组。在这个例子中,我将使用数组[182,13,97,94,164,102,129,70,192,52,94,65,243,190,57,48,153,161,46,32 ,122,64,53,237,62,130,60,1,22,184,28,231]。

它被使用加密:

arr2str(arr: number[]): string { 
    var result = ''; 
    for (var i = 0; i < arr.length; i++) { 
     result += String.fromCharCode(arr[i]); 
    } 
    return result; 
} 

encryptRSA(data: number[], key: string): string { 
    var enc = new window.JSEncrypt(); 
    enc.setPublicKey(key); 
    return enc.encrypt(this.arr2str(data)); 
} 

的关键是产生服务器的私钥的PKCS#1公钥。我们将使用关键

----- BEGIN PUBLIC KEY ----- \ nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyJ824ZiwMiCMrrHrDq1IKLwL8 \ nQWg + ZzwMprrG85k0nxEB8ZJn + s2lXhS4pOE0Nu6I9XiXjtyDbnT8kQvaWLve593v \ nDzC16wP9IKrAdmeV9CExMzKAHbFSvNTTn3TWjaKy9OnH + 7Uv/VVn63AQZXaqvY/W \ nbPVdTKn4Nx7vl + laOwIDAQAB \ n ---- -END PUBLIC KEY -----

----- BEGIN RSA私钥----- MIICXAIBAAKBgQCyJ824ZiwMiCMrrHrDq1IKLwL8QWg + ZzwMprrG85k0nxEB8ZJn + s2lXhS4pOE0Nu6I9XiXjtyDbnT8kQvaWLve593vDzC16wP9IKrAdmeV9CExMzKA HbFSvNTTn3TWjaKy9OnH + 7Uv/VVn63AQZXaqvY/WbPVdTKn4Nx7vl + laOwIDAQAB AoGASP3b4HgkBgJk/ojNR4vSsg9u1rFpp1 + ej8Rj9A1sMM4XJse151ovlVhFfx02 k7EJ7B0 + ikHjAQppbe1zgMMoPUuDOQc9VF2A2Tsf71kMagbQpNrLNiTIu6DNwzHI ivubmYBs73s2MyZmK7G8D/QRDs0qQNXdUfAKMBIUh9wQj0kCQQD5Urh18NWmW7w8 4MDFmjdalSbE9Dg38mfrlUne0KSCvwyX2zkoh/uc1eB + hqONwDkuw8VLTBgxDm + L 7jwOlmiVAkEAtu0uNEewMHi1oCIvRoS1n/UDqEHzuwFuxg + cNwAKJoN1ljqKIfqa jFLGawkyHIK2fLhP8OSQeyDi3kSoIMJzjwJAT0737FRqsdt2emsIBxNyTjcpuPby tyE921uGvwDhg9GgAOI0QWdYK2CBY94SQrIFvpF5veT7wQcVho6GviEsLQJABGj7 cC86RDDk0BOC6ERSzKRvjiLo6V1Demrt7TWHCR6qOxD2O5N7Hl7wgawbFSzhkWgw JTKdeRp13b3x/7gwaQJBAOpgGkEJKcwRFdamFYZwMGbueqkpqG/AmfNXblrOv70N CkB9YP3skoZ69 + vFr1TJXfz23lHpwQdPkRXhjlc/GLS = ----- END RSA PRIVATE KEY -----

服务器接收到此加密数据。看来,JSEncrypt b64_encodes它,所以我们必须使用

openssl_private_decrypt(BASE64_DECODE($ result_obj [ '数据']), $解密,$ pkcs_private_key)解密;

然而,我接收字节数组:

[194,182,13,97,94,194,164,102,194,129,70,195,128,52,94,65 ,195,179,194,190,57,48,194,153,194,161,46,32,122,64,53,195,173,62,194,130,60,1,22,194,184 ,28,195,167]。

也许这跟JS的arr2str函数有关。但是,我不明白怎么不使用它,因为JSEncrypt期望加密一个字符串。我认为该功能没有修改字节...

对于本示例的完整性起见,JSEncrypt返回的编码数据:

E728nXaCUUSTzuGLB5QIkodddyUMUMR0rEM5Ad7qL3SEtGJVukMjsQt7NAaRyXz1P3n2qK/iBGcuUBy2bPg5pTwk1twVZc2BzXueZYcKxxOby8AkNTgF9YMPlh1FMjD5c0UAiwcb7DnykvbsulG4h + FlxEy + 28eMTfRvjZmpq + 4 =

这是openssl_private_decrypt尝试解密的内容。

+0

base64_decode($ decrypted)会产生一个长度为6的字符串,可悲的是,它们的字节甚至不是我正在寻找的第一个字节。但也许你的意思是别的? – Ottunger

+0

那么,我已经检查了strlen,以及解压缩(“C *”,$解密),返回一个长度为6的数组,并允许我检查每个字节的字节数 – Ottunger

+0

我期望的字节数:[182,13,第97,94,164,102,129,70,192,52,94,65,243,190,57,48,153,161,46,32,122,64,53,237,62, 1,22,184,28,231],我收到的:[194,182,13,97,94,194,164,102,194,129,70,195,128,52,94,65,195 ,179,194,190,57,48,194,153,194,161,46,32,122,64,53,195,173,62,194,130,60,1,22,194,184,28 ,195,167] – Ottunger

回答

2

对于后代,我发现了这个问题。 事实上,它位于两个库之间的填充不兼容。

因此我设置解密模式为 “无填充” 在PHP:

openssl_private_decrypt(BASE64_DECODE($ result_obj [ '数据']), $解密,$ pkcs_private_key,OPENSSL_NO_PADDING);

而且我已经把在PHP中的JS做了去填充:

function pkcs1unpad2($b, $bits = 4096) { 
    $i = 0; 
    $n = ($bits + 7) >> 3; 
    $l = strlen($b); 
    while($i < $l && ord($b[$i]) == 0) 
     ++$i; 
    if(ord($b[$i]) != 2) 
     return null; 
    ++$i; 
    while(ord($b[$i]) != 0) 
     if(++$i >= $l) 
      return null; 
    $ret = ""; 
    while(++$i < $l) { 
     $c = ord($b[$i]) & 255; 
     if($c < 128) { 
      $ret .= chr($c); 
     } elseif(($c > 191) && ($c < 224)) { 
      $ret .= chr((($c & 31) << 6) | (ord($b[$i+1]) & 63)); 
      ++$i; 
     } else { 
      $ret .= chr((($c & 15) << 12) | ((ord($b[$i+1]) & 63) << 6) | (ord($b[$i+2]) & 63)); 
      $i += 2; 
     } 
    } 
    return $ret; 
} 

pcks1unpad2($解密)

是我所期望的!