如何像在 1.0 版中那样使用 PHPSeclib 2.0 版获取签名字符串?
How can I use version 2.0 of PHPSeclib to get a signed string as I did in version 1.0?
我参与的一个项目中,一位队友添加了 phpseclib (for php5),我们使用下面的代码对加密字符串进行签名,并将其与请求一起发送到内部 API 以进行验证过程。
function GetSignature($message) {
$rsa = new Crypt_RSA();
$sPath = PRIVATE_KEY_FILE; //defined elsewhere
$sKey = file_get_contents($sPath);
$rsa->LoadKey($sKey);
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
return $rsa->sign($message);
};
对于包含与 URL 连接的时间戳的字符串(例如 1490239371+https://api-domain/api/endpoint),将生成如下所示的字符串。此字符串在请求 header 中发送,下面的字符串是内部 API 的控制台日志中的输出。
Rsh1dv5ZGaPjCb6pgEsMrXwZbAeVgxVK/+5d5bxu7BfDzaILl++/pi/WxDP4H2qJ7Ayp6QnYXGckIIYX9l9fKOJoShOZOkB19RxaNdBL5vLjKk409XVRY/GKGz3kHmZmTcyBYDPQaT/VFOQTd7+o0d1mBY4EbHadI3f+kahHz4U=
在一个较新的项目中,我试图重新创建它,因为我们需要利用相同的内部 API。较新的项目正在使用 composer(和 laravel),因此向其添加了 phpseclib version 2.0。常量已更改为 class 常量,但除此之外,方法似乎是相同的。下面是我添加的代码,用于在另一个代码库中复制以前的代码。
use phpseclib\Crypt\RSA as Crypt_RSA;
class EncyptionController {
public static function GetSignature($message) {
$rsa = new Crypt_RSA();
$path = config('app.encryption_key_path') . '/certs/private.pem';
$rsa->loadKey(file_get_contents($path));
$rsa->setSignatureMode(Crypt_RSA::SIGNATURE_PKCS1);
return $rsa->sign($message);
}
使用较新的代码,相同格式的字符串将生成包含 unicode 字符的加密字符串。下面的字符串出现在内部 API 的控制台日志中(当记录在请求 headers 中收到的值时)。
=���˭\u0003�uʂ\u000e_\u0013\u000bd)w�8�\u0018�����q
在 Laravels 日志中记录显示它带有 unicode 字符(没有编码的实体 - 我在 notepad++ 中打开它):
=žšîË´uÊ‚_d)wË8ƒ”ñ‘¤úqýÁ‹þ:‹dºäÿLÈ?!F§?…ãIEìê*K®gUþèÎÅ
然后内部 API 使用 public 密钥解密编码的字符串。对于较新的代码库,这会失败。内部API在Nginx/NodeJS中实现,使用crypto and its verifier.verify()方法。
更新:
基于 by Álvaro González, it has come to light that the version 2.0 sign() method returns a raw binary hash. I can use base64_encode()对其进行base-64编码,但该字符串(88个字符)比1.0版本生成的字符串(172个字符)短很多。
return base64_encode($rsa->sign($message));
版本 1.0 字符串 - 172 个字符长:
Rsh1dv5ZGaPjCb6pgEsMrXwZbAeVgxVK/+5d5bxu7BfDzaILl++/pi/WxDP4H2qJ7Ayp6QnYXGckIIYX9l9fKOJoShOZOkB19RxaNdBL5vLjKk409XVRY/GKGz3kHmZmTcyBYDPQaT/VFOQTd7+o0d1mBY4EbHadI3f+kahHz4U='
"Rsh1dv5ZGaPjCb6pgEsMrXwZbAeVgxVK/+5d5bxu7BfDzaILl++/pi/WxDP4H2qJ7Ayp6QnYXGckIIYX9l9fKOJoShOZOkB19RxaNdBL5vLjKk409XVRY/GKGz3kHmZmTcyBYDPQaT/VFOQTd7+o0d1mBY4EbHadI3f+kahHz4U=
2.0 版字符串 - 88 个字符长:
mYT/MSb9UOuDDQ1RV893Ix7xh21IRHINs6o1PnhdhffgTAIeX4le1rfd+EzoPPJN9pvvwirm3CAbkeubGjXgWQ==
有没有设置签名字符串长度的方法?
在 v2.0 中是 RSA(),而不是 Crypt_RSA()。 http://phpseclib.sourceforge.net/2.0.html 详细说明。
无论如何,在 base64 中解码你的两个密文,然后得到每个的长度...第一个(由 phpseclib-php5 生成的)我得到 256 字节或 2048 位。第二个(phpseclib 2.0产生的那个)是64字节512位
我认为您为每个密钥使用了不同长度的不同密钥,这肯定会影响长度。
我参与的一个项目中,一位队友添加了 phpseclib (for php5),我们使用下面的代码对加密字符串进行签名,并将其与请求一起发送到内部 API 以进行验证过程。
function GetSignature($message) {
$rsa = new Crypt_RSA();
$sPath = PRIVATE_KEY_FILE; //defined elsewhere
$sKey = file_get_contents($sPath);
$rsa->LoadKey($sKey);
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
return $rsa->sign($message);
};
对于包含与 URL 连接的时间戳的字符串(例如 1490239371+https://api-domain/api/endpoint),将生成如下所示的字符串。此字符串在请求 header 中发送,下面的字符串是内部 API 的控制台日志中的输出。
Rsh1dv5ZGaPjCb6pgEsMrXwZbAeVgxVK/+5d5bxu7BfDzaILl++/pi/WxDP4H2qJ7Ayp6QnYXGckIIYX9l9fKOJoShOZOkB19RxaNdBL5vLjKk409XVRY/GKGz3kHmZmTcyBYDPQaT/VFOQTd7+o0d1mBY4EbHadI3f+kahHz4U=
在一个较新的项目中,我试图重新创建它,因为我们需要利用相同的内部 API。较新的项目正在使用 composer(和 laravel),因此向其添加了 phpseclib version 2.0。常量已更改为 class 常量,但除此之外,方法似乎是相同的。下面是我添加的代码,用于在另一个代码库中复制以前的代码。
use phpseclib\Crypt\RSA as Crypt_RSA;
class EncyptionController {
public static function GetSignature($message) {
$rsa = new Crypt_RSA();
$path = config('app.encryption_key_path') . '/certs/private.pem';
$rsa->loadKey(file_get_contents($path));
$rsa->setSignatureMode(Crypt_RSA::SIGNATURE_PKCS1);
return $rsa->sign($message);
}
使用较新的代码,相同格式的字符串将生成包含 unicode 字符的加密字符串。下面的字符串出现在内部 API 的控制台日志中(当记录在请求 headers 中收到的值时)。
=���˭\u0003�uʂ\u000e_\u0013\u000bd)w�8�\u0018�����q
在 Laravels 日志中记录显示它带有 unicode 字符(没有编码的实体 - 我在 notepad++ 中打开它):
=žšîË´uÊ‚_d)wË8ƒ”ñ‘¤úqýÁ‹þ:‹dºäÿLÈ?!F§?…ãIEìê*K®gUþèÎÅ
然后内部 API 使用 public 密钥解密编码的字符串。对于较新的代码库,这会失败。内部API在Nginx/NodeJS中实现,使用crypto and its verifier.verify()方法。
更新:
基于
return base64_encode($rsa->sign($message));
版本 1.0 字符串 - 172 个字符长:
Rsh1dv5ZGaPjCb6pgEsMrXwZbAeVgxVK/+5d5bxu7BfDzaILl++/pi/WxDP4H2qJ7Ayp6QnYXGckIIYX9l9fKOJoShOZOkB19RxaNdBL5vLjKk409XVRY/GKGz3kHmZmTcyBYDPQaT/VFOQTd7+o0d1mBY4EbHadI3f+kahHz4U=' "Rsh1dv5ZGaPjCb6pgEsMrXwZbAeVgxVK/+5d5bxu7BfDzaILl++/pi/WxDP4H2qJ7Ayp6QnYXGckIIYX9l9fKOJoShOZOkB19RxaNdBL5vLjKk409XVRY/GKGz3kHmZmTcyBYDPQaT/VFOQTd7+o0d1mBY4EbHadI3f+kahHz4U=
2.0 版字符串 - 88 个字符长:
mYT/MSb9UOuDDQ1RV893Ix7xh21IRHINs6o1PnhdhffgTAIeX4le1rfd+EzoPPJN9pvvwirm3CAbkeubGjXgWQ==
有没有设置签名字符串长度的方法?
在 v2.0 中是 RSA(),而不是 Crypt_RSA()。 http://phpseclib.sourceforge.net/2.0.html 详细说明。
无论如何,在 base64 中解码你的两个密文,然后得到每个的长度...第一个(由 phpseclib-php5 生成的)我得到 256 字节或 2048 位。第二个(phpseclib 2.0产生的那个)是64字节512位
我认为您为每个密钥使用了不同长度的不同密钥,这肯定会影响长度。