在互联网项目、应用中,由于应用在外网的暴露,使得应用的安全要求更高,为了防止敏感数据被恶意劫取、恶意篡改。应用敏感数据必须加密,来保证对用户隐私、重要数据的安全性。下面来看看非对称加密RSA算法的实现:
package file; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class RsaTest { /** * 1、先初始化 KeyPairGenerator,并生成KeyPair,得到KeyPair * @return * @throws NoSuchAlgorithmException */ public static KeyPair getKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator instance = KeyPairGenerator.getInstance("RSA"); instance.initialize(1024); KeyPair keyPair = instance.generateKeyPair(); return keyPair; } /** * 2、通过KeyPair获得公钥 * 为了方便保存,通过Base64 编码将其转换为String类型 * @param keyPair * @return */ public static String getPublicKey(KeyPair keyPair) { PublicKey publicKey = keyPair.getPublic(); byte[] encoded = publicKey.getEncoded(); BASE64Encoder base64Encoder = new BASE64Encoder(); String encode = base64Encoder.encode(encoded); return encode; } /** * 2、通过KeyPair获得私钥 * 为了方便保存,通过Base64 编码将其转换为String类型 * @param keyPair * @return */ public static String getPrivateKey(KeyPair keyPair) { PrivateKey privateKey = keyPair.getPrivate(); byte[] encoded = privateKey.getEncoded(); BASE64Encoder base64Encoder = new BASE64Encoder(); String encode = base64Encoder.encode(encoded); return encode; } /** * 将String类型的公钥转换为PublicKey对象 * 先通过Base64解码,公钥需要转换成为X509EncodedKeySpec对象,然后通过KeyFactory生成PublicKey对象。 * @param publicKeyStr * @return * @throws IOException * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PublicKey string2PublicKey(String publicKeyStr) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] decodeBuffer = base64Decoder.decodeBuffer(publicKeyStr); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodeBuffer); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; } /** * 将String类型的私钥转换为PrivateKey对象 * 先通过Base64解码,私钥需要转换成为PKCS8EncodedKeySpec对象,然后通过KeyFactory生成PrivateKey对象。 * @param privateKeyStr * @return * @throws IOException * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PrivateKey string2PrivateKey(String privateKeyStr) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] decodeBuffer = base64Decoder.decodeBuffer(privateKeyStr); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodeBuffer); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey ; } /** * 使用公钥加密 * 首先获得RSA算法的Cipher实例,然后传入加密模式Cipher.ENCRYPT_MODE和公钥PublicKey类的实例进行初始化, * 通过doFinal方法获得加密字节流 * @param content * @param publicKey * @return * @throws NoSuchAlgorithmException * @throws NoSuchPaddingException * @throws InvalidKeyException * @throws IllegalBlockSizeException * @throws BadPaddingException */ public static byte[] publicEncrypt(byte[] content,PublicKey publicKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE,publicKey); byte[] bytes = cipher.doFinal(content); return bytes; } /** * 使用私钥解密 * 首先获得RSA算法的Cipher实例,然后传入解密模式Cipher.DECRYPT_MODE和PrivateKey类的实例, * 通过doFinal方法获得解密字节流 * @param content * @param privateKey * @return * @throws NoSuchAlgorithmException * @throws NoSuchPaddingException * @throws InvalidKeyException * @throws IllegalBlockSizeException * @throws BadPaddingException */ public static byte[] privateDecrypt(byte[] content,PrivateKey privateKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] bytes = cipher.doFinal(content); return bytes; } public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, IOException { KeyPair keyPair = RsaTest.getKeyPair(); String publicKey = RsaTest.getPublicKey(keyPair); PublicKey publicKeyObj = RsaTest.string2PublicKey(publicKey); String privateKey = RsaTest.getPrivateKey(keyPair); PrivateKey privateKeyObj = RsaTest.string2PrivateKey(privateKey); String resource = "你好,这是RSA算法"; byte[] publicEncrypt = RsaTest.publicEncrypt(resource.getBytes("utf-8"), publicKeyObj); System.out.println("加密后的字符串:"+new String(publicEncrypt,"utf-8")); byte[] decode = RsaTest.privateDecrypt(publicEncrypt, privateKeyObj); System.out.println("解密后的字符串:"+new String(decode,"utf-8")); System.out.println("私钥:"+privateKey); System.out.println("公钥:"+publicKey); } }
如果使用1024初始化KeyPairGenerator,RSA加密后的密文长度为1024位,即128个字节,此时明文的最大长度不能超过117个字节,超过117个字节要使用2048的keysize来初始化KeyPairGenerator,超过245个字节,则需要使用更高位数的keysize,RSA的位数越高,其产生秘钥及加密、解密的速度越慢。这是基于大素数非对称加密的缺陷。