Подпись DSA определяется как пара целых чисел (называемых r и s соответственно). Стандарт DSA не предписывает конкретное кодирование такой подписи в последовательность байтов. Таким образом, каждый протокол, использующий подписи DSA, должен определять свою собственную кодировку.
Существует два обычно используемых кодировки подписи DSA; одним из них является прямая конкатенация беззнаковых кодирований с прямым порядком байтов значений r и s , оба из которых нормализуются к длине (в байтах) q параметр в открытом ключе («размер подгруппы», обычно 160-битное простое число, что дает 40-байтовую подпись). Документация к M2Crypto.DSA довольно краткая, но я предполагаю, что она возвращает r и s отдельно, но уже в этом формате.
Java использует другую кодировку, основанную на ASN.1. Эта кодировка используется в X.509 и во всем, что на ней основано (включая подписи в SSL / TLS). ASN.1 является общим стандартом для представления и сериализации структурированных данных. В этом случае подпись должна быть сериализацией ASN.1 SEQUENCE
, содержащей два значения INTEGER
( r и s , в этом порядке). В соответствии с правилами кодирования ASN.1 и DER подпись должна иметь следующий формат:
0x30 A 0x02 B R 0x02 C S
где:
R - это кодировка с прямым порядком байтов со знаком r минимальной длины: это означает, что первый байт должен иметь значение между 0 и 127, и он должен иметь значение 0 только в том случае, если второй байт имеет значение между 128 и 255. Другими словами, кодируйте r как последовательность байтов с условным порядком байтов (самый старший байт во-первых), убедившись, что у вас как можно меньше начальных нулевых битов, при условии, что вы сохраняете хотя бы один (это то, что означает «подписанное» кодирование: поскольку r положительно, его старший значащий бит должен быть 0). Поскольку r является целым числом от 0 до q-1 , длина R будет не более чем на один байт больше длины q , но оно может быть меньше.
S - кодировка со знаком с прямым порядком байтов s (такая же обработка, как для r ; примечание: R и S может иметь различную длину).
B - это один байт, содержащий длину R (в байтах).
C - это один байт, содержащий длину S (в байтах).
A - это один байт, содержащий B + C + 2 (т. Е. Длину в байтах того, что следует за байтом A ) .
Написание специализированных функций кодирования и декодирования для подписей DSA на основе ASN.1 немного утомительно, но не сложно; просто позаботьтесь о создании последовательностей R и S нужного размера. В качестве альтернативы вы можете использовать существующую библиотеку кодирования / декодирования ASN.1, которая излишня, но может быть проще, в зависимости от вашей ситуации.