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


using phpseclib's Crypt_RSA to encrypt verification code for a bank

我需要向银行发送一个查询,其中包含指定字符串格式的验证码 $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) 计算的。

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

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

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

如上所述,

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

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

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