繁体   English   中英

使用Java RSA加密和使用BigInteger解密

[英]encryption with java RSA and decryption with BigInteger

因此,我试图弄清楚如何在Java中加密和解密RSA。 加密是通过javas API完成的,解密是通过biginteger完成的。 我完成了,但是biginteger有时会给我奇怪的输出。 这是我的代码:

import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class cryptoAndBigIntegerFIX {
    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException{
        Security.addProvider(new BouncyCastleProvider());
        System.out.println("input <> encrypted <> decrypted");
        cryptoAndBigIntegerFIX.keygen();

        BigInteger encryptbytes;
        BigInteger decryptbytes;

        //Multiple tests with powers of 3 for some reason :D
        for(int i=1;i<1000;i*=3){
            encryptbytes = cryptoAndBigIntegerFIX.encrypt(new BigInteger(""+i));
            System.out.print(i + " <> " + encryptbytes.intValue() + " <> ");
            decryptbytes = cryptoAndBigIntegerFIX.decrypt(encryptbytes);
            System.out.println(decryptbytes.intValue());            
        }
    }

    public static RSAPrivateKey priv;
    public static RSAPublicKey pub;

    public static void keygen() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException{
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");

        generator.initialize(512);
        KeyPair keyPair = generator.generateKeyPair();
        priv = (RSAPrivateKey) keyPair.getPrivate();
        pub = (RSAPublicKey) keyPair.getPublic();       
    }

    //Encrypt with javas API
    public static BigInteger encrypt(BigInteger bg) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException{
        byte[] encoded;
        Cipher cipher=Cipher.getInstance("RSA/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, pub);
        encoded=cipher.doFinal(bg.toByteArray());
        return new BigInteger(encoded);
    }

    //Decrypt manually
    public static BigInteger decrypt(BigInteger bg){
        BigInteger decoded = bg.modPow(priv.getPrivateExponent(),priv.getModulus());
        return decoded;

    }

}

这给出的输出是:

input <> encrypted <> decrypted
1 <> 1 <> 1
3 <> 1088098617 <> 3
9 <> 1947497039 <> 9
27 <> -1665331145 <> 27
81 <> -1064046970 <> 81
243 <> -599005266 <> 243
729 <> -1534949160 <> 729

这是正确的,因为我正在尝试加密和解密3的幂。 但是有时它会给出错误的输出,例如:

input <> encrypted <> decrypted
1 <> 1 <> 1
3 <> 1693488667 <> 3
9 <> -924345856 <> 9
27 <> 777525903 <> 144224668
81 <> -1602799071 <> 765474161
243 <> -227258229 <> 243
729 <> 1097077312 <> 296615835

哪个很奇怪? 知道我的代码有什么问题吗? biginteger或我生成密钥的方式是否有问题?

您的代码中有两个错误,将这些结果修正为正确的输出:

  • RSA返回一个字节数组,该字节数组表示无符号 (大端)值的编码,而BigInteger构造函数期望一个有符号 (大端)值。
  • 您使用intValue将您的〜512位整数转换为32位int ,这是一种狭窄的转换(即,您丢失了大部分信息);

要解决此问题,请在主机中使用以下代码:

for (int i = 1; i < 1000; i *= 3) {
    encryptbytes = encrypt(new BigInteger("" + i));
    decryptbytes = decrypt(encryptbytes);
    System.out.printf("%d <> %d <> %d%n", i, encryptbytes, decryptbytes); // <-- CHANGED
}

并修复您的encrypt方法,如下所示:

public static BigInteger encrypt(BigInteger bg) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException{
    byte[] encoded;
    Cipher cipher=Cipher.getInstance("RSA/ECB/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, pub);
    encoded=cipher.doFinal(bg.toByteArray());
    // always return a positive number, all numbers in RSA range from 0 to N, the modulus
    return new BigInteger(1, encoded); // <-- CHANGED
}

输出:

1 <> 1 <> 1
3 <> 5391244976364305547335484748020521942086098609617330384518129302949818422340576199311962549547267600132422679070440104879858341377467952359964277978034437 <> 3
9 <> 6124821216540311592072512276604516925109106437800474377305024835746311326643844937438898166014089888517013623381274703706957136996030394061334489396421471 <> 9
27 <> 7417955231776825208837885603385850571492475371613109504900294367112291012186031184819506881671785651668774452694772296927652149185293472327267855826108811 <> 27
81 <> 4379633872520787556108807271103986910459839084415924804306544674047140392288351081810043910720852387318488882506988222018682090612584816530149697340650488 <> 81
243 <> 7246933972891920591130671309726014055879369415307203680175037003794552795366338573568427805702031164261947749468386326443821678079330776559688467025349997 <> 243
729 <> 1545447812776244759821683256943744637177323415383752406121617316817182282617298911713206245407992744746920675542053503316837741108184755354755351275313816 <> 729

对其他读者的警告:切勿使用纯文本/原始RSA(Java中为"RSA/ECB/NoPadding" ),这是不安全的。 尝试使用带有RSA OAEP的混合密码系统。 不要复制/粘贴上面的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM