使用phpseclib的Crypt_RSA加密银行验证码

发布于 2024-11-08 14:03:51 字数 1743 浏览 0 评论 0原文

我需要向银行发送一条查询,其中包含指定字符串格式的验证码 $vk_mac。该代码必须是使用我的公钥加密的 SHA1 哈希和 RSA,并以 Base64 格式呈现。不幸的是,到目前为止,我还没有成功——银行给了我“错误的签名”以及我得到的所有信息。

我所拥有的是这样的:

$rsa = new Crypt_RSA();
$rsa->loadKey(file_get_contents("private_key.pem"));
$rsa->loadKey($rsa->getPublicKey());
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$encrypted = $rsa->encrypt(sha1($vk_mac));
$vk_mac = base64_encode($encrypted);

private_key.pem 这里是我的纯文本私钥。我尝试将加密模式设置为 CRYPT_RSA_ENCRYPTION_OAEP 但没有成功。我 99.9% 确信起始 $vk_mac 字符串的格式正确并且包含所有必需的详细信息。

有人知道我做错了什么吗?谢谢。


编辑:

我已将代码更改为以下内容(其中 vk_mac 是需要签名的起始格式化字符串,private_key.pem 是我解码后的私钥):

$rsa = new Crypt_RSA();
$rsa->loadKey(file_get_contents("private_key.pem"));
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$hashed = $rsa->hash->hash($vk_mac);
$encrypted = $rsa->sign($hashed);
$signature = base64_encode($encrypted);

我可以告诉生成的签名是正确的,因为当我这样做时:

$rsa->loadKey($rsa->getPublicKey());
$verified = $rsa->verify($hashed, base64_decode($signature));

$verified 返回 TRUE。

然而,银行回应“签名不正确”。还有更多想法吗?

编辑:

规范

VK_MAC控制码计算

VK_MAC,用于电子签名,在请求中使用,用于检查和确认所使用的算法版本,在参数VK_VERSION中指示。这次使用的是008版本。 VK_MAC在BASE64编码中作为请求参数呈现。

版本 008

MAC008函数的值是使用公钥算法RSA计算出来的。空字段的值也被考虑在内 - “000”。

MAC008(x1,x2,…,xn) := RSA(SHA-1(p(x1)|| x1|| p(x2 )|| x2 || … ||p(xn)||xn) ,d,n)

地点: ||是一个字符串相加的操作 x1, x2, …, xn 是查询参数 p 是参数长度的函数。长度是一个三位数字符串形式的数字 d 是 RSA 秘密指数 n 是 RSA 模数 签名按照PKCS1标准(RFC 2437)计算。

I am required to send a query to the bank which contains a verification code $vk_mac in a specified string format. The code has to be a SHA1 hash and RSA encrypted with my public key and presented in base64 format. Unfortunately, so far, I have been unsuccessful - the bank gives me "Wrong signature" and that all the info I'm getting.

What I have is this:

$rsa = new Crypt_RSA();
$rsa->loadKey(file_get_contents("private_key.pem"));
$rsa->loadKey($rsa->getPublicKey());
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$encrypted = $rsa->encrypt(sha1($vk_mac));
$vk_mac = base64_encode($encrypted);

private_key.pem here is my private key in plain text. I tried setting the encryption mode to CRYPT_RSA_ENCRYPTION_OAEP without luck. I am 99.9% sure, that the starting $vk_mac string is formatted correctly and contains all the required details.

Does anybody have any idea what can I be doing wrong? Thank you.


Edit:

I've changed the code to this (where vk_mac is the starting formatted string that needs to be signed and private_key.pem is my the decoded private key):

$rsa = new Crypt_RSA();
$rsa->loadKey(file_get_contents("private_key.pem"));
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$hashed = $rsa->hash->hash($vk_mac);
$encrypted = $rsa->sign($hashed);
$signature = base64_encode($encrypted);

I can tell the generated signature is correct, since when I do this:

$rsa->loadKey($rsa->getPublicKey());
$verified = $rsa->verify($hashed, base64_decode($signature));

$verified returns TRUE.

The bank though, responds "Incorrect signature". Any more ideas?

Edit:

Specification

VK_MAC control code calculation

VK_MAC, for electronic signature, using in the request, for checking and confirming used version of the algorithm, indicated in the parameter VK_VERSION. In this time version 008 is used. VK_MAC is presented as a request parameter in BASE64 coding.

Version 008

The value of the MAC008 function is calculated using the public key algorithm RSA. Values of empty fields are taken into account as well – “000”.

MAC008(x1,x2,…,xn) := RSA(SHA-1(p(x1)|| x1|| p(x2 )|| x2 || … ||p(xn)||xn),d,n)

Where:
|| is an operation of adding the string
x1, x2, …, xn are the query parameters
p is a function of the parameter length. The length is a number in the form of a three-digit string
d is the RSA secret exponent
n is the RSA modulus
The signature is calculated in accordance with the PKCS1 standard (RFC 2437).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深者入戏 2024-11-15 14:03:51

如果你尝试 $rsa->sign() 会怎么样? PKCS#1 不会通过简单地加密哈希来进行签名,如果您的银行使用可互操作的 RSA 解决方案,他们可能也不会这样做。

What if you try $rsa->sign()? PKCS#1 doesn't do signing by simply encrypting the hash and if your bank is using an interoperable RSA solution they're probably not doing that either.

紫瑟鸿黎 2024-11-15 14:03:51

代码几乎是正确的 - 不过我不需要再次散列它(感谢@Accipitridae)。

解决方案是商家的 ID 必须为大写,而不是提供的小写。规范中没有任何地方说它也必须是大写的。好的。

The code was almost correct - I did not need to hash it again though (thanks @Accipitridae).

The solution was that the merchant's ID had to be uppercase, and not lowercase as provided. It does not say anywhere in the spec that it has to be uppercase as well. Nice.

懒猫 2024-11-15 14:03:51

如上所述,您可以使用 openssl 轻松完成此操作。下面是我将如何做到这一点。

$hashed = sha1($vk_mac);
openssl_public_encrypt($vk_mac, $encrypted, ($pubkey));
$vk_mac = base6$_encode($encrypted);

阅读有关 openssl_public_crypt 的文档了解更多信息。

As mentioned above you can do this easily with openssl. Below is how I would do so.

$hashed = sha1($vk_mac);
openssl_public_encrypt($vk_mac, $encrypted, ($pubkey));
$vk_mac = base6$_encode($encrypted);

Read the documentation on openssl_public_encrypt for more.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文