I'm trying to adopt RSA algorithm for encrypting String objects, but seems that BigInteger -> String and String -> BigInteger conversions do not work properly. Here's my code:
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);
}
}
It prints not what is expected, and a strange thing is that every time the output differs. Am I doing something wrong? Thanks
Hint: What does getBytes do that's different from the string value of message? Why aren't you just doing BigInteger(message); ?
Encrypted message is an arbitrary
byte[]
, it's not guaranteed that it can be correctly converted toString
with particular character encoding, so there is no need to convert it toString
.Another trick is that
plaintext
should be less thann
, otherwise algorithm would produce garbage. When this condition is met, it works fine for me.Yet another possible problem is that when the first byte of message in greater or equal than
0x80
, a negativeplaintext
would be produced. It can be solved by prepending a zero byte to the bytes of message before converting it toBigInteger
, and stripping that byte during inverse conversion.