请教一个 DSA 签名 在 Java 和 PHP 平台互通的问题

2020-04-03 10:57:28 +08:00
 object123

PHP 生成签名方法为:openssl_sign($paramStr, $sign, $_privateKey,OPENSSL_ALGO_DSS1);

JAVA 验签的部分代码是:

Signature signet = Signature.getInstance("SHA1withDSA"); byte[] publicKeyCode = pubkey.getBytes(); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyCode); KeyFactory keyFactory = KeyFactory.getInstance("DSA"); PublicKey publicKey = keyFactory.generatePublic(keySpec); signet.initVerify(publicKey); signet.update(content.getBytes("utf-8")); // 公匙验证结果 boolean result = signet.verify(sign);

但是 JAVA 那边验签不通过。 PHP 的生成签名方法 openssl_sign 最后一个$signature_alg 变量试过 OPENSSL_ALGO_DSS1 和 DSA,都不行。

请问有人我遇到这种情况吗

1227 次点击
所在节点    程序员
4 条回复
object123
2020-04-03 11:00:20 +08:00
JAVA 那边提供的秘钥是 base64 的。

PHP 签名代码:
$param = array($data,$randomStr,$timestamp);
sort($param);

$paramStr = implode('',$param);

$privateKey = chunk_split($this->_privateKey, 64, "\n");

$privateKey = "-----BEGIN PRIVATE KEY-----\n" . $privateKey . "-----END PRIVATE KEY-----\n";

$_privateKey = openssl_get_privatekey($privateKey);

if (!openssl_sign($paramStr, $sign, $_privateKey,OPENSSL_ALGO_DSS1)){
return false;
} else {
return base64_encode($sign);
}
Jrue0011
2020-04-03 14:56:55 +08:00
Java 那里 pubkey 不会还是 base64 编码吧?
object123
2020-04-08 09:37:10 +08:00
@Jrue0011 是的
Jrue0011
2020-04-08 10:06:59 +08:00
@object123

真是吗? pubkey 既然是对公钥 byte 数组进行 base64 编码后的字符串,没做解码直接 pubkey.getBytes()拿到的肯定不是原来的 byte 数组,验证自然不通过。解码的话,JDK1.8 应该可以用 java.util.Base64.getDecoder().decode(pubkey),JDK1.8 以前貌似网上不建议用 sun 的实现,可以用 apache commons-codec 的 Base64.decodeBase64(pubkey)。

另外看 PHP 代码,签名后传给 Java 的值也是一个 base64 编码的字符串?是的话,在 Java 验证这里,boolean result = signet.verify(sign),这个 sign 如果也只是用传过来的字符串直接 getBytes()的话那也是不行的,也要 base64 解码获得原本的 byte 数组。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/658925

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX