gpt4 book ai didi

php - 使用 PHP 进行签名的 RSA 和 SHA-256 加密

转载 作者:行者123 更新时间:2023-12-02 02:27:21 33 4
gpt4 key购买 nike

我正在接收来自 Web 服务 API 的请求中的 XML。它包含一个签名,由请求者的私钥签名,我必须通过请求者的公钥来验证它。然后我必须发送带有签名的响应,由我的私钥签名。

此过程应在 PHP 中使用 RSA 和 SHA-256 完成。

我目前有以下代码:

$data_to_encrypt = "MsgBody..../MsgBody"; // xml 

$msgbody = simplexml_load_string($data_to_encrypt);
$result = $msgbody->xpath('//MsgBody');

openssl_private_encrypt(json_encode($result), $encrypted, $private_key, OPENSSL_PKCS1_PADDING);

$signature = $encrypted;
$verify = openssl_verify($encrypt, $signature ,$publick_key, OPENSSL_ALGO_SHA256);

$verify=0的结果,为什么是bad verify?

最佳答案

openssl_private_encrypt 的对应物是openssl_public_decrypt .这两种方法都允许使用 PKCS#1 v1.5 填充 ( RSASSA-PKCS1-v1_5 ) 进行低级签名/验证,其中数据隐式未进行哈希处理,所用摘要的 ID 也未添加到哈希值之前。即,为了使结果符合 PKCS#1 v1.5 填充,两者都必须显式完成。

相比之下,在 openssl_sign隐式考虑了散列和添加摘要 ID和 openssl_verify在 RSA 和 PKCS#1 v1.5 填充的上下文中,因此签名自动符合 PKCS#1 v1.5 填充。

通常,后者是更有效的签名/验证方式。但是,openssl_private_encrypt 也有一个用途,即当不是要签名的数据本身,而是只有已经散列的数据 可供签名时。

代码中的问题是 openssl_private_encryptopenssl_verify 的组合。当然,您可以将两者结合起来,但是您必须实现散列并为 openssl_private_encrypt 添加摘要 ID,这在代码中是缺失的。或者(如评论中所述)openssl_sign 可以应用,这在这里效率更高。
另一个不一致是必须对相同的数据进行签名和验证。代码中,json_encode($result)用于签名,$encrypt(json_encode($result)派生)用于验证.

以下 PHP 代码演示了 openssl_private_encryptopenssl_verify 的组合(参见测试 1):

function getRSAKeys(){
$keyPairResource = openssl_pkey_new(array("private_key_bits" => 2048, "private_key_type" => OPENSSL_KEYTYPE_RSA));
openssl_pkey_export($keyPairResource, $privateKey);
return [$privateKey, openssl_pkey_get_details($keyPairResource)["key"]];
}

// Create test key
$newKeyPair = getRSAKeys();
$privateKey = $newKeyPair[0];
$publicKey = $newKeyPair[1];

// Test 1: openssl_private_encrypt and openssl_verify
$dataToSign = 'Test 1: The data to sign'; // Could correspond to e.g. json_encode($result) in the code
$dataToSignHashed = hash('sha256', $dataToSign, true);
$dataToSignHashedWithID = hex2bin("3031300d060960864801650304020105000420") . $dataToSignHashed; // ID from https://www.rfc-editor.org/rfc/rfc8017#page-47
openssl_private_encrypt($dataToSignHashedWithID, $signature, $privateKey, OPENSSL_PKCS1_PADDING);
$verified = openssl_verify($dataToSign, $signature, $publicKey, OPENSSL_ALGO_SHA256);
print($verified) . PHP_EOL;

// Test 2: openssl_sign and openssl_verify
$dataToSign = 'Test 2: The data to sign'; // Could correspond to e.g. json_encode($result) in the code
openssl_sign($dataToSign, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$verified = openssl_verify($dataToSign, $signature, $publicKey, OPENSSL_ALGO_SHA256);
print($verified) . PHP_EOL;

// Test 3: openssl_private_encrypt and openssl_public_decrypt (without hashing and adding the digest id)
$dataToSign = 'Test 3: The data to sign'; // Could correspond to e.g. json_encode($result) in the code
openssl_private_encrypt($dataToSign, $signature, $privateKey, OPENSSL_PKCS1_PADDING);
openssl_public_decrypt($signature, $decrypted, $publicKey, OPENSSL_PKCS1_PADDING);
print($dataToSign === $decrypted) . PHP_EOL;

编辑:最后一个示例纯粹是技术性的,应该证明使用openssl_private_encrypt 进行加密而不进行散列和添加 ID 可以使用 openssl_public_decrypt 解密。实际上,签名时会应用散列,请参阅 kelalaka 的评论,例如here .这两种方法都不是为了直接签署/验证消息,而是,如上所述,允许用户签署/验证已经散列的消息。

关于php - 使用 PHP 进行签名的 RSA 和 SHA-256 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65451594/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com