Почему мой код шифрования RSA работает для небольших размеров, а не для больших? - PullRequest
2 голосов
/ 13 апреля 2019

Я не много кодирую, но когда я пытаюсь реализовать шифрование RSA в JAVA, мой шифрование и дешифрование работают для простых чисел меньшего размера, но, когда я пытаюсь сделать это для простых чисел размером 1536 бит, дешифрование перестает работать.Я прошел через это, но я не вижу, в чем проблема.

Я уже пытался увидеть, в какой момент длина бит начинает становиться проблемой, и кажется, что когда я устанавливаюэто до 50, когда перестает работать.Я также, как правило, получаю сообщение об ошибке, если мой метод обратного мода выдает ошибку о невозможности e.modinv (lambda).Я попытался исправить это, добавив цикл do, но, похоже, это не решило проблему.

public BigInteger Random_Prime()
{
    SecureRandom random = new SecureRandom();
    byte [] randomize = new byte [192];
    random.nextBytes(randomize);
    BigInteger big = new BigInteger(randomize);
    return big.probablePrime(1536,random);
}
public BigInteger lcm(BigInteger p, BigInteger q)
{
    long p1 = p.longValue()-1;
    long q1 = q.longValue()-1;
    BigInteger test1 = p.valueOf(p1);
    BigInteger test2 = p.valueOf(q1);
    return test1.multiply(test2).divide(test1.gcd(test2));

do {

        p = obj1.Random_Prime();
        q = obj1.Random_Prime();
        lambda = obj1.lcm(p, q);
    }
    while(lambda.gcd(e).compareTo(ONE)!=0);
    BigInteger n = p.multiply(q);
    BigInteger m = new BigInteger("75");
    BigInteger d = e.modInverse(lambda);
    BigInteger c = obj1.Encrypt(n,e,m);

Я ожидаю, что 75 вернется как 75после прохождения шифрования и дешифрования.

1 Ответ

4 голосов
/ 13 апреля 2019

Ваш lcm() неверен.

Java long - это только 64 бита, включая знак, и не может представлять числа больше 2 ^ 63.(Или равно, но большое простое число никогда не равно степени 2). Таким образом, ваше вычисление lcm должно работать для p, q до 63 бит, и работает для меня, но дает совершенно неправильные и бесполезные результаты для чего-то большего,Вместо этого используйте {p,q}.subtract(BigInteger.ONE) для чисел, которые вы умножаете и делите на gcd.

Кроме того, BigInteger.probablePrime(int,Random) - это метод static (он же класс);вам не нужно вызывать его с использованием какого-либо экземпляра, тем более случайного значения, которое вы потратили впустую на вычисления, потому что оно игнорируется.В этом отношении BigInteger.valueOf(long) также static и игнорирует любой экземпляр, используемый для его вызова.Если вы используете какую-либо среду разработки Java более продвинутую, чем просто набирать javac для оболочки или COMMAND, она должна (по крайней мере, опционально) предупредить вас об использовании экземпляра для вызова статического метода.

Наконец, если вы не знаете, использование примитивов RSA m ^ e mod n и c ^ d mod n напрямую для шифрования / дешифрования данных, особенно небольших данных, небезопасно.Вы должны использовать достаточно большую и случайную схему заполнения, чтобы это вообще было безопасно;см. wikipedia для краткого объяснения, и если вы хотите больше поиска по https://crypto.stackexchange.com и, возможно, https://security.stackexchange.com, где об этом спрашивали и отвечали много раз,И если вы расшифровываете (что вы не показывали), просто делая c.modPow(d,n), то это неэффективно (см. Википедию о CRT) и небезопасно (см. Википедию о времени атаки, и снова crypto.SX и security.SX).А использование RSA напрямую для данных является очень ограниченным и неэффективным, поэтому на практике люди используют гибридное шифрование - используют симметричный алгоритм (в настоящее время обычно AES) для шифрования данных с использованием одноразового ключа и шифрования этого одноразового ключа.используя RSA - или, возможно, лучше получить , используя RSA-KEM (снова см. википедию crypto.SX security.SX).

Если вы действительно хотите обеспечить безопасность , а не просто поиграть, используйте криптографию из библиотеки Java , которая была правильно реализована (и проверена) компетентными людьми,в отличие от вашего кода.

...