本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《Go DSA 和 Java DSA 的区别》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~
问题内容
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");
返回错误
正确答案
在 Java 中,(签名)算法名称 DSA 是 SHA1withDSA 的别名,即原始 FIPS186-0 算法。这与 Go 显然实现的非标准“原始”原语不同。 NONEwithDSA 确实是您想要的正确的 Java 名称,但是“标准”(SUN) 提供程序中的实现有点混乱,需要恰好 20 字节的数据,而不是更多或更少,因为这是 SHA1 的大小hash 是 FIPS186-3 之前 DSA 的唯一标准哈希值。
如果您(拥有或可以获得并)使用 BouncyCastle 提供程序,则它没有此限制,并且应该适用于更改为 NONEwithDSA 的代码(并且代码或安全配置已修改为当然,BC 被选为提供者)。
如果你不使用 Bouncy,我认为你必须自己编写算法;我认为没有任何方法可以让 SUN 实现执行您想要的操作。
尽管最好是按照标准而不是原始数据的方式对大小合适的哈希进行签名,然后您就可以使用指定和设计的 Java 提供程序。
终于介绍完啦!小伙伴们,这篇关于《Go DSA 和 Java DSA 的区别》的介绍应该让你收获多多了吧!