在Java中使用RSA算法加密字符串时出现问题

发布于 2024-11-04 01:19:03 字数 1485 浏览 1 评论 0原文

我正在尝试采用 RSA 算法来加密 String 对象,但似乎 BigInteger ->字符串和字符串 -> 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);
    }
}

它打印的不是预期的内容,奇怪的是每次输出都不同。我做错了什么吗?谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

长亭外,古道边 2024-11-11 01:19:04

加密消息是任意的byte[],不保证能正确转换为特定字符编码的String,所以不需要转换为>字符串。

另一个技巧是plaintext应该小于n,否则算法会产生垃圾。当这个条件满足时,它对我来说就很好用。

另一个可能的问题是,当消息的第一个字节大于或等于0x80时,将产生负的明文。可以通过在将消息转换为 BigInteger 之前在消息字节前面添加一个零字节,并在逆转换期间剥离该字节来解决此问题。

Encrypted message is an arbitrary byte[], it's not guaranteed that it can be correctly converted to String with particular character encoding, so there is no need to convert it to String.

Another trick is that plaintext should be less than n, 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 negative plaintext would be produced. It can be solved by prepending a zero byte to the bytes of message before converting it to BigInteger, and stripping that byte during inverse conversion.

毁梦 2024-11-11 01:19:04

提示: getBytes 与 message 的字符串值有何不同?
你为什么不直接做 BigInteger(message); ?

Hint: What does getBytes do that's different from the string value of message?
Why aren't you just doing BigInteger(message); ?

浅紫色的梦幻 2024-11-11 01:19:04
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);    
   }     
}
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);    
   }     
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文