Проблемы шифрования строки с использованием алгоритма RSA в Java - PullRequest
3 голосов
/ 28 апреля 2011

Я пытаюсь принять алгоритм RSA для шифрования объектов String, но кажется, что преобразования BigInteger -> String и String -> BigInteger не работают должным образом. Вот мой код:

public class RSAEncryptor {

    private BigInteger n, d, e;

    public RSAEncryptor(int bitlen) {
        SecureRandom r = new SecureRandom();
        BigInteger p = new BigInteger(bitlen / 2, 100, r);
        BigInteger q = new BigInteger(bitlen / 2, 100, r);
        n = p.multiply(q);
        BigInteger m = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
        e = new BigInteger("3");
        while (m.gcd(e).intValue() > 1) {
            e = e.add(new BigInteger("2"));
        }
        d = e.modInverse(m);
    }

    public String encrypt(String message) {
        BigInteger plaintext = new BigInteger(message.getBytes());
        return new String(plaintext.modPow(e, n).toByteArray());
    }

    public String decrypt(String message) {
        BigInteger plaintext = new BigInteger(message.getBytes());
        return new String(plaintext.modPow(d, n).toByteArray());
    }
}

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        RSAEncryptor encryptor = new RSAEncryptor(64);

        String source = "1";
        String crypted = encryptor.encrypt(source);
        System.out.println(crypted);
        String decrypted = encryptor.decrypt(crypted);
        System.out.println(decrypted);
    }
}

Он печатает не то, что ожидается, и странно то, что каждый раз, когда вывод отличается. Я делаю что-то неправильно? Спасибо

Ответы [ 3 ]

2 голосов
/ 28 апреля 2011

Зашифрованное сообщение является произвольным byte[], не гарантируется, что оно может быть правильно преобразовано в String с определенной кодировкой символов, поэтому нет необходимости преобразовывать его в String.

ДругоеХитрость заключается в том, что plaintext должно быть меньше n, иначе алгоритм выдаст мусор.Когда это условие выполняется, оно прекрасно работает для меня.

Еще одна возможная проблема заключается в том, что, когда первый байт сообщения больше или равен 0x80, будет получен отрицательный plaintext.Это можно решить, добавив нулевой байт к байту сообщения перед его преобразованием в BigInteger и очистив этот байт во время обратного преобразования.

0 голосов
/ 23 августа 2013
import java.math.BigInteger;     
import java.security.SecureRandom;

public class RSA {  
   private final static BigInteger one      = new BigInteger("1");  
   private final static SecureRandom random = new SecureRandom();

   private BigInteger privateKey;  
   private BigInteger publicKey;  
   private BigInteger modulus;   

   // generate an N-bit (roughly) public and private key  
   RSA(int N) {  
      BigInteger p = BigInteger.probablePrime(N/2, random);  
      BigInteger q = BigInteger.probablePrime(N/2, random);   
      BigInteger phi = (p.subtract(one)).multiply(q.subtract(one));       
      modulus    = p.multiply(q);                                          
      publicKey  = new BigInteger("65537");       
   // common value in practice = 2^16 + 1
      privateKey = publicKey.modInverse(phi);   
   }


   BigInteger encrypt(BigInteger message) {    
      return message.modPow(publicKey, modulus);    
   }  

   BigInteger decrypt(BigInteger encrypted) {     
      return encrypted.modPow(privateKey, modulus);    
   }    

   public String toString() {    
      String s = "";    
      s += "public  = " + publicKey  + "\n";   
      s += "private = " + privateKey + "\n";    
      s += "modulus = " + modulus;    
      return s;    
   }    

   public static void main(String[] args) {    
      int N = Integer.parseInt(args[0]);    
      RSA key = new RSA(N);    
      System.out.println(key);    
      // create random message, encrypt and decrypt   
      BigInteger message = new BigInteger(N-1, random);   
      //// create message by converting string to integer   
      // String s = "test";    
      // byte[] bytes = s.getBytes();    
      // BigInteger message = new BigInteger(s);    
      BigInteger encrypt = key.encrypt(message);    
      BigInteger decrypt = key.decrypt(encrypt);    
      System.out.println("message   = " + message);    
      System.out.println("encrpyted = " + encrypt);    
      System.out.println("decrypted = " + decrypt);    
   }     
}
0 голосов
/ 28 апреля 2011

Подсказка: что getBytes отличается от строкового значения сообщения?Почему вы просто не делаете BigInteger (сообщение);

...