DSA问题 – 使用.NET创建DSA公钥/私钥,使用Java公钥(android)

这是设置:

我用.NET创建公钥/私钥对,我想签一个字符串。 我取一个随机字符串,从中获取一个byte [],签名,然后在java应用程序中获取签名。 我想在java中validation它((!)我在谈论Android的java)。

将公钥带到Java环境的过程:当我创建公钥时,我将字节数组用于公钥(P,Q,G,Y),并使用这些值在Java中创建PublicKey。 .NET中的P,Q,G,Y是byte [],我将它们转换为sbyte []并在Java中使用这些sbyte [],创建大整数:

byte [] byteP = new byte [] {-34,…… -117};

BigInteger p = new BigInteger(1,byteP);

新的DSAPublicKeySpec(y,p,q,g);

为了测试这个过程,我从C#中获取签名byte [],将其转换为sbyte [],然后在Java中使用它。

问题是,我以后无法validation签名字符串。 我有

java.security.SignatureException:签名字节具有无效编码

任何想法赞赏! (比如,完成整个事情的更好,完全不同的方式;))

DSA签名实际上是两个数字,并且没有关于如何将其格式化为bytearray的真正标准。

Java选择将其编码为包含两个ASN.1整数的ASN.1序列的DER编码。

.NET选择将前缀添加到两个数字,因此它们正好是20个字节长并连接它们。

要从.NET转换为Java格式,请执行以下操作(未经测试,但应该大多正确):

public byte[] ConvertToDsaSignatureToJavaEncoding(byte[] dsa){ if(dsa.Length!=40) throw new ArgumentException("dsa", "DSA signature should always be 40 bytes long"); // Split into r and s. byte[] r = new byte[20]; Array.Copy(dsa, 0, r, 0, 20); byte[] s = new byte[20]; Array.Copy(dsa, 20, s, 0, 20); // Convert to complement-2 byte[] complementTwoR = ToComplementTwo(r); byte[] complementTwoS = ToComplementTwo(s); // Build the result byte[] res = new byte[complementTwoR.Length + complementTwoS.Length + 6]; // Sequence{ res[0] = 0x30; res[1] = (byte) (complementTwoR.Length + complementTwoS.Length + 4); // Integer (R) res[2] = 0x02; res[3] = (byte) complementTwoR.Length; Array.Copy(complementTwoR, 0, res, 4, complementTwoR.Length); // Integer (S) res[complementTwoR.Length + 4] = 0x02; res[complementTwoR.Length + 5] = (byte) complementTwoS.Length; Array.Copy(complementTwoS, 0, res, complementTwoR.Length + 6, complementTwoS.Length); return res; } public byte[] ToComplementTwo(byte[] d){ // Ensure the top-bit is zero, otherwise remove unneeded zeroes // - Find non-zero byte int i = 0; while (i < d.Length && d[i] == 0) i++; // - Do we need an extra byte int extraByte = (d[i] & 0x80) == 1 ? 1 : 0; // - Build the result byte[] res = new byte[d.Length-i+extraByte]; Array.Copy(d, i, res, extraByte, d.Length-i); return res; 

}

我不确定我是不是会把你扔在鹅追逐上,但是(太阳的!)BigInteger使用你在构造函数中传递的1作为数字的符号 – 所以它可能对生成的签名计算产生影响……我过去使用RSA已经遇到过这个问题……