Так как вы попросили любую помощь, я отвечу на ваш вопрос и дам другие советы.
Как получить e
Один совет - использовать equals()
вместо compareTo()
, когда вы просто проверяете равенство.Иногда это может уменьшить объем выполняемой работы, а также его легче читать.
Самая большая ошибка в вашем коде заключается в том, что temp
используется для установки исходного значения GCD
, но , который не связывает temp
с GCD .Они остаются отключенными.Если вы измените temp
позже, GCD
не узнает об этом и не изменится.Вам нужно добавить один к GCD
напрямую.Вот пример кода:
BigInteger e = BigInteger.valueOf(3);
while (! phi.gcd(e).equals(BigInteger.ONE)) {
e = e.add(BigInteger.ONE);
}
Просмотрите методы BigInteger
Получите представление о том, что вы можете легко сделать с BigInteger
, используя вашу любимую поисковую систему ипоиск BigInteger 8 API
.8 для версии Java, которую вы используете, так что это может измениться.API предназначен для списка методов.
В самом начале результатов поиска вы должны найти эту страницу API .BigInteger
имеет много хороших и удобных методов, так что проверьте их.У него даже есть конструктор, который даст вам BigInteger
любого размера, который вы хотите, который, скорее всего, будет простым, что хорошо для генерации простых чисел для нового случайного ключа RSA.
Использование BigInteger
Встроенные константы
Не создавайте заново следующие константы (которые показаны на странице API выше):
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
Никогда не конвертируйте BigInteger
в long
, если вы не уверены, что оно будет соответствовать
Вы конвертируете BigInteger
s до long
, что является плохой идеей, поскольку существует множество BigInteger
, которые не помещаются в long
, давая вам неправильные результаты.Для правильности (что важнее скорости), делайте арифметику напрямую с BigInteger
s .
Вы также часто используете intValue()
, когда получаете long
.Используйте longValueExact()
.В этом отношении используйте intValueExact()
, когда вы получаете int
.
Итак, чтобы вычислить ϕ:
BigInteger pMinusOne = p.subtract(BigInteger.ONE);
BigInteger qMinusOne = q.subtract(BigInteger.ONE);
BigInteger phi = pMinusOne.multiply(qMinusOne);
Теперь вы знаете, что это даст правильные результаты, дажедля больших BigInteger
с.Это также не так сложно для чтения, что хорошо для поддержки кода позже.
Что хранить
Вы также должны хранить только n и e (и d , но только если это закрытый ключ) Никогда store p , q или ϕ с RSA, потому что они позволяют вам легко определить закрытый ключ из открытого ключа.
В общем, не рассчитывайте в getZZZ
методах
Вы должны выяснить n и e (и d , но только если это закрытый ключ) в методе (ах) конструктора и сохраняют только те, которые находятся в переменных экземпляра.Затем у вас может быть метод getN()
и getE()
для получения предварительно вычисленных переменных экземпляра.Например (и вам не нужно использовать этот код, это просто для того, чтобы дать представление):
public class RSA {
private final BigInteger n;
private final BigInteger e;
private final BigInteger d;
public RSA(final BigInteger p, final BigInteger q) {
this.n = p.multiply(q);
// Calculate phi
final BigInteger pMinusOne = p.subtract(BigInteger.ONE);
final BigInteger qMinusOne = q.subtract(BigInteger.ONE);
final BigInteger phi = pMinusOne.multiply(qMinusOne);
// Calculate e
BigInteger e = BigInteger.valueOf(3L);
while (! phi.gcd(e).equals(BigInteger.ONE)) {
e = e.add(BigInteger.ONE);
}
this.e = e;
// Calculate d
this.d = e.modInverse(phi);
}
public BigInteger getN() {
return n;
}
public BigInteger getE() {
return e;
}
public BigInteger getD() {
return d;
}
}