作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
你好,我有一个非常奇怪的问题,也许你们中的一些人可以帮助我。我正在 Java 中实现 DSA 签名算法,但除了从 java.security 生成 SHA-1 哈希函数外,我不能使用任何现有库来执行此操作。我的代码正在生成每个所需的数字,但验证签名时出现问题。这是我的代码:
public class Key {
int primeCenterie = 20;
BigInteger q;
BigInteger p;
BigInteger g;
BigInteger y;
BigInteger x;
BigInteger k;
Random rand = new Random();
Key() { }
public void generateKey() {
q = new BigInteger(160, primeCenterie, rand);
p = generateP(q, 512);
g = generateG(p, q);
do {
x = new BigInteger(q.bitCount(), rand);
} while (x.compareTo(BigInteger.ZERO) == -1 || x.compareTo(g) == 1);
y = g.modPow(x, p);
System.out.println("p:" + p);
System.out.println("q:" + q);
System.out.println("g:" + g);
System.out.println("private key (x):" + x);
System.out.println("public key (y):" + y);
}
private BigInteger generateP(BigInteger q, int l) {
if (l % 64 != 0) {
throw new IllegalArgumentException(" zle l ");
}
BigInteger pTemp;
BigInteger pTemp2;
do {
pTemp = new BigInteger(l, primeCenterie, rand);
pTemp2 = pTemp.subtract(BigInteger.ONE);
pTemp = pTemp.subtract(pTemp2.remainder(q));
} while (!pTemp.isProbablePrime(primeCenterie));
return pTemp;
}
private BigInteger generateG(BigInteger p, BigInteger q) {
BigInteger aux = p.subtract(BigInteger.ONE);
BigInteger pow = aux.divide(q);
BigInteger g;
do {
g = new BigInteger(aux.bitLength(), rand);
} while (g.compareTo(aux) == -1 && g.compareTo(BigInteger.ZERO) == 1);
return g.modPow(pow, aux);
}
public BigInteger generateR() {
BigInteger r = g.modPow(x, p).mod(q);
System.out.println("r:" + r);
return r;
}
public BigInteger generateS(BigInteger r, byte[] data) {
MessageDigest md;
BigInteger s = BigInteger.ONE;
try {
md = MessageDigest.getInstance("SHA-1");
md.update(data);
BigInteger hash = new BigInteger(md.digest());
System.out.println("Hash:" + hash);
s = (x.modInverse(q).multiply(hash.add(x.multiply(r)))).mod(q);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(DSA.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("s:" + s);
return s;
}
boolean verify(byte[] data, BigInteger r, BigInteger s) {
if (r.compareTo(BigInteger.ZERO) <= 0 || r.compareTo(q) >= 0) {
return false;
}
if (s.compareTo(BigInteger.ZERO) <= 0 || s.compareTo(q) >= 0) {
return false;
}
MessageDigest md;
BigInteger v = BigInteger.ZERO;
try {
md = MessageDigest.getInstance("SHA-1");
md.update(data);
BigInteger hash = new BigInteger(md.digest());
BigInteger w = s.modInverse(q);
BigInteger u1 = hash.multiply(w).mod(q);
BigInteger u2 = r.multiply(w).mod(q);
v = ((g.modPow(u1, p).multiply(y.modPow(u2, p))).mod(p)).mod(q);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(DSA.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("v:" + v);
System.out.println("r:" + r);
return v.compareTo(r) == 0;
}
}
我正在使用 generateR() 和 generateS(BigInteger r, byte[] data) 函数生成 R 和 S。数据是我的消息文本转换为字节。当我发送完全相同的字节数组并生成 S 和 R 来验证函数时,它返回 false。 R 和 V 不相同,但它们应该相同。我做错了什么:)??我以这个 c# 代码为例:
http://www.koders.com/csharp/fidE9EF01A91C00DF066F023DD2EECA23856B922537.aspx?s=mdef%3Afile和维基百科的描述
http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
生成K的函数:
public BigInteger generateK(BigInteger q){
BigInteger tempK;
do {
tempK = new BigInteger(q.bitLength(), rand);
} while (tempK.compareTo(q) != -1 && tempK.compareTo(BigInteger.ZERO) != 1);
return tempK;
}
最佳答案
终于!!这是我的代码:
public class Key {
int primeCenterie = 20;
BigInteger q;
BigInteger p;
BigInteger g;
BigInteger y;
BigInteger x;
BigInteger k;
Random rand = new Random();
Key() {}
public void generateKey() {
q = new BigInteger(160, primeCenterie, rand);
p = generateP(q, 512);
g = generateG(p, q);
do {
x = new BigInteger(q.bitCount(), rand);
} while (x.compareTo(BigInteger.ZERO) != 1 && x.compareTo(q) != -1);
y = g.modPow(x, p);
}
private BigInteger generateP(BigInteger q, int l) {
if (l % 64 != 0) {
throw new IllegalArgumentException("L value is wrong");
}
BigInteger pTemp;
BigInteger pTemp2;
do {
pTemp = new BigInteger(l, primeCenterie, rand);
pTemp2 = pTemp.subtract(BigInteger.ONE);
pTemp = pTemp.subtract(pTemp2.remainder(q));
} while (!pTemp.isProbablePrime(primeCenterie) || pTemp.bitLength() != l);
return pTemp;
}
private BigInteger generateG(BigInteger p, BigInteger q) {
BigInteger aux = p.subtract(BigInteger.ONE);
BigInteger pow = aux.divide(q);
BigInteger gTemp;
do {
gTemp = new BigInteger(aux.bitLength(), rand);
} while (gTemp.compareTo(aux) != -1 && gTemp.compareTo(BigInteger.ONE) != 1);
return gTemp.modPow(pow, p);
}
public BigInteger generateK(BigInteger q) {
BigInteger tempK;
do {
tempK = new BigInteger(q.bitLength(), rand);
} while (tempK.compareTo(q) != -1 && tempK.compareTo(BigInteger.ZERO) != 1);
return tempK;
}
public BigInteger generateR() {
k = generateK(q);
BigInteger r = g.modPow(k, p).mod(q);
return r;
}
public BigInteger generateS(BigInteger r, byte[] data) {
MessageDigest md;
BigInteger s = BigInteger.ONE;
try {
md = MessageDigest.getInstance("SHA-1");
md.update(data);
BigInteger hash = new BigInteger(md.digest());
s = (k.modInverse(q).multiply(hash.add(x.multiply(r)))).mod(q);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(DSA.class.getName()).log(Level.SEVERE, null, ex);
}
return s;
}
boolean verify(byte[] data, BigInteger r, BigInteger s) {
if (r.compareTo(BigInteger.ZERO) <= 0 || r.compareTo(q) >= 0) {
return false;
}
if (s.compareTo(BigInteger.ZERO) <= 0 || s.compareTo(q) >= 0) {
return false;
}
MessageDigest md;
BigInteger v = BigInteger.ZERO;
try {
md = MessageDigest.getInstance("SHA-1");
md.update(data);
BigInteger hash = new BigInteger(md.digest());
BigInteger w = s.modInverse(q);
BigInteger u1 = hash.multiply(w).mod(q);
BigInteger u2 = r.multiply(w).mod(q);
v = ((g.modPow(u1, p).multiply(y.modPow(u2, p))).mod(p)).mod(q);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(DSA.class.getName()).log(Level.SEVERE, null, ex);
}
return v.compareTo(r) == 0;
}}
小错误但还是错误;)
@crazyscot 感谢您的帮助:D
关于java - 在没有密码学库的情况下在 Java 中实现 DSA 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6005178/
我有 Java 算法/计算和单元测试。单元测试期望结果具有一定的精度/增量。现在我将算法移植到 .NET 中并希望使用相同的单元测试。我使用双数据类型。 问题是 Java 对 Math 类中的某些操作
我是一名优秀的程序员,十分优秀!