所以我try 用php库phpseclib v3验证rsa-ps签名.Php验证总是给我一个错误.但让我困惑的是,当我try 用php签署签名,并验证它在Golang和php中都有效时.

这是我在Golang中用来签名和验证签名的代码

签名

rng := rand.Reader
rsa.SignPSS(rng, key, crypto.SHA256, digest, nil)

验证签名

rsa.VerifyPSS(key, crypto.SHA256, digest, signature, nil)

这是用php验证和签名的代码.

验证签名

$key = RSA::loadPublicKey('the key');
$result = $key->withHash('sha256')->withMGFHash('sha256')->verify($message, $signature);

签名

$key = RSA::loadPrivateKey('the key');
$key = $private->withPadding(RSA::SIGNATURE_PSS);
$signature = $private->withHash('sha256')->withMGFHash('sha256')->sign($message);

NOTE个 签名的值在加密的Base64中返回,在验证签名之前我已经解密了该值

有谁能解释这是怎么发生的吗?我应该怎么做才能让它对两个人都有效呢?

推荐答案

PSS allows the specification of various parameters (s. RFC8017, 9.1.1): Digest, mask generation function (in practice, MGF1 is applied and only its digest can be specified) and salt length.
The verification with PHP fails because although you specify the digests explicitly (so that they are identical in both codes), you use the library defaults for the salt length, which are different. Therefore, the two codes are not compatible:

  • In your Go code, in the SignPSS() call the 5th parameter is specified as nil, so saltLength() gives PSSSaltLengthAuto, resulting in the maximum possible salt length being applied.
    The maximum possible salt length is signature length - digest output length - 2 in bytes (e.g. with a 2048 bits signature / key length and SHA256 as digest: 256 - 32 - 2 bytes).

  • 在PHP代码中,默认情况下,摘要输出长度(SHA256为32字节)用于盐长度S.

因此,为了让PHP代码验证GO代码的签名,必须使用withSaltLength()将SALT长度显式设置为最大大小:

$key = RSA::load($pubKey);
$result =   $key
            ->withHash('sha256')                // default (in V3)
            ->withMGFHash('sha256')             // default (in V3)
            ->withSaltLength(256 - 32 - 2)      // Fix! Replace 256 with your signature / key length in bytes
            ->verify($message, $signature);
print($result ? 'valid signature' : 'invalid signature'); // valid signature

为确保完整性:最大盐分长度也可通过以下方式确定:

$key->getLength()/8 - $key->getHash()->getLengthInBytes() - 2

或者,在PHP代码中默认应用的摘要输出长度(SHA256为32字节)可以用作GO代码中的SALT长度:

var ops rsa.PSSOptions
ops.SaltLength = rsa.PSSSaltLengthEqualsHash
signature, err := rsa.SignPSS(rng, keyPkcs8, crypto.SHA256, digest, &ops)

在实践中,摘要输出长度通常被用作盐长.

Php相关问答推荐

Laravel通过(扩展FormRequest类)方法验证表单请求

从WooCommerce邮箱通知中的订单详细信息中删除产品列表

未在moodle上运行的计划任务

在ShipStation for WooCommerce中使用自定义订单项目元数据

MariaDB 11.3.2+PHP:服务器向客户端发送未知的字符集(0).请向开发人员报告

Laravel eloquent-如果没有包含InitialValue的结果,则查询where Second Value

为什么正则表达式与得到的文本块之前得到的也行?

PHP -多维数组到一维数组

是否重新排序多维数组元素以将所有子数组中的子数组移动到元素列表的底部?

只收取WooCommerce中最高的运费

哪里的表现能更好?

在 PHP 中将字符串分解为数组(字符串类似于 WP 短代码)

主机中未检索用户表数据

使用 foreach php 将记录正确分配给正确的父级

MySQLI bind_param导致的Cannot modify readonly property错误

将样式文件或脚本引入WordPress模板

Eloquent 的模型更新了它应该 laravel php 的更多行

如何从 PHP 中的字符串位置排除图像扩展名

在全局安装 Composer 包后运行命令

为什么非贪婪匹配会消耗整个模式,即使后面跟着另一个非贪婪匹配