AES和RSA加密算法入门Demo

首先感谢博主开园精神,此博客是个人结合博主博文来进行一次个人的总结,加深学习印象。博主已经总结的非常的不错,大家可以参考博主原文博主博客地址
资料参考:
博主源码下载
百度百科


Java中有对称加密和非对称加密。
对称加密算法在加密和解密时使用的是同一个秘钥;而非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥),要么公钥加密私钥加密,要么私钥加密公钥揭秘。

下面来学习AES(对称加密)和RAS(非对称加密)
AES(高级加密标准)
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。
RAS
之所以叫 RSA算法,是因为算法的三位发明者RSA是目前最有影响力的公钥加密算法
下面提出demo,具体讲解大家参考博主原文。

客户端代码:

package base64;


public class Client {
    public static void main(String[] args){

//        rsaTest();
//     aesTest();
        rse_aesTest();
    }
    /**
     *  模拟RSA公钥加密
     *  生成的公钥就是解密需要获取的参数
     */
    private static void rsaTest(){
        try {
            String encryptText=RSAUtils.encryptByPublicKey("Beyond黄家驹");
            System.out.println("公钥:"+encryptText);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    /**
     *  模拟AES加密
     *  解密需要key和encryptText
     */
    private static void aesTest(){
     //明文
     String content="AES加密算法";
     //密钥
     String key=AESUtils.generateKey();
     //密文
     String encryptText=AESUtils.encryptData(key,content);
     System.out.println("key:"+key);
     System.out.println("密钥:"+encryptText);
    }
    /**
     *  RSA和AES结合使用
     */
    private static void rse_aesTest(){
         String text="我是要加密的信息";
         //使用AES对信息加密
        String key=AESUtils.generateKey();
        String encryptText=AESUtils.encryptData(key,text);
        //使用RSA对AES的密钥加密
        try {
            String doubleKey=RSAUtils.encryptByPublicKey(key);
            String doubleencryptText=RSAUtils.encryptByPublicKey(encryptText);
            System.out.println("要传到服务端的密文:"+doubleencryptText);
            System.out.println("要传到服务端的密钥:"+doubleKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

服务端代码:

package base64;


public class Server {

    public static void main(String[] args) {
//          rsaTest();
//        aesTest();
        rsa_aesTest();
    }

    /**
     *  解密需要的参数是客户端加密的公钥
     */
    private static void rsaTest() {
        String encryptText = "QclhVvuJJJTd/2KVotzKlTYJEDZh1x1w5KThxyttQZZVGaapyHyEpEprkjHwBlb9xpfHefTIqPscMDXlkuO+yyi09Na0PjLBMl7a8iyVM8MLMedzeU+dgSmAi629u73ZnrOBvs1Oq" +
                "UJswh2P9kqysKSN7MXL2t56KUn93iwY7I0=";
        try {
            String text = RSAUtils.decryptByPrivateKey(encryptText);
            System.out.println("明文:" + text);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void aesTest() {
        /**
         *  每一个key对应一个encryptText,只要key相同那么每一个文本生成的encryptText都是唯一的
         */
        String encryptText = "r2aEHW20cXZ9+NGNklHDwQ==";
        String key="8f9046aac19c45d0";
        try {
            String text = AESUtils.decryptData(key,encryptText);
            System.out.println("明文:" + text);
        } catch (Exception e) {e.printStackTrace();
        }
    }

    private static void rsa_aesTest(){
        //客户端发来的密文
        String doubleEnCryptText="UUAYnThYdXR58mJU9wV9crWf5vmODCDVUF0iu8CmM0Q2etKABgJfnZg1gCqV1bP5kv5IEV33TEgNM3CuoF5Ick+VI02wwJITioAfWK5cB6GB7W8SLvwZCKfRyxa" +
                "cLLKbgUtCB2AZA8BblOqZbkc8E+tY9QpausMePtzOoX4gs3w=";
        //客户端发来的密钥
        String doubleKey="LY8PY7htpWM5W2XtU58sQyE84qur1JVpOJ0zO2++Y5LSj41mrwv9JUA5611kIvXuWTDdkOXukdk1b8fbZWfmwdmlCEAOvAJ2lmo7Hwb7rfEILSzXkXnHxlxWuCkXsgZOqnK2eGVs" +
                "vFTEPqzci77vHCMyTXoGLFTPNV09AyqQgyo=";
        try {
            //RSA解密
            String key=RSAUtils.decryptByPrivateKey(doubleKey);
            String encrtptText=RSAUtils.decryptByPrivateKey(doubleEnCryptText);
            //AES解密
            String text=AESUtils.decryptData(key,encrtptText);
            //解密完成的明文
            System.out.println("明文:"+text);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

加密解密算法工具类
AESUtils.java

package base64;

import java.util.UUID;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES工具类,密钥必须是16位字符串
 */
public class AESUtils {

    /**偏移量,必须是16位字符串*/
    private static final String IV_STRING = "16-Bytes--String";

    /**
     * 默认的密钥
     */
    public static final String DEFAULT_KEY = "1bd83b249a414036";

    /**
     * 产生随机密钥(这里产生密钥必须是16位)
     */
    public static String generateKey() {
        String key = UUID.randomUUID().toString();
        key = key.replace("-", "").substring(0, 16);// 替换掉-号
        return key;
    }

    public static String encryptData(String key, String content) {
        byte[] encryptedBytes = new byte[0];
        try {
            byte[] byteContent = content.getBytes("UTF-8");
            // 注意,为了能与 iOS 统一
            // 这里的 key 不可以使用 KeyGenerator、SecureRandom、SecretKey 生成
            byte[] enCodeFormat = key.getBytes();
            SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
            byte[] initParam = IV_STRING.getBytes();
            IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
            // 指定加密的算法、工作模式和填充方式
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            encryptedBytes = cipher.doFinal(byteContent);
            // 同样对加密后数据进行 base64 编码
            return Base64Utils.encode(encryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String decryptData(String key, String content) {
        try {
            // base64 解码
            byte[] encryptedBytes = Base64Utils.decode(content);
            byte[] enCodeFormat = key.getBytes();
            SecretKeySpec secretKey = new SecretKeySpec(enCodeFormat, "AES");
            byte[] initParam = IV_STRING.getBytes();
            IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
            byte[] result = cipher.doFinal(encryptedBytes);
            return new String(result, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        String plainText = AESUtils.decryptData("F431E6FF9051DA07", "q8jHYk6LSbwC2K4zmr/wRZo8mlH0VdMzPEcAzQadTCpSrPQ/ZnTmuIvQxiLOnUXu");
        System.out.println("aes加密后: " + plainText);
    }

}

RSAUtils.java

package base64;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class RSAUtils {

    public static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJFBnk78A4CN5gBpIV/pGOGqi/CzvwjvXoj2gYXtbEIg+ZxpRrVi7Is6dwIK4+xrDr35ExaN1s4GnyF3g88z93iYpM5URhQTRJ/GGENNlozkLNARRdTJfLuJxBMZHnAGOtuNTXIcIo5/k8klllBYHTqG6xIVnjRN0vsV2UGlnW7VAgMBAAECgYBMoT9xD8aRNUrXgJ7YyFIWCzEUZN8tSYqn2tPt4ZkxMdA9UdS5sFx1/vv1meUwPjJiylnlliJyQlAFCdYBo7qzmib8+3Q8EU3MDP9bNlpxxC1go57/q/TbaymWyOk3pK2VXaX+8vQmllgRZMQRi2JFBHVoep1f1x7lSsf2TpipgQJBANJlO+UDmync9X/1YdrVaDOi4o7g3w9u1eVq9B01+WklAP3bvxIoBRI97HlDPKHx+CZXeODx1xj0xPOK3HUz5FECQQCwvdagPPtWHhHx0boPF/s4ZrTUIH04afuePUuwKTQQRijnl0eb2idBe0z2VAH1utPps/p4SpuT3HI3PJJ8MlVFAkAFypuXdj3zLQ3k89A5wd4Ybcdmv3HkbtyccBFALJgs+MPKOR5NVaSuF95GiD9HBe4awBWnu4B8Q2CYg54F6+PBAkBKNgvukGyARnQGc6eKOumTTxzSjSnHDElIsjgbqdFgm/UE+TJqMHmXNyyjqbaA9YeRc67R35HfzgpvQxHG8GN5AkEAxSKOlfACUCQ/CZJovETMmaUDas463hbrUznp71uRMk8RP7DY/lBnGGMeUeeZLIVK5X2Ngcp9nJQSKWCGtpnfLQ==";
    private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRQZ5O/AOAjeYAaSFf6Rjhqovws78I716I9oGF7WxCIPmcaUa1YuyLOncCCuPsaw69+RMWjdbOBp8hd4PPM/d4mKTOVEYUE0SfxhhDTZaM5CzQEUXUyXy7icQTGR5wBjrbjU1yHCKOf5PJJZZQWB06husSFZ40TdL7FdlBpZ1u1QIDAQAB";

    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /**
     * 加密算法RSA
     */
    private static final String KEY_ALGORITHM = "RSA";

    /**
     * 生成公钥和私钥
     *
     * @throws Exception
     */
    public static void getKeys() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        String publicKeyStr = getPublicKeyStr(publicKey);
        String privateKeyStr = getPrivateKeyStr(privateKey);

        System.out.println("公钥\r\n" + publicKeyStr);
        System.out.println("私钥\r\n" + privateKeyStr);
    }

    /**
     * 使用模和指数生成RSA公钥
     * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
     * /None/NoPadding】
     *
     * @param modulus  模
     * @param exponent 公钥指数
     * @return
     */
    public static RSAPublicKey getPublicKey(String modulus, String exponent) {
        try {
            BigInteger b1 = new BigInteger(modulus);
            BigInteger b2 = new BigInteger(exponent);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 使用模和指数生成RSA私钥
     * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
     * /None/NoPadding】
     *
     * @param modulus  模
     * @param exponent 指数
     * @return
     */
    public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
        try {
            BigInteger b1 = new BigInteger(modulus);
            BigInteger b2 = new BigInteger(exponent);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 公钥加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String encryptByPublicKey(String data) throws Exception {
        byte[] dataByte = data.getBytes();
        byte[] keyBytes = Base64Utils.decode(PUBLIC_KEY);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        // 对数据加密
        // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = dataByte.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(dataByte, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataByte, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return Base64Utils.encode(encryptedData);
    }

    /**
     * 私钥解密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String decryptByPrivateKey(String data) throws Exception {
        byte[] encryptedData = Base64Utils.decode(data);
        byte[] keyBytes = Base64Utils.decode(PRIVATE_KEY);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

        cipher.init(Cipher.DECRYPT_MODE, privateK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher
                        .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher
                        .doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData);
    }

    /**
     * 获取模数和密钥
     *
     * @return
     */
    public static Map getModulusAndKeys() {

        Map map = new HashMap();

        try {
            InputStream in = RSAUtils.class
                    .getResourceAsStream("/rsa.properties");
            Properties prop = new Properties();
            prop.load(in);

            String modulus = prop.getProperty("modulus");
            String publicKey = prop.getProperty("publicKey");
            String privateKey = prop.getProperty("privateKey");

            in.close();

            map.put("modulus", modulus);
            map.put("publicKey", publicKey);
            map.put("privateKey", privateKey);

        } catch (IOException e) {
            e.printStackTrace();
        }

        return map;
    }

    /**
     * 从字符串中加载公钥
     *
     * @param publicKeyStr 公钥数据字符串
     * @throws Exception 加载公钥时产生的异常
     */
    public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
        try {
            byte[] buffer = Base64Utils.decode(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("公钥非法");
        } catch (NullPointerException e) {
            throw new Exception("公钥数据为空");
        }
    }

    /**
     * 从字符串中加载私钥
* 加载时使用的是PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。 * * @param privateKeyStr * @return * @throws Exception */
public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception { try { byte[] buffer = Base64Utils.decode(privateKeyStr); // X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("私钥非法"); } catch (NullPointerException e) { throw new Exception("私钥数据为空"); } } public static String getPrivateKeyStr(PrivateKey privateKey) throws Exception { return new String(Base64Utils.encode(privateKey.getEncoded())); } public static String getPublicKeyStr(PublicKey publicKey) throws Exception { return new String(Base64Utils.encode(publicKey.getEncoded())); } public static void main(String[] args) throws Exception { getKeys(); } }

Base64Utils.java

package base64;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import it.sauronsoftware.base64.Base64;

/** */
/**
 * 

* BASE64编码解码工具包 *

*

* 依赖javabase64-1.3.1.jar *

* * @author jun * @date 2012-5-19 * @version 1.0 */
public class Base64Utils { /** */ /** * 文件读取缓冲区大小 */ private static final int CACHE_SIZE = 1024; /** */ /** *

* BASE64字符串解码为二进制数据 *

* * @param base64 * @return * @throws Exception */
public static byte[] decode(String base64) throws Exception { return Base64.decode(base64.getBytes()); } public static String decode(byte[] b) { return new String(Base64.decode(b)); } /** */ /** *

* 二进制数据编码为BASE64字符串 *

* * @param bytes * @return * @throws Exception */
public static String encode(byte[] bytes) throws Exception { return new String(Base64.encode(bytes)); } /** */ /** *

* 将文件编码为BASE64字符串 *

*

* 大文件慎用,可能会导致内存溢出 *

* * @param filePath * 文件绝对路径 * @return * @throws Exception */
public static String encodeFile(String filePath) throws Exception { byte[] bytes = fileToByte(filePath); return encode(bytes); } /** */ /** *

* BASE64字符串转回文件 *

* * @param filePath * 文件绝对路径 * @param base64 * 编码字符串 * @throws Exception */
public static void decodeToFile(String filePath, String base64) throws Exception { byte[] bytes = decode(base64); byteArrayToFile(bytes, filePath); } /** */ /** *

* 文件转换为二进制数组 *

* * @param filePath * 文件路径 * @return * @throws Exception */
public static byte[] fileToByte(String filePath) throws Exception { byte[] data = new byte[0]; File file = new File(filePath); if (file.exists()) { FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(2048); byte[] cache = new byte[CACHE_SIZE]; int nRead = 0; while ((nRead = in.read(cache)) != -1) { out.write(cache, 0, nRead); out.flush(); } out.close(); in.close(); data = out.toByteArray(); } return data; } /** */ /** *

* 二进制数据写文件 *

* * @param bytes * 二进制数据 * @param filePath * 文件生成目录 */
public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception { InputStream in = new ByteArrayInputStream(bytes); File destFile = new File(filePath); if (!destFile.getParentFile().exists()) { destFile.getParentFile().mkdirs(); } destFile.createNewFile(); OutputStream out = new FileOutputStream(destFile); byte[] cache = new byte[CACHE_SIZE]; int nRead = 0; while ((nRead = in.read(cache)) != -1) { out.write(cache, 0, nRead); out.flush(); } out.close(); in.close(); } }

Demo源码

你可能感兴趣的:(数据结构和算法)