Проблема DSA - создайте открытый / закрытый ключ DSA в .NET, используйте открытый ключ в Java (android) - PullRequest
1 голос
/ 16 декабря 2009

Вот настройки:

Я создаю пару открытого / закрытого ключа с помощью .NET, я хочу подписать строку. Я беру случайную строку, получаю из нее байт [], подписываю ее и беру подпись в приложении java. Я хочу проверить это в Java ((!) Я говорю о Java в Android).

Процесс переноса открытого ключа в среду Java: когда я создаю открытый ключ, я беру массивы байтов для открытого ключа (P, Q, G, Y) и создать PublicKey в Java с этими значениями. P, Q, G, Y в .NET являются байтами [], я конвертирую их в sbyte [] и использую эти sbyte [] в Java, создавая большие целые числа:

byte [] byteP = новый байт [] {-34, ...... -117};

...

BigInteger p = новый BigInteger (1, byteP);

...

новый DSAPublicKeySpec (y, p, q, g);

Чтобы проверить процесс, я беру сигнатуру байта [] из C #, преобразую его в sbyte [] и затем использую его в Java.

Проблема в том, что я не могу проверить строку подписи позже. Я получил

java.security.SignatureException: байты подписи имеют неправильную кодировку

Любые идеи приветствуются! (Например, лучший, совершенно другой способ сделать все это;))

Ответы [ 2 ]

2 голосов
/ 16 декабря 2009

Подпись DSA на самом деле представляет собой два числа, и нет никакого реального стандарта для того, чтобы отформатировать ее как байтовый массив.

Java выбирает кодировать его как DER-кодирование последовательности ASN.1, содержащей два целых числа ASN.1.

.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;

}

0 голосов
/ 16 декабря 2009

Не уверен, что я вас здесь отбросил, но (Sun!) BigInteger использует 1, который вы передаете в конструкторе, в качестве знака числа - так что это может повлиять на вычисление подписи. .. У меня были проблемы с этим в прошлом при использовании RSA ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...