Соглашение о ключе BouncyCastle ECDH не выполнено

Я реализовал криптографию Диффи-Хеллмана с использованием эллиптических кривых с использованием API BouncyCastle. Но, похоже, соглашение о ключах не работает должным образом. Это печатает ложь.

Где я сделал не так? Спасибо.

ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("B-571");

    KeyPairGenerator g = KeyPairGenerator.getInstance("ECDH", "BC");

    g.initialize(ecSpec, new SecureRandom());

    KeyPair aKeyPair = g.generateKeyPair();

    KeyAgreement aKeyAgree = KeyAgreement.getInstance("ECDH", "BC");

    aKeyAgree.init(aKeyPair.getPrivate());

     KeyPair bKeyPair = g.generateKeyPair();

    KeyAgreement bKeyAgree = KeyAgreement.getInstance("ECDH", "BC");

    bKeyAgree.init(bKeyPair.getPrivate());

    //
    // agreement
    //
    aKeyAgree.doPhase(bKeyPair.getPublic(), true);
    bKeyAgree.doPhase(aKeyPair.getPublic(), true);

    byte[] aSecret = aKeyAgree.generateSecret();
    byte[] bSecret = bKeyAgree.generateSecret();

    System.out.println(aSecret);
    System.out.println(bSecret);
    if (aSecret.equals(bSecret)){
        return true;
    } else { return false; }

1 ответ

Решение

Это работает правильно, когда я тестировал с Bouncy Castle 1.49. Однако вы сравниваете, используя неправильный метод.

  • Если вам нужно постоянное сравнение, используйте MessageDigest.isEqual,
  • Если вам не нужно сравнение с постоянным временем, используйте Arrays.equals,

Чтобы распечатать содержимое байтовых массивов, используйте Arrays.toString:

System.out.println(Arrays.toString(aSecret));
System.out.println(Arrays.toString(bSecret));
return MessageDigest.isEqual(aSecret, bSecret);

Редактировать: ОП попросил меня объяснить, что означает "сравнение с постоянной времени", и вот так: сравнение с постоянной времени занимает одинаковое количество времени, независимо от того, совпадают две строки или нет. Сравнение без постоянной времени обычно выполняется быстрее, если две строки имеют несоответствие, а время выполнения зависит от того, где находится несоответствие: сравнение останавливается, когда обнаруживается первое несоответствие.

Нужно ли вам сравнение с постоянным временем или нет, зависит от того, есть ли у вас оракул времени. То есть время, затраченное на сравнение, даст злоумышленнику полезную информацию?

Вот пример временного оракула: предположим, что вы веб-сервер, отправляющий куки в браузер. Вы не хотите, чтобы пользователь вмешивался в cookie, поэтому вы присоединяете HMAC к содержимому cookie:

cookie_to_send = hmac(cookie) + ":" + cookie

Теперь, когда браузер отправляет вам файл cookie, вы заново вычисляете HMAC и смотрите, соответствует ли он:

mac, cookie = received_cookie.split(":")
compare(mac, hmac(cookie))

И если сравнение не удается (mac не соответствует hmac(cookie)), тогда вы отклоните запрос.

В этом compare Операция выше, очень, очень важно, чтобы это было сравнение с постоянным временем. В противном случае злоумышленник может посмотреть, сколько времени понадобилось вашему серверу, чтобы отклонить запрос, и использовать его, чтобы определить ожидаемое значение HMAC. Это потому, что один компонент сравнения (значение HMAC в cookie, перед первым :) контролируется злоумышленником, и злоумышленник может корректировать его значение побайтно, чтобы увидеть, сколько времени занимает отклонение каждый раз.


В вашем случае ваши байтовые массивы (которые вы сравниваете) генерируются из generateSecret(), что говорит мне о том, что он не контролируется злоумышленниками. Таким образом, на первый взгляд, это не выглядит так, как будто необходимо постоянное сравнение. Но я не эксперт по безопасности, поэтому точно не знаю. Всегда безопасно (но может быть медленным, если сравниваемые строки длинные) использовать сравнение с постоянной времени, поэтому, если вообще не уверены, это то, что я предлагаю.

Другие вопросы по тегам