RSA加解密「JAVA」

记录一下java如何使用RSA,以下主要有三种方法,基本大同小异,只是获取公钥私钥的途径不一样,总结起来也就是:

  1. KeyPairGenerator获取key
  2. String获取key
  3. modulus和exponent获取key

方法一:

利用KeyPairGenerator直接生成公钥和密钥,一般私钥保留给服务端,公钥交给客户端

package com.michael.RSA;

import javax.crypto.Cipher;
import java.security.*;
import java.util.Base64;

public class RSACryptography {

    public static String data = "hello world";
    
    public static void main(String[] args) {
        KeyPair keyPair = genKeyPair(1024);

        // 获取公钥,并以base64格式打印出来
        PublicKey publicKey = keyPair.getPublic();
        System.out.println("公钥:" + base64Encode(publicKey.getEncoded()));

        // 获取私钥,并以base64格式打印出来
        PrivateKey privateKey = keyPair.getPrivate();
        System.out.println("私钥:" + base64Encode(privateKey.getEncoded()));

        // 公钥加密
        byte[] encryptedBytes = encrypt(data.getBytes(), publicKey);
        System.out.println("加密后:" + new String(encryptedBytes));

        // 私钥解密
        byte[] decryptedBytes = decrypt(encryptedBytes, privateKey);
        System.out.println("解密后:" + new String(decryptedBytes));
    }

    public static String base64Encode(byte[] src) {
        return new String(Base64.getEncoder().encode(src));
    }

    /**
     * 生成密钥对
     *
     * @param keyLength
     * @return
     */
    public static KeyPair genKeyPair(int keyLength) {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024);
            return keyPairGenerator.generateKeyPair();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 公钥加密
     *
     * @param content
     * @param publicKey
     * @return
     */
    public static byte[] encrypt(byte[] content, PublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");// java默认"RSA"="RSA/ECB/PKCS1Padding"
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 私钥解密
     *
     * @param content
     * @param privateKey
     * @return
     */
    public static byte[] decrypt(byte[] content, PrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

方法二:

方法一只是用来生成密钥就OK了,生成的密钥需要保存到本地文件中,所以一般不会在客户端调用KeyPairGenerator进行密钥的生成操作。
可以将方法一得到的密钥保存到文件,下次我们直接读取就可以了。
假设以String的形式保存在文件内,那么接下来直接使用读取到的String生成密钥即可。
也可以使用openssl来生成

package com.michael.RSA;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.*;
import java.util.Base64;

public class RSACryptography2 {

    public static String data = "hello world";
    
    public static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCISLP98M/56HexX/9FDM8iuIEQozy6kn2JMcbZS5/BhJ+U4PZIChJfggYlWnd8NWn4BYr2kxxyO8Qgvc8rpRZCkN0OSLqLgZGmNvoSlDw80UXq90ZsVHDTOHuSFHw8Bv//B4evUNJBB8g9tpVxr6P5EJ6FMoR/kY2dVFQCQM4+5QIDAQAB";
    public static String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIhIs/3wz/nod7Ff/0UMzyK4gRCjPLqSfYkxxtlLn8GEn5Tg9kgKEl+CBiVad3w1afgFivaTHHI7xCC9zyulFkKQ3Q5IuouBkaY2+hKUPDzRRer3RmxUcNM4e5IUfDwG//8Hh69Q0kEHyD22lXGvo/kQnoUyhH+RjZ1UVAJAzj7lAgMBAAECgYAVh26vsggY0Yl/Asw/qztZn837w93HF3cvYiaokxLErl/LVBJz5OtsHQ09f2IaxBFedfmy5CB9R0W/aly851JxrI8WAkx2W2FNllzhha01fmlNlOSumoiRF++JcbsAjDcrcIiR8eSVNuB6ymBCrx/FqhdX3+t/VUbSAFXYT9tsgQJBALsHurnovZS1qjCTl6pkNS0V5qio88SzYP7lzgq0eYGlvfupdlLX8/MrSdi4DherMTcutUcaTzgQU20uAI0EMyECQQC6il1Kdkw8Peeb0JZMHbs+cMCsbGATiAt4pfo1b/i9/BO0QnRgDqYcjt3J9Ux22dPYbDpDtMjMRNrAKFb4BJdFAkBMrdWTZOVc88IL2mcC98SJcII5wdL3YSeyOZto7icmzUH/zLFzM5CTsLq8/HDiqVArNJ4jwZia/q6Fg6e8KO2hAkB0EK1VLF/ox7e5GkK533Hmuu8XGWN6I5bHnbYd06qYQyTbbtHMBrFSaY4UH91Qwd3u9gAWqoCZoGnfT/o03V5lAkBqq8jZd2lHifey+9cf1hsHD5WQbjJKPPIb57CK08hn7vUlX5ePJ02Q8AhdZKETaW+EsqJWpNgsu5wPqsy2UynO";

    public static void main(String[] args) {

        //获取公钥
        PublicKey publicKey = getPublicKey(PUBLIC_KEY);

        //获取私钥
        PrivateKey privateKey = getPrivateKey(PRIVATE_KEY);

        //公钥加密
        byte[] encryptedBytes = encrypt(data.getBytes(), publicKey);
        System.out.println("加密后:" + new String(encryptedBytes));

        //私钥解密
        byte[] decryptedBytes = decrypt(encryptedBytes, privateKey);
        System.out.println("解密后:" + new String(decryptedBytes));
    }

    /**
     * 将base64编码后的公钥字符串转成PublicKey实例
     *
     * @param publicKey
     * @return
     */
    public static PublicKey getPublicKey(String publicKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(publicKey.getBytes());
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(keySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将base64编码后的私钥字符串转成PrivateKey实例
     *
     * @param privateKey
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(privateKey.getBytes());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(keySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 公钥加密
     *
     * @param content
     * @param publicKey
     * @return
     */
    public static byte[] encrypt(byte[] content, PublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");// java默认"RSA"="RSA/ECB/PKCS1Padding"
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 私钥解密
     *
     * @param content
     * @param privateKey
     * @return
     */
    public static byte[] decrypt(byte[] content, PrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

方法三:

除了保存密钥字符串之外,其他的做法一般是只保存 模n(modulus),公钥和私钥的e和d(exponent);其中,n, e, d可以这样获取到,获取到后可以保存到本地文件中。

//获取公钥
RSAPublicKey publicKey=(RSAPublicKey) getPublicKey(publicKeyString);
BigInteger modulus1=publicKey.getModulus();
BigInteger exponent1=publicKey.getPublicExponent();
	
//获取私钥
RSAPrivateKey privateKey=(RSAPrivateKey) getPrivateKey(privateKeyString);		
BigInteger modulus2=privateKey.getModulus();
BigInteger exponent2=privateKey..getPrivateExponent();

假设已经从文件中读取到了modulusexponent

package com.michael.RSA;

import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;

public class RSACryptography3 {

    public static String data = "hello world";

    public static String MODULUS = "95701876885335270857822974167577168764621211406341574477817778908798408856077334510496515211568839843884498881589280440763139683446418982307428928523091367233376499779842840789220784202847513854967218444344438545354682865713417516385450114501727182277555013890267914809715178404671863643421619292274848317157";

    public static String PUBLIC_EXPONENT = "65537";

    public static String PRIVATE_EXPONENT = "15118200884902819158506511612629910252530988627643229329521452996670429328272100404155979400725883072214721713247384231857130859555987849975263007110480563992945828011871526769689381461965107692102011772019212674436519765580328720044447875477151172925640047963361834004267745612848169871802590337012858580097";

    public static void main(String[] args) throws Exception {
        //由n和e获取公钥
        PublicKey publicKey = getPublicKey(MODULUS, PUBLIC_EXPONENT);

        //由n和d获取私钥
        PrivateKey privateKey = getPrivateKey(MODULUS, PRIVATE_EXPONENT);

        //公钥加密
        String encrypted = encrypt(data, publicKey);
        System.out.println("加密后:" + encrypted);

        //私钥解密
        String decrypted = decrypt(encrypted, privateKey);
        System.out.println("解密后:" + new String(decrypted));
    }

    /**
     * 将base64编码后的公钥字符串转成PublicKey实例
     *
     * @param modulusStr
     * @param exponentStr
     * @return
     */
    public static PublicKey getPublicKey(String modulusStr, String exponentStr) {
        try {
            BigInteger modulus = new BigInteger(modulusStr);
            BigInteger exponent = new BigInteger(exponentStr);
            RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(publicKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将base64编码后的私钥字符串转成PrivateKey实例
     *
     * @param modulusStr
     * @param exponentStr
     * @return
     */
    public static PrivateKey getPrivateKey(String modulusStr, String exponentStr) {
        try {
            BigInteger modulus = new BigInteger(modulusStr);
            BigInteger exponent = new BigInteger(exponentStr);
            RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(privateKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 公钥加密,并转换成十六进制字符串打印出来
     *
     * @param content
     * @param publicKey
     * @return
     */
    public static String encrypt(String content, PublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");// java默认"RSA"="RSA/ECB/PKCS1Padding"
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);

            int splitLength = ((RSAPublicKey) publicKey).getModulus().bitLength() / 8 - 11;
            byte[][] arrays = splitBytes(content.getBytes(), splitLength);
            StringBuffer sb = new StringBuffer();
            for (byte[] array : arrays) {
                sb.append(bytesToHexString(cipher.doFinal(array)));
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 私钥解密,并转换成十六进制字符串打印出来
     *
     * @param content
     * @param privateKey
     * @return
     */
    public static String decrypt(String content, PrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            int splitLength = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8;
            byte[] contentBytes = hexString2Bytes(content);
            byte[][] arrays = splitBytes(contentBytes, splitLength);
            StringBuffer sb = new StringBuffer();
            for (byte[] array : arrays) {
                sb.append(new String(cipher.doFinal(array)));
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 拆分byte数组
     *
     * @param bytes
     * @param splitLength
     * @return
     */
    public static byte[][] splitBytes(byte[] bytes, int splitLength) {
        int x; //商,数据拆分的组数,余数不为0时+1
        int y; //余数
        y = bytes.length % splitLength;
        if (y != 0) {
            x = bytes.length / splitLength + 1;
        } else {
            x = bytes.length / splitLength;
        }
        byte[][] arrays = new byte[x][];
        byte[] array;
        for (int i = 0; i < x; i++) {
            if (i == x - 1 && bytes.length % splitLength != 0) {
                array = new byte[bytes.length % splitLength];
                System.arraycopy(bytes, i * splitLength, array, 0, bytes.length % splitLength);
            } else {
                array = new byte[splitLength];
                System.arraycopy(bytes, i * splitLength, array, 0, splitLength);
            }
            arrays[i] = array;
        }
        return arrays;
    }

    /**
     * byte数组转十六进制字符串
     *
     * @param bytes
     * @return
     */
    public static String bytesToHexString(byte[] bytes) {
        StringBuffer sb = new StringBuffer(bytes.length);
        String sTemp;
        for (int i = 0; i < bytes.length; i++) {
            sTemp = Integer.toHexString(0xFF & bytes[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 十六进制字符串转byte数组
     *
     * @param hex
     * @return
     */
    public static byte[] hexString2Bytes(String hex) {
        int len = (hex.length() / 2);
        hex = hex.toUpperCase();
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }

    private static byte toByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RSA(Rivest–Shamir–Adleman)是一种非对称加密算法,可以用于加密和解密数据。在Java中,可以使用Java加密扩展(Java Cryptography Extension,JCE)提供的RSA类来实现RSA加解密。 以下是一个简单的RSA加解密示例: ```java import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import javax.crypto.Cipher; public class RSADemo { public static void main(String[] args) throws Exception { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); // 生成RSA密钥对 KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC"); generator.initialize(2048); KeyPair keyPair = generator.generateKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); // 使用公钥加密数据 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] input = "Hello, world!".getBytes(); byte[] cipherText = cipher.doFinal(input); System.out.println("Cipher text: " + new String(cipherText)); // 使用私钥解密数据 cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] plainText = cipher.doFinal(cipherText); System.out.println("Plain text: " + new String(plainText)); } } ``` 需要注意的是,上面的示例中使用的是Bouncy Castle作为Java加密扩展提供者,需要将Bouncy Castle库添加到项目中才能正常运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值