Хорошо, это действительно выглядит как (DER) OCTET STRING (тег 04, длина 39 hex), содержащий точку в стандартном (X9.62 / SEC1 et seq) несжатом формате (первый октет 04) для 28-октетного кода. (224-битная) кривая. Это кажется мне глупым, поскольку все известные мне стандартные структуры ASN.1 помещают (точечный или другой) pubkey в BIT STRING и включают метаданные, но, очевидно, это известно или, по крайней мере, о нем слышно, потому что asn1.x9.X9ECPoint
имеет конструктор для него. (Для краткости и форматирования я опускаю внешний пакет org.bouncycastle
, который применяется ко всему.)
Чтобы использовать точку, вам нужно указать, на какой она кривой; Мне известны две 224-битные кривые (точнее, наборы параметров), стандартизированные SECG и X9, secp224 {k1, r1}, последняя из которых (только) принята NIST в FIPS 186-2 + как P-224, и два стандартизированы TeleTrusT как brainpool224 {r1, t1}. Они доступны встроенными от asn1.x9.ECNamedCurveTable
или jce.ECNamedCurveTable
. Может быть любое количество нестандартных кривых, которые AFAICT вам придется создавать самостоятельно. Если вы не знаете, на какой кривой находится ваша несжатая точка, вы можете с точной точностью угадать, проверяя, удовлетворяет ли она уравнениям кривых-кандидатов; Я слишком ленив, чтобы сделать это для вас. (Сжатую точку будет гораздо сложнее угадать, возможно, невозможно.)
Учитывая кривую (из набора параметров или прямой), преобразуйте DER в ASN1OctetString
с ASN1OctetString.getInstance(ASN1Primitive.fromByteArray(byte[]))
или просто ASN1OctetString.getInstance(Object/*byte[]*/)
, который делает первое для вас, и тогда вы можете напрямую построить X9ECPoint и в зависимости от того, с какими API вы хотите его использовать, либо вызовите .getPoint
для преобразования в math.ec.ECPoint
, либо создайте связанные (более сложные) структуры, такие как crypto.params.ECPublicKeyParameters
.
Добавлено в ответ на комментарий, так как это довольно долго, плюс несколько изменяет мой ответ:
Я не осознавал, что вы используете dotNET; Мой опыт связан с Java-версией Bouncy, и я впечатлен тем, что две версии достаточно точно отслеживают ваш код, даже компилируя. FWIW Java-эквиваленты вашего пересмотренного кода, с одним добавлением явного построения BCECPublicKey
из параметров, потому что JCE Signature
принимает только тип Key
, а не тип Parameters
, работает для меня с тестовой парой ключей и данные. Вы можете попробовать выполнить аналогичное упражнение - создать пару ключей и подпись (для известных данных) в программном обеспечении и подтвердить, работает ли ваш код для этого случая, а затем попытаться изолировать различия в случае с аппаратной подписью. Хотя PKCS11 и другие аппаратные устройства часто разрабатываются для предотвращения экспорта сгенерированных ключами устройств в программное обеспечение, где они, вероятно, подвергаются большему риску компрометации, они не всегда настолько строги при импорте - вы можете использовать свое программное обеспечение. сгенерированный ключ в аппаратном обеспечении для сравнения.
В дополнение к общим причинам, по которым любая подпись не должна проверять (неправильные данные, неправильный хеш-код, который вы явно используете по умолчанию, неправильный ключ), существует и другая возможность , возможно - формат подписи. Существует два обычно используемых формата (или кодировки) для сигнатур ECDSA (и DSA): либо ПОСЛЕДОВАТЕЛЬНОСТЬ ИНТЕГРОВ ASN.1 в DER, либо просто два целых числа в фиксированном двоичном формате, объединенные без каких-либо метаданных. «Стандартная» Java (точнее, Java с поставщиками Sun / Oracle) использует только формат ASN.1; Java с Bouncy по умолчанию - ASN.1, но поддерживает фиксированный формат для ECDSA, если вы измените имя алгоритма на [hash]WITH{PLAIN,CVC}-ECDSA
, поэтому я ожидаю, что Bouncy в dotNET (при условии, что ваш код использует его, хотя и не указано явно), может делать то же самое , Я понимаю (но не имею личного опыта) PKCS11 использует фиксированный формат. Если я передаю Java Bouncy в неправильном формате, он выдает исключение, а не возвращает verify = false, но я не знаю, может ли dotNET отличаться здесь. Посмотрите на значение вашей подписи подробно, чтобы проверить, какой это формат.