Значение, возвращаемое из Java PrivateKey.getEncoded()
, является частной клавишей в кодировке , как следует из названия. В частности, , как указано в суперклассе Key
, это кодировка ASN.1 (DER) PKCS # 8 = стандарт шифрования с открытым ключом # 8, Синтаксис информации личного ключа . PKCS # 8 обрабатывает приватные ключи для широкого спектра различных алгоритмов открытого ключа и содержит метаданные в дополнение к фактическому ключу, а именно «AlgorithmIdentifier», который идентифицирует алгоритм и любые параметры алгоритма; для алгоритма (ов) ECC (ECDSA, ECDH, ECMQV и другие совместно используют один ключевой формат) эти параметры указывают используемую группу эллиптических кривых, и хотя для этой спецификации существует несколько вариантов, на практике каждый, включая здесь Java, использует ' Параметр namedCurve ', который определяет группу кривых по идентификатору объекта ASN.1, также известному как Идентификатор объекта.
Затем структура PKCS # 8 содержит фактические данные закрытого ключа, «обернутые» в СТРОКУ ОКТЕТА, в формате, который изменяется в зависимости от алгоритма. Для ECC этот формат определен (AFAICT) в SEC1 с помощью SECG / Certicom и содержит фактическое значение закрытого ключа (число, выраженное как OCTET STRING) плюс , необязательно спецификация кривой и открытый ключ.
Ваш первый код использует BouncyCastle, и Bouncy генерирует кодировку с включенным значением, включая необязательную спецификацию кривой и открытый ключ, делая его длиннее.
Ваш второй код по умолчанию использует провайдера Oracle / Sun (SunEC), который генерирует кодировку без этих опций, но все еще включает в себя требуемый AlgorithmIdentifier, что делает его длиннее фактического значения privatekey. Он также использует другую кривую : при инициализации генератора SunEC с целым числом 256 выбирается secp256r1 (он же P-256, prime256v1), а не secp256k1. Если вы измените его на использование new ECGenParameterSpec("secp256k1")
в качестве параметра, SunEC также сгенерирует secp256k1, но без параметров, предоставляя 64-байтовую кодировку.
В обоих случаях, если вам нужен только закрытый ключ номер , приведите к java.security.interfaces.ECPrivateKey
и используйте getS()
. Если вы хотите получить результат в байтовом / октетном массиве, как это принято, обратите внимание, BigInteger.toByteArray()
возвращает результат переменной длины, и вам часто нужно оставить нулевое усечение или дополнить его.
И если вы действительно хотели публичный ключ, он имеет аналогичную схему, использующую кодировку 'X.509', которая содержит и AlgorithmIdentifier, и BIT STRING, заключающие фактическое значение publickey, и, следовательно, длиннее, чем необработанное значение publickey. Однако в этом случае interfaces.ECPublicKey
и spec.ECPoint
не создадут кодировку для вас; использование Bouncy-only типов может быть более удобным.