Построение E C Publi c Key из E C Point и ECParameterSpe c дает неверное значение x - PullRequest
2 голосов
/ 13 февраля 2020

У меня несжатая точка E C для кривой prime256v1, и я пытаюсь построить из нее объект PublicKey, используя приведенный ниже код (ссылка здесь ), с использованием поставщика BouncyCastle :

public static void main(String[] args) throws Exception
{
    // Using BC as SunEC (java8) doesn't support prime256v1.
    Security.addProvider(new BouncyCastleProvider());

    // Input values -----------------

    // Complete EC Point (with uncompressed prefix 04 and the length [41])
    // 0441044ef454741576ed945005ea87f114bf8045bcff84155914246aaef43bc35804c9537201ea2387f7edabf76e85b9a7fc341001ddda3272a9685d9aa36ff96526d9

    // EC Point value w/o the tag and length
    final String ecPointHex = "044ef454741576ed945005ea87f114bf8045bcff84155914246aaef43bc35804c9537201ea2387f7edabf76e85b9a7fc341001ddda3272a9685d9aa36ff96526d9";
    // final String ecParamsHex = "06082a8648ce3d030107"; // prime256v1; OID: 1.2.840.10045.3.1.7

    final String curveName = "prime256v1";
    // ------------------------------

    // EC Parameter Spec ------------

    AlgorithmParameters params = AlgorithmParameters.getInstance("EC", "BC");
    params.init(new ECGenParameterSpec(curveName));

    ECParameterSpec ecParameterSpec = params.getParameterSpec(ECParameterSpec.class);

    // ------------------------------

    // EC Point ---------------------

    byte[] ecPointBinary = Hex.decode(ecPointHex);

    byte[] x = Arrays.copyOfRange(ecPointBinary, 0, ecPointBinary.length / 2);
    byte[] y = Arrays.copyOfRange(ecPointBinary, ecPointBinary.length / 2, ecPointBinary.length);

    ECPoint ecPoint = new ECPoint(new BigInteger(1, x), new BigInteger(1, y));

    // ------------------------------

    // Construct Public Key ---------

    KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC"); // Tried ECDSA as well

    ECPublicKey ecPublicKey = (ECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec)); // <-- exception here

    System.out.println(ecPublicKey);

    // ------------------------------
}

Но я получаю это исключение:

Exception in thread "main" java.lang.IllegalArgumentException: x value invalid for SecP256R1FieldElement
    at org.bouncycastle.math.ec.custom.sec.SecP256R1FieldElement.<init>(Unknown Source)
    at org.bouncycastle.math.ec.custom.sec.SecP256R1Curve.fromBigInteger(Unknown Source)
    at org.bouncycastle.math.ec.ECCurve.createPoint(Unknown Source)
    at org.bouncycastle.math.ec.ECCurve.createPoint(Unknown Source)
    at org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertPoint(Unknown Source)
    at org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertPoint(Unknown Source)
    at org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey.<init>(Unknown Source)
    at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.engineGeneratePublic(Unknown Source)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:328)
    at com.test.ECStackOverflow.main(ECStackOverflow.java:70)

Что я делаю не так?

PS: этот PublicKey был создан в Saf eNet HSM а значения E C Point и Params извлекаются из объекта PublicKey.

1 Ответ

3 голосов
/ 13 февраля 2020

Вы включаете индикатор несжатой точки 04 в свое значение X, и поэтому ваши значения X и Y были смещены.

Поэтому прямой ответ - пропустить индикатор. Однако, чтобы быть уверенным, я не буду использовать размер точки, как вы ее получите, а используйте размер кривой, чтобы скопировать ее. Таким образом, метод потерпит неудачу до того, как произойдет считывание точек для кривой более низкого или более высокого размера.

Конечно, в этом случае вы также создадите проверку.

int primeSizeBytes = (ecParameterSpec.getCurve().getField().getFieldSize() + Byte.SIZE - 1) / Byte.SIZE;

if (ecPointBinary.length != 1 + 2 * primeSizeBytes) {
    // or think of your own exception
    throw new InvalidKeyException("EC point size invalid");
}

if (ecPointBinary[0] != 04) {
    throw new InvalidKeyException("EC uncompressed point indicator with byte value 04 missing");
}

byte[] x = Arrays.copyOfRange(ecPointBinary, 1, 1 + primeSizeBytes);
byte[] y = Arrays.copyOfRange(ecPointBinary, 1 + primeSizeBytes, 1 + 2 * primeSizeBytes);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...