DSA问题 - 创建DSA公共/与.NET的私钥,使用与Java(机器人)的公开密钥 [英] DSA problem - create DSA public/private key with .NET, use the public key with Java(android)
问题描述
下面是设置:
创建公共/私有密钥对。NET,我想签一个字符串。 我拿一个随机字符串,得到一个byte []从它,签字,并采取签名在java应用程序。我想验证它在Java中((!),我说的是关于Android的Java)。
I create public/private key pair with .NET, I want to sign a string. I take a random string, get a byte[] from it, sign it, and take the signature in the java app. I want to verify it in java ( (!)I'm talking about Android's java).
的过程中采取的公钥Java环境:当我创建了公钥,我把字节数组的公共密钥(P,Q,G,Y)和 在Java中创建公钥与价值观。 P,Q,G,Y在.NET中的字节[],我将它们转换到sbyte []和使用这些为sbyte在Java中[],创建大整数:
The process to take the public key to Java environment: When I create the public key, I take the byte arrays for the public key (P, Q, G, Y) and create PublicKey in Java with those values. P, Q, G, Y in .NET are byte[], I convert them to sbyte[] and use these sbyte[] in Java, creating big integers:
字节[] byteP =新的字节[] {-34,...... -117};
byte[] byteP = new byte[] { -34, ...... -117 };
...
BigInteger的P =新的BigInteger(1,byteP);
BigInteger p = new BigInteger(1,byteP);
...
新到DSAPublicKeySpec(Y,P,Q,G);
new DSAPublicKeySpec(y, p, q, g);
要测试的过程中,我拿签名的byte []从C#,将其转换到sbyte [],然后用它在Java中。
To test the process, I take the signature byte[] from C#, convert it to sbyte[] and then use it in Java.
现在的问题是,我以后不能验证签名的字符串。我得到了
The problem is, I cannot verify the signature string later. I got
java.security.SignatureException:签名字节有无效的编码
java.security.SignatureException: signature bytes have invalid encoding
pciated任何想法AP $ P $! (喜欢一个更好的,完全不同的方式来做这件事;))
Any ideas appreciated! (Like, a better, entirely different way to do the whole thing ;) )
推荐答案
一个DSA签名实际上是两个数字并没有对如何格式化这是一个字节组没有真正的标准。
A DSA signature is actually two numbers and there is no real standard for how to format this as a bytearray.
Java的选择EN code它包含两个ASN.1-整数一个ASN.1序列的DER编码。
Java chooses to encode it as the DER-encoding of an ASN.1-sequence containing two ASN.1-integers.
.NET选择prePEND零的两个号码,将他们正好是20个字节,将它们连接起来。
.NET chooses to prepend zeroes to the two numbers so they are exactly 20 bytes long and concatenate them.
从.NET转换成Java格式做这样的事情(未经测试,但应该是基本正确的):
To convert from .NET to Java format do something like this (untested, but should be mostly correct):
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;
}
这篇关于DSA问题 - 创建DSA公共/与.NET的私钥,使用与Java(机器人)的公开密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!