2016-09-06 81 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($解密)

是我所期望的!