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)
在实践中,摘要输出长度通常被用作盐长.