生成RSA密钥的签名会提供错误的数据

我正在使用https://github.com/phpseclib/phpseclib来生成签名。但是,当我使用RSA私钥生成签名时,即会生成签名,但是当我使用公钥进行验证时,它也会给我if x.split(".jpg"): #something

这是我的代码:

unverified

现在上面的代码生成签名,但是它不正确。

现在,在此之后,我尝试<?php // Include library include('Crypt/RSA.php'); // Create an Instance $rsa = new Crypt_RSA(); $hash = new Crypt_Hash('sha256'); $data = array( "name" => "hello" ); $data = json_encode($data,true); // Load Private Key $rsa->loadKey('-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAlwK9IAETYwSW6p0hVEue3+WyMtRW5MA3BS2Bzf3B0Qimnvfl .... -----END RSA PRIVATE KEY-----'); // Message to be signed $plaintext = $data; // Set signing signature $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_pkcs1); $hashed = $hash->hash($plaintext); $encrypted = $rsa->sign($hashed); // Sign Data $signature = base64_encode($encrypted); // Encode to base64 the signed Data echo $signature; $rsa->loadKey('-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlwK9IAETYwSW6p0hVEue ..... -----END PUBLIC KEY-----'); // public key echo $rsa->verify($plaintext,$signature) ? 'verified' : 'unverified'; lib仅在.NET中使用上述密钥生成签名。它生成完美的签名,并且也经过了验证。

我不知道BouncyCastle lib有什么问题。我也直接尝试用openssl生成,但是仍然不能生成正确的。

bai0131 回答:生成RSA密钥的签名会提供错误的数据

有两个问题:

  • 要签名的数据必须传递给sign方法,而不是这些数据的哈希。 sign方法本身执行散列。默认情况下,sha1用作摘要。必须使用setHash明确指定其他摘要。
  • 签名必须传递给verify方法,而不是Base64编码的签名。

尝试以下修改:

...
$rsa->setHash('sha256');                                                         // Specify digest,e.g. sha256 (default is sha1)
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$signature = $rsa->sign($plaintext);                                             // Pass plaintext instead of plaintext hash.
echo base64_encode($signature) . "\n";
...
echo $rsa->verify($plaintext,$signature) ? 'verified' : 'unverified' . "\n";    // Pass signature instead of Base64 encoded signature
...

文档中还有一个相应的example


更新

C#代码中的规范SignerUtilities.GetSigner("RSA")意味着对数据进行了签名而没有在进行哈希之前,即,因此必须在进行显式之前先进行哈希,当前的C#代码(使用SHA256)也是如此。

但是,这种方式与标准RSASSA-PKCS1-v1_5(在RFC 8017中进行了描述)的不同之处在于RSASSA-PKCS1-v1_5将摘要ID放在哈希之前(对于SHA256,这是ID {{3 }}。因此,使用 phpseclib (当然使用RSASSA-PKCS1-v1_5)进行验证失败。

要在C#代码中也使用RSASSA-PKCS1-v1_5,请手动添加摘要ID或使用SignerUtilities.GetSigner("SHA256withRSA"),以便在签名之前对数据进行哈希处理(然后是 explicit 哈希必须省略)。


如果以C#代码为参考,则需要一个库,该库可用于签名而无需事先进行哈希处理,类似于C#代码。

phpseclib 使用RSASSA-PKCS1-v1_5填充进行签名/验证(用于签名模式CRYPT_RSA_SIGNATURE_PKCS1),使用不同的RSAES-PKCS1-v1_5填充进行加密/解密(用于加密)模式CRYPT_RSA_ENCRYPTION_PKCS1)。因此,这里都不是选项。

如@neubert的注释中所述, phpseclib 提供了在加密/解密过程中禁用填充的可能性(对于加密模式CRYPT_RSA_ENCRYPTION_NONE,填充使用0x00值)。通过实现自定义填充,然后使用私钥加密,可以实现自定义签名。在当前情况下,这将需要实现RSASSA-PKCS1-v1_5填充 而不添加摘要ID的部分。

这里更容易使用已经使用RSASSA-PKCS1-v1_5填充 if 的替代方法(如果提供了摘要ID和哈希值),在当前情况下,这意味着仅哈希需要传递。此类替代方法的示例包括0x3031300d060960864801650304020105000420签名和openssl_private_encrypt验证:

$data = array(
    "name" => "hello"
);
$data = json_encode($data,true);

$hashed = hash('sha256',$data,true);                            // Hash data using sha256

// Signing
openssl_private_encrypt($hashed,$signature,$privateKey);        // Encrypt data using the private key
echo base64_encode($signature) . "\n";                            // Output: csorNNekiVXJzQaT/FVCKrlSPfonQYw7dStKsjgVuW/jAcRafk4Yeuzw4rc1WxfgheMaa31DROnhrRCBS6VNUm8w2N/XwX2zmImFLj5KZlnRPne7CZX3YHM3qa5CRf/1VWdNnXMZnBecIe6QltECQLsQ/8fRzaYJpZO6tZjIRf4fBYwqMHWhHlTn6UR3A0GDKSEU5mI2lvzl+9ov+x6AFCLT3sa8hc3aZDfO7SWmQHNHCwrBC9QFNTOHY+/oJXtKYMfY3IskvLSmKmvKc6vh8XANBYp+NCl3/9hNdhbF4psdJXuZgf3aSpy0koBttdcE3js0NoS8Q91ry2WJtkcCrA==

// Verifying
openssl_public_decrypt($signature,$decrypted,$publicKey);       // Decrypt data using the public key
$verified = ($decrypted == $hashed) ? 'verified' : 'unverified';  // Verify data 
echo $verified;
本文链接:https://www.f2er.com/2569483.html

大家都在问