【问题标题】:Verifying JAVA signature in php在php中验证JAVA签名
【发布时间】:2019-11-01 14:49:52
【问题描述】:

现在我被困在这一天了。我环顾四周,但无法解决问题。

JAVA 代码:

public String generateDigitalSignedToken(String requestData) throws Exception 
{
    Signature signature = Signature.getInstance("SHA1withRSA");
    PrivateKey privateKey = this.readPrivateKeyFromFile(busPrivateFile);
    signature.initSign(privateKey, new SecureRandom());
    byte[] message = requestData.getBytes();
    signature.update(message);
    byte[] sigBytes = signature.sign();
    return Base64.getEncoder().encodeToString(sigBytes);
}

PHP 代码:

$rsa = new RSA();
$rsa->loadKey($publicKey);
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
$rsa->setHash("sha1");
$rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
$receivedHash = $rsa->decrypt($decodedHash);

待办事项

  1. 解密令牌以获取接收到的哈希。
  2. 第二个任务是重新创建哈希并将其与接收到的哈希进行比较。

重新创建哈希的代码

$temp = new RSA();
$temp->setHash('sha1');
$temp->setSignatureMode(RSA::SIGNATURE_PKCS1);
$generatedHash1 = $temp->hash->_sha1($decryptedBody);

//Or simply

$generatedHash2 = sha1($data, true);

以下是值:

"receivedHash" => b"0!0\t\x06\x05+\x0E\x03\x02\x1A\x05\x00\x04\x14öRM▀ÿuï®▀Q÷Å\x06M¬Õ \x16{M^"

"generatedHash1" / "generatedHash2" => b"öRM▀ÿuï®▀Q÷Å\x06M¬Õ\x16{M^"

可以看出,即使在两端使用相同的字符串时,哈希也会部分匹配。

谁能帮我解决这个问题? 我将不胜感激。

编辑:

使用的 PHP 库:https://github.com/phpseclib/phpseclib

【问题讨论】:

  • 我们不知道您使用的是什么 PHP RSA 库。
  • 您好@JamesReinstateMonicaPolk,已更新问题,请检查。
  • @JamesReinstateMonicaPolk - 该库的文档位于 phpseclib.sourceforge.net
  • @JamesReinstateMonicaPolk - 根据 packagist 的说法,最常用的是 2.0。你选择了正确的版本 - 我没有大声笑。今晚晚些时候我会尝试提交错误报告!
  • @JamesReinstateMonicaPolk - 现在看起来效果更好了!可能需要刷新缓存!

标签: java php rsa sha1 phpseclib


【解决方案1】:

一个问题是“receivedHash”不是只是一个哈希。它是包装在 ASN.1 结构中的散列。如果你对它执行 openssl asn1parse ,你会得到以下信息:

    0:d=0  hl=2 l=  33 cons: SEQUENCE
    2:d=1  hl=2 l=   9 cons:  SEQUENCE
    4:d=2  hl=2 l=   5 prim:   OBJECT            :sha1
   11:d=2  hl=2 l=   0 prim:   NULL
   13:d=1  hl=2 l=  20 prim:  OCTET STRING

您可以通过这样做获得实际的 sha1 哈希(在 PHP 中):

substr(base64_decode('MCEwCQYFKw4DAhoFAAQUlFJN35h1i6nfUfaPBk2q5RZ7TV4='), 13 + 2, 20)

还有其他可以说是更好的方法来实际解析 ASN.1 并“映射”它,但这些方法更冗长,而且无论如何超出了这个“答案”的范围。

另一个问题是receivedHash 不是实际签名,也不是有效的密文。您的 RSA 密钥是 2048 位。那是 256 个字节。签名/密文也应该是那个长度。当然,我想如果你修剪前导或尾随 NULL 空间,它可能会更小,但即便如此,签名/密文也不应该像你的那样具有“结构”。也许在模幂之前它会但不是之后。所以我认为很多问题可能出在您的 Java 代码中。也许当我回到家时,我可以在本地运行您的 Java 代码,看看是否得到与您的receivedHash 类似的输出。如果是这样,我可以制作自己的 stackoverflow 帖子,询问这是怎么回事。但暂时我会看看你的 Java 代码。

【讨论】:

  • 感谢您的详细解释,将等待您对Java代码的发现。
  • @vivektakrani - 在您的 Java 代码中,您有 PrivateKey privateKey = this.readPrivateKeyFromFile(busPrivateFile);。这是您定义的功能吗?您能否以该方法所期望的格式生成一个新的私钥?也许我可以自己生成正确格式的密钥,但如果你能这样做会更方便。谢谢!
  • 嘿@neubert,抱歉回复晚了,我已经解决了这个问题。在我的 PHP 代码中,在验证哈希之前无需解密正文。我只需要对其进行解码,生成哈希并进行验证。
猜你喜欢
  • 1970-01-01
  • 2016-12-27
  • 2016-12-27
  • 2013-09-12
  • 2017-11-22
  • 1970-01-01
  • 2018-07-09
  • 1970-01-01
  • 2012-09-09
相关资源
最近更新 更多