Преобразовать подпись из формата P1363 в формат ASN.1 / DER с помощью Crypto ++? - PullRequest
2 голосов
/ 25 сентября 2019

У меня есть подпись, созданная таким образом:

size_t siglenth = _signer.MaxSignatureLength();
QByteArray signature(siglenth, 0x00);
signature.reserve(siglenth);
siglenth = _signer.SignMessage(_prng,
        (const CryptoPP::byte*) (message.constData()),
        message.length(), (CryptoPP::byte*) signature.data());

Моя подпись имеют размер 64 и содержит:

ECCD530E5F232B7C566CA5322F990B3D55ED91156DF3845C4B9105BFE57606DDD68F332A0A5BF7CAB673E4970D10109B72F114571E7474F93ED7C89CD1B89AD4

Счто я прочитал в dsa.h файле, эта подпись в настоящее время имеет формат DSA_P1363.Мне нужно преобразовать его в DSA_DER формат.

Для выполнения этого действия я стараюсь:

QByteArray derSign(70, 0xFF);
size_t converted_size = CryptoPP::DSAConvertSignatureFormat(
        (CryptoPP::byte*) (derSign.data()), sizeof(derSign.data()), CryptoPP::DSA_DER,
        (CryptoPP::byte*) (signature.data()), sizeof(signature.data()), CryptoPP::DSA_P1363);

Результат этого преобразования показан ниже.Вроде бы только первая часть подписи.Он имеет размер 8 и содержит:

300D020500ECCD53

Что не так?

Спасибо.

1 Ответ

2 голосов
/ 26 сентября 2019

Вывод этого преобразования любопытен, кажется, что это только первая часть подписи.Он имеет размер 8 и содержит:

300D020500ECCD53

Что не так?

Вместо:

size_t converted_size = DSAConvertSignatureFormat(
    (byte*) (derSign.data()), sizeof(derSign.data()), DSA_DER,
    (byte*) (signature.data()), sizeof(signature.data()), DSA_P1363);

Выследует использовать что-то вроде:

size_t converted_size = DSAConvertSignatureFormat(
    (byte*) (derSign.data()), derSign.size(), DSA_DER,
    (const byte*) (signature.data()), signature.size(), DSA_P1363);

sizeof(derSign.data()) дает sizeof a size_t, который отличается от размера строковых данных.

Кроме того, поскольку derSignзаписывается, вам нужен неконстантный указатель.Способ получить это почти во всех версиях C ++ - использовать адрес первого элемента:

size_t converted_size = DSAConvertSignatureFormat(
    (byte*) (&derSign[0]), derSign.size(), DSA_DER,
    (const byte*) (signature.data()), signature.size(), DSA_P1363);

Почти наконец, это то, что вы имеете в P1363, где r и s являютсяконкатенация, каждая из которых основана на размере элемента поля и порядке подгрупп:

[ r ] [ s ]

Это то, что вам нужно в ASN.1 / DER.Есть 3 объекта ASN.1 - одна последовательность и два целых числа.Каждому объекту нужен один октет для типа ASN.1 и максимум два октета для длины.r и s - размер элемента поля.Каждому целому числу ASN.1 может понадобиться начальный 0, поэтому добавьте два дополнительных байта для r и s.

SEQUENCE = {
    INTEGER r;
    INTEGER s;
}

Итак, для буфера ASN.1 / DER вам нужно 3+3 + 3 + COUNTOF (r) + 1 + COUNTOF (s) + 1.

Наконец, фрагмент может выглядеть следующим образом:

using namespace CryptoPP;
// ... Other gyrations

std::string derSign, signature;
// ...Calculate signature

// Make room for the ASN.1/DER encoding
derSign.resize(3+3+3+2+signature.size())

size_t converted_size = DSAConvertSignatureFormat(
    (byte*) (&derSign[0]), derSign.size(), DSA_DER,
    (const byte*) (signature.data()), signature.size(), DSA_P1363);

ASSERT(converted_size <= derSign.size());
derSign.resize(converted_size);

Crypto ++ теперь имеет страницу навики на DSAConvertSignatureFormat.Есть пример использования DSAConvertSignatureFormat в ECDSA |OpenSSL и Java , но преобразование идет другим путем.

(Ваш вопрос и отсутствие документации фактически вызвали ошибку, и мы сократили разрыв).


Я только что заметил это ...

size_t siglenth = _signer.MaxSignatureLength();
QByteArray signature(siglenth, 0x00);
signature.reserve(siglenth);
siglenth = _signer.SignMessage(_prng, (const CryptoPP::byte*) (message.constData()),
                               message.length(), (CryptoPP::byte*) signature.data());

Вместо этого используйте это:

QByteArray signature;
size_t siglenth = _signer.MaxSignatureLength();

signature.resize(siglenth);
siglenth = _signer.SignMessage(_prng,
             (const byte*) (message.constData()), message.length(),
             (byte*) (&signature[0]));
signature.resize(siglenth);
...