如何让 PHP 对与 C# 完全相同的输入进行签名?

Ada*_*own 6 php c# signing

我正在使用需要对 XML 进行签名的旧 API。没有适当的文档,唯一的代码示例是在 C# 中给出的。我需要将此示例移植到 PHP。但是,即使提供相同的输入,我用 PHP 编写的代码也会得到不同的输出,从而导致 API 调用失败。

我在 C# 中将它缩小到这个函数:

public byte[] CreateSignature(byte[] hash)
{
    RSAPKCS1SignatureFormatter signatureFormatter = new RSAPKCS1SignatureFormatter(pfxCert.PrivateKey);
    signatureFormatter.SetHashAlgorithm("SHA1");
    return signatureFormatter.CreateSignature(hash);
}
Run Code Online (Sandbox Code Playgroud)

这是 PHP 中的相同操作:

public function createSignature($hashByteArray, $certArray) {
    $hash = implode(array_map("chr", $hashByteArray));
    $hashEncoded = base64_encode($hash);
    openssl_sign($hashEncoded,$signature, $certArray);
    return unpack("C*", $signature);
}
Run Code Online (Sandbox Code Playgroud)

请注意, openssl_sign 中的输入不能采用字节数组,因此这可能是一个不同点。我已经尝试了 openssl_get_md_methods() 和 phpseclib 提供的所有算法,但都没有匹配输出。

我在C#PHP 中创建了相同示例输入和证书的 GitHub 要点,以更好地说明问题。

给定相同的输入,如何在 PHP 中获得与 C# 相同的签名输出?

Kul*_*gin 3

它们之间有根本的区别。

RSAPKCS1SignatureFormatter.CreateSignature方法需要数据哈希。另一方面期待数据本身openssl_sign

来自PHP:openssl_sign - 手册

openssl_sign() 通过使用与 priv_key_id 关联的私钥生成加密数字签名来计算指定数据的签名。请注意,数据本身未加密。

显然,您生成了一些数据的哈希值,以便与用 C# 编写的 API 一起使用。不要使用 来执行此操作openssl_sign,而是使用原始数据进行调用。openssl_sign将在签名之前对其进行哈希处理,这是设计使然。