К сожалению, эта проблема может быть родовой один (что без знака значение не может быть использовано в сценариях Bitcoin).
В этом разговоре сип объясняет, как Bitcoin принимает значения без знака, а затем передает подпись непосредственно в OpenSSL, и OpenSSL только разбирает все как беззнаковые. Поэтому вы должны прочитать строку байт и, если это уже не нули, добавьте 0x00 байты.
https://download.wpsoftware.net/bitcoin/wizards/2013/03/13-03-11.log19:00 < HM> как подписанные значения даже работы
19:00 < сипа> они хранятся в виде дополнения до 2
19:00 < сипа> так что если старший бит первого байта установлен, это отрицательное юдоль
19:00 < сипа> но OpenSSL просто разбирает все как беззнаковое
19:02 < HM> Конечно, но как эти сделки получить признание?
19:02 < сипа> потому что OpenSSL анализирует все как беззнаковое
19:02 < сипа> и каждый Bitcoin полный узел использует OpenSSL для анализа подписи
19:04 < сипа> Представьте, что вы хотите сохранить значение 0x9999
19:04 < сипа> поэтому положительное целое число 39321
19:04 < сипа> правильное кодирование МЭД 0x009999
19:05 < сипа> а 0x9999 интерпретируется как -26215
19:06 < сипа> проблема, потому что OpenSSL знает, что ожидает целое число без знака, даже если вы храните 0x9999, он будет интерпретировать это, как 39321, а не как -26215
19:06 < HM> как сошедшие кодировать совершенно разумный 2 байт без знака в 3 байта с 1 бесполезного 0x00 байт?
19:06 < сипа> потому что это не значение без знака
19:06 < сипа> МЭД не имеет тип целого числа без знака
19:09 < сипа> в любом случае: нижняя строка: каждая реализация _должны_ принимает 0x9999, как 39321, даже если соответствующий стандартам DER анализатор может интерпретировать это как отрицательное число, которое вызвало бы ECDSA отклонить подпись, как вне диапазона
19:12 < сипа> а в некотором смысле это имеет смысл: "ОК вы дать мне эту подпись * синтаксическая * ки, синтаксический правильно. подождите ... это значение R отрицательна? я не ожидал отрицательного числа здесь ... давайте предположим, что вы просто пропустили 0 байт перед"
19:13 < сипа> Единственная проблема заключается в том, что Bitcoin передает подпись непосредственно в OpenSSL
19:13 < HM> поэтому в основном вы должны прочитать строку байтов и, если это уже не нулями, добавьте 0x00 байт
Ваш последний комментарий на Github спрашивает, если 5 байт разрешены.
хорошо - но ваши изменения позволяют 5 байт?
(Если это произойдет, то я думаю, проблема будет решена)
мы, очевидно, нужно работать: 0x017f, 0x02ff00 и 0x03ffff00 по крайней мере,
Это говорит в комментарии здесь CScriptNum закодирован принимать до 5 байт bignums, которые хорошо до 2 ** 39-1, а за пределы самого поля nLockTime 2 ** 32-1.
https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L355-L358 // Если мы сохранили до этого предела мы имеем проблему год 2038,
// даже если поле nLockTime в сделках
// самих uint32, который только становится бессмысленным
// после 2106 года.
//
// Так как частный случай, мы говорим CScriptNum принять до
// до 5 байт bignums, которые хорошо до 2 ** 39-1, хорошо
// за пределы самого поля nLockTime 2 ** 32-1.
Const CScriptNum nLockTime (stacktop (-1), fRequireMinimal, 5);