【发布时间】:2021-10-30 17:12:09
【问题描述】:
- Go 使用 DSA 私钥生成签名
- Java 使用 DSA 公钥验证第一步结果
- Java 应该返回 true,但返回 false
package main
import (
"crypto/dsa"
"crypto/rand"
"encoding/asn1"
"encoding/hex"
"fmt"
"golang.org/x/crypto/ssh"
"math/big"
)
func main() {
// a dsa private key
pemData := []byte("-----BEGIN DSA PRIVATE KEY-----\n" +
"MIIBvAIBAAKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR\n" +
"+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb\n" +
"+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdg\n" +
"UI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlX\n" +
"TAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj\n" +
"rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQB\n" +
"TDv+z0kqAoGBAIb9o0KPsjAdzjK571e1Mx7ZhEyJGrcxHiN2sW8IztEbqrKKiMxp\n" +
"NlTwm234uBdtzVHE3uDWZpfHPMIRmwBjCYDFRowWWVRdhdFXZlpCyp1gMWqJ11dh\n" +
"3FI3+O43DevRSyyuLRVCNQ1J3iVgwY5ndRpZU7n6y8DPH4/4EBT7KvnVAhR4Vwun\n" +
"Fhu/+4AGaVeMEa814I3dqg==\n" +
"-----END DSA PRIVATE KEY-----")
// parse dsa
p, _ := ssh.ParseRawPrivateKey(pemData)
pp := p.(*dsa.PrivateKey)
// orign data
hashed := []byte{1}
r, s, _ := dsa.Sign(rand.Reader, pp, hashed)
type dsaSignature struct {
R, S *big.Int
}
var ss dsaSignature
ss.S = s
ss.R = r
signatureBytes, _ := asn1.Marshal(ss)
// print sign
fmt.Println(hex.EncodeToString(signatureBytes))
}
- Java 读取 DSA 公钥并初始化签名者
- Java 验证第一步签名结果
- 返回 false
@Test
public void ttt() throws InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
// DSA public key
String pubKey = "-----BEGIN PUBLIC KEY-----\n" +
"MIIBuDCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E\n" +
"AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f\n" +
"6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv\n" +
"8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtc\n" +
"NrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwky\n" +
"jMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/h\n" +
"WuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYUAAoGBAIb9o0KPsjAdzjK571e1Mx7ZhEyJ\n" +
"GrcxHiN2sW8IztEbqrKKiMxpNlTwm234uBdtzVHE3uDWZpfHPMIRmwBjCYDFRowW\n" +
"WVRdhdFXZlpCyp1gMWqJ11dh3FI3+O43DevRSyyuLRVCNQ1J3iVgwY5ndRpZU7n6\n" +
"y8DPH4/4EBT7KvnV\n" +
"-----END PUBLIC KEY-----";
String publicKeyPEM = pubKey
.replace("-----BEGIN PUBLIC KEY-----\n", "")
.replaceAll(System.lineSeparator(), "")
.replace("-----END PUBLIC KEY-----", "");
byte[] publicEncoded = Base64.decodeBase64(publicKeyPEM);
KeyFactory keyFactory1 = KeyFactory.getInstance("DSA");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicEncoded);
DSAPublicKey pubKeyy = (DSAPublicKey) keyFactory1.generatePublic(publicKeySpec);
// init signer
Signature sig1 = Signature.getInstance("DSA");
sig1.initVerify(pubKeyy);
sig1.update(new byte[]{1});
// verify first result
System.out.println(sig1.verify(HexUtil.decodeHex("first step result")));
}
- 我想在 Java 实现中使用
NONEwithDSA,但没有这样做 - 签名 sig1 = Signature.getInstance("NONEwithDSA");
java.security.SignatureException: Data for RawDSA must be exactly 20 bytes long
- 我想在 Java 实现中使用
SHA1withDSA,但没有这样做 - 签名 sig1 = Signature.getInstance("SHA1withDSA");
- 返回错误
【问题讨论】:
-
您的 golang 签名是“原始/普通”r|s 格式,但 Java 需要“DER”编码。对于 Java,您需要将签名转换为 DER 格式或直接以 DER 编码生成 golang 签名[因为我不是 DSA 签名方面的专家,我无法进一步帮助您,抱歉。]
-
@MichaelFehr:我不这么认为。虽然 OP 没有发布数据,我也不是一个旁观者(更像是一个停止者) asn1.Marshal 在我看来就像会生成 DER 的东西,在我的测试中,SUN 和 BC 提供者都为非 DER 签名抛出异常,它们不会像发布的那样返回 false。