【发布时间】:2017-01-14 08:32:27
【问题描述】:
我在用 PHP 解密一些我在 JS 中使用 RSA 加密的数据时遇到了麻烦:
一些数据(32 字节,对于 RSA 来说足够短)在客户端使用 JSEncrypt 和服务器的公钥进行加密。
服务器使用以下方法对其进行解密:
openssl_private_decrypt(base64_decode($result_obj['data']), $decrypted, $pkcs_private_key);
但这会返回 44 字节,所以显然这是错误的!我一个字节一个字节地检查了,看起来这几乎是在解密字符串中的某些位置删除字节,但也不是那么简单。
我检查了填充 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 公钥-----
-----开始 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= -----结束 RSA 私钥-----
服务器接收此加密数据。看来 JSEncrypt b64_encodes 了它,所以我们必须使用来解密
openssl_private_decrypt(base64_decode($result_obj['data']), $decrypted, $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+Flx
这就是 openssl_private_decrypt 试图解密的内容。
【问题讨论】:
-
base64_decode($decrypted) 产生一个长度为 6 的字符串,遗憾的是,它的字节甚至不是我要寻找的第一个字节。但也许你的意思是别的?
-
好吧,我已经检查了 strlen,以及返回长度为 6 的数组的 unpack("C*", $decrypted),并允许我检查每个字节的字节
-
我期望的字节数:[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],我收到的那个:[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]
-
并且count返回但数字1,我想它会查找数组的维数。
-
已编辑。已经谢谢了