• JAVA加解密


    【前言】

    本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及使用方法和例子

    【最简单的加密】

    1.简单的概念

    明文:加密前的信息

    密文:机密后的信息

    算法:加密或解密的算法

    密钥:算法使用的钥匙(读作miyao,正确应该是miyue,但是大家都读miyao)

    2.简单的例子

    将123456每位数字都加1后得到234567,

    其中123456就是明文,234567就是密文,加密密钥就是1,加密算法是每位加

    3.对称加密和非对称加密

    以上为例,

    123456-->234567的加密密钥就是1,加密算法是每位+

    234567-->123456的解密密钥也是1,解密算法是每位-

    其中加密算法(+)和解密算法(-)相对称,这种加密算法就称作对称加密,

    同样,如果加密算法和解密算法不对称就称之为非对称加密。

    4.算法举例

    众多的加密手段大致可以分为单项加密和双向加密。单项加密指通过对数据进行摘要计算生成密文,密文不可逆推还原,比如有Base64、MD5、SHA等;双向加密则相反,指可以把密文逆推还原成明文,其中双向加密又分为对称加密和非对称加密。对称加密是指数据使用者必须拥有同样的密钥才可以进行加密解密,就像大家共同约定了一组暗号一样,对称加密的手段有DES、3DES、AES、IDEA、RC4、RC5等;而非对称加密相对于对称加密而言,无需拥有同一组密钥,它是一种“信息公开的密钥交换协议”。非对称加密需要公开密钥和私有密钥两组密钥,公开密钥和私有密钥是配对起来的,也就是说使用公开密钥进行数据加密,只有对应的私有密钥才能进行解密。此类的加密手段有RSA、DSA等

    对称加密算法:DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法,AES算法

    非对称加密算法:RSA、Elgamal、背包算法、Rabin、D-H、ECC。

    经典的哈希算法:MD2、MD4、MD5 和 SHA-1(目的是将任意长输入通过算法变为固定长输出,且保证输入变化一点输出都不同,且不能反向解密)

    5.经典算法实现

      5.1:AES算法

    package com.meng.study.security;
    
    import java.security.SecureRandom;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    public class AESUtil {
    
        /**
         * AES加密
         * 
         * @param content
         *            待加密的内容
         * @param encryptKey
         *            加密密钥
         * @return 加密后的byte[]
         * @throws Exception
         */
        public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(encryptKey.getBytes());
            kgen.init(128, random);
            SecretKey secretKey = new SecretKeySpec(kgen.generateKey().getEncoded(), "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return cipher.doFinal(content.getBytes("UTF-8"));
        }
    
        /**
         * AES加密为base 64 code
         * 
         * @param content
         *            待加密的内容
         * @param encryptKey
         *            加密密钥
         * @return 加密后的base 64 code
         * @throws Exception
         */
        public static String aesEncrypt(String content, String encryptKey) throws Exception {
            return BASE64Util.base64Encode(aesEncryptToBytes(content, encryptKey));
        }
    
        /**
         * AES解密
         * 
         * @param encryptBytes
         *            待解密的byte[]
         * @param decryptKey
         *            解密密钥
         * @return 解密后的String
         * @throws Exception
         */
        public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(decryptKey.getBytes());
            kgen.init(128, random);
            SecretKey secretKey = new SecretKeySpec(kgen.generateKey().getEncoded(), "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] decryptBytes = cipher.doFinal(encryptBytes);
            return new String(decryptBytes);
        }
    
        /**
         * 将base 64 code AES解密
         * 
         * @param encryptStr
         *            待解密的base 64 code
         * @param decryptKey
         *            解密密钥
         * @return 解密后的string
         * @throws Exception
         */
        public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
            return aesDecryptByBytes(BASE64Util.base64Decode(encryptStr), decryptKey);
        }
    }
    显示代码

      

      5.2:3DES算法

    package com.meng.study.security;
    
    import java.io.UnsupportedEncodingException;
    
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    import org.apache.log4j.Logger;
    
    import com.meng.study.cache.GuavaCacheUtil;
    
    /**
     * 
     * @author zhenbinmeng
     *
     */
    public class DESUtil {
        private static Logger logger = Logger.getLogger(DESUtil.class);
    
        // 定义加密算法,DESede(即3DES)
        private static final String DESede = "DESede";
    
        private static final String PASSWORD_CRYPT_KEY = "2015mengzhenbinStudyForSecurity@DESede";
    
        /**
         * 加密方法
         * 
         * @param src
         *            源数据的字节数组
         * @return
         */
        public static byte[] encryptMode(byte[] src) {
            try {
                SecretKey deskey = new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); // 生成密钥
                Cipher c1 = Cipher.getInstance(DESede); // 实例化负责加密/解密的Cipher工具类
                c1.init(Cipher.ENCRYPT_MODE, deskey); // 初始化为加密模式
                return c1.doFinal(src);
            } catch (Exception e) {
                logger.error("DesUtil.encryptMode error", e);
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 加密方法(BASE64编码返回)
         * 
         * @param src
         *            源数据的字节数组
         * @return
         */
        public static String encryptModeBase64(byte[] src) {
            try {
                SecretKey deskey = new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); // 生成密钥
                Cipher c1 = Cipher.getInstance(DESede); // 实例化负责加密/解密的Cipher工具类
                c1.init(Cipher.ENCRYPT_MODE, deskey); // 初始化为加密模式
                return BASE64Util.base64Encode(c1.doFinal(src));
            } catch (Exception e) {
                logger.error("DesUtil.encryptMode error", e);
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 解密函数
         * 
         * @param src
         *            密文的字节数组
         * @return
         */
        public static byte[] decryptMode(byte[] src) {
            try {
                SecretKey deskey = new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede);
                Cipher c1 = Cipher.getInstance(DESede);
                c1.init(Cipher.DECRYPT_MODE, deskey); // 初始化为解密模式
                return c1.doFinal(src);
            } catch (Exception e) {
                logger.error("DesUtil.decryptMode error", e);
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 解密函数(BASE64解码后解密)
         * 
         * @param src
         *            密文的字节数组
         * @return
         */
        public static String decryptModeBase64(String src) {
            try {
                SecretKey deskey = new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede);
                Cipher c1 = Cipher.getInstance(DESede);
                c1.init(Cipher.DECRYPT_MODE, deskey); // 初始化为解密模式
                return new String(c1.doFinal(BASE64Util.base64Decode(src)));
            } catch (Exception e) {
                logger.error("DesUtil.decryptMode error", e);
                e.printStackTrace();
            }
            return null;
        }
    
        /*
         * 根据字符串生成密钥字节数组
         * 
         * @param keyStr 密钥字符串
         * 
         * @return
         * 
         * @throws UnsupportedEncodingException
         */
        public static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException {
            byte[] key = new byte[24]; // 声明一个24位的字节数组,默认里面都是0
            byte[] temp = keyStr.getBytes("UTF-8"); // 将字符串转成字节数组
            /*
             * 执行数组拷贝 System.arraycopy(源数组,从源数组哪里开始拷贝,目标数组,拷贝多少位)
             */
            if (key.length > temp.length) {
                // 如果temp不够24位,则拷贝temp数组整个长度的内容到key数组中
                System.arraycopy(temp, 0, key, 0, temp.length);
            } else {
                // 如果temp大于24位,则拷贝temp数组24个长度的内容到key数组中
                System.arraycopy(temp, 0, key, 0, key.length);
            }
            return key;
        }
    
    }
    显示代码

      5.3:MD5算法

    package com.meng.study.security;
    
    import java.security.MessageDigest;
    
    public class MD5Util {
        /**
         * 获取byte[]的md5值
         * 
         * @param bytes
         *            byte[]
         * @return md5
         * @throws Exception
         */
        public static byte[] md5(byte[] bytes) throws Exception {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(bytes);
            return md.digest();
        }
    
        /**
         * 获取字符串md5值
         * 
         * @param msg
         * @return md5
         * @throws Exception
         */
        public static byte[] md5(String msg) throws Exception {
            return md5(msg.getBytes());
        }
    
        /**
         * 获取字符串md5值
         * 
         * @param msg
         * @return md5
         * @throws Exception
         */
        public static String md5Hex(String msg) throws Exception {
            byte[] messageDigest = md5(msg.getBytes());
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();
        }
    
        /**
         * 结合base64实现md5加密
         * 
         * @param msg
         *            待加密字符串
         * @return 获取md5后转为base64
         * @throws Exception
         */
        public static String md5Base64(String msg) throws Exception {
            return BASE64Util.base64Encode(md5(msg));
        }
    }
    显示代码

      5.4:SHA算法

    package com.meng.study.security;
    
    import java.security.MessageDigest;
    
    public class SHAUtil {
        
        public static String SHA1(String decript) {
            try {
                MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
                digest.update(decript.getBytes());
                byte messageDigest[] = digest.digest();
                // Create Hex String
                StringBuffer hexString = new StringBuffer();
                // 字节数组转换为 十六进制 数
                for (int i = 0; i < messageDigest.length; i++) {
                    String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                    if (shaHex.length() < 2) {
                        hexString.append(0);
                    }
                    hexString.append(shaHex);
                }
                return hexString.toString();
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "";
        }
    
        public static String SHA(String decript) {
            try {
                MessageDigest digest = java.security.MessageDigest.getInstance("SHA");
                digest.update(decript.getBytes());
                byte messageDigest[] = digest.digest();
                // Create Hex String
                StringBuffer hexString = new StringBuffer();
                // 字节数组转换为 十六进制 数
                for (int i = 0; i < messageDigest.length; i++) {
                    String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                    if (shaHex.length() < 2) {
                        hexString.append(0);
                    }
                    hexString.append(shaHex);
                }
                return hexString.toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "";
        }
    }
    显示代码

      5.5:RSA算法

    package com.meng.study.security;
    
    import java.math.BigInteger;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.RSAPrivateKeySpec;
    import java.security.spec.RSAPublicKeySpec;
    import java.util.HashMap;
    
    import javax.crypto.Cipher;
    
    public class RSAUtil {
    
        /**
         * 生成公钥和私钥
         * 
         * @throws NoSuchAlgorithmException
         *
         */
        public static HashMap<String, Object> getKeys() throws NoSuchAlgorithmException {
            HashMap<String, Object> map = new HashMap<String, Object>();
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
            keyPairGen.initialize(1024);
            KeyPair keyPair = keyPairGen.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            map.put("public", publicKey);
            map.put("private", privateKey);
            return map;
        }
    
        /**
         * 使用模和指数生成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
         * @param publicKey
         * @return
         * @throws Exception
         */
        public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 模长
            int key_len = publicKey.getModulus().bitLength() / 8;
            // 加密数据长度 <= 模长-11
            String[] datas = splitString(data, key_len - 11);
            String mi = "";
            // 如果明文长度大于模长-11则要分组加密
            for (String s : datas) {
                mi += bcd2Str(cipher.doFinal(s.getBytes()));
            }
            return mi;
        }
    
        /**
         * 私钥解密
         * 
         * @param data
         * @param privateKey
         * @return
         * @throws Exception
         */
        public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 模长
            int key_len = privateKey.getModulus().bitLength() / 8;
            byte[] bytes = data.getBytes();
            byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
            // 如果密文长度大于模长则要分组解密
            String ming = "";
            byte[][] arrays = splitArray(bcd, key_len);
            for (byte[] arr : arrays) {
                ming += new String(cipher.doFinal(arr));
            }
            return ming;
        }
    
        /**
         * ASCII码转BCD码
         * 
         */
        public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
            byte[] bcd = new byte[asc_len / 2];
            int j = 0;
            for (int i = 0; i < (asc_len + 1) / 2; i++) {
                bcd[i] = asc_to_bcd(ascii[j++]);
                bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
            }
            return bcd;
        }
    
        public static byte asc_to_bcd(byte asc) {
            byte bcd;
    
            if ((asc >= '0') && (asc <= '9'))
                bcd = (byte) (asc - '0');
            else if ((asc >= 'A') && (asc <= 'F'))
                bcd = (byte) (asc - 'A' + 10);
            else if ((asc >= 'a') && (asc <= 'f'))
                bcd = (byte) (asc - 'a' + 10);
            else
                bcd = (byte) (asc - 48);
            return bcd;
        }
    
        /**
         * BCD转字符串
         */
        public static String bcd2Str(byte[] bytes) {
            char temp[] = new char[bytes.length * 2], val;
    
            for (int i = 0; i < bytes.length; i++) {
                val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
                temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
    
                val = (char) (bytes[i] & 0x0f);
                temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
            }
            return new String(temp);
        }
    
        /**
         * 拆分字符串
         */
        public static String[] splitString(String string, int len) {
            int x = string.length() / len;
            int y = string.length() % len;
            int z = 0;
            if (y != 0) {
                z = 1;
            }
            String[] strings = new String[x + z];
            String str = "";
            for (int i = 0; i < x + z; i++) {
                if (i == x + z - 1 && y != 0) {
                    str = string.substring(i * len, i * len + y);
                } else {
                    str = string.substring(i * len, i * len + len);
                }
                strings[i] = str;
            }
            return strings;
        }
    
        /**
         * 拆分数组
         */
        public static byte[][] splitArray(byte[] data, int len) {
            int x = data.length / len;
            int y = data.length % len;
            int z = 0;
            if (y != 0) {
                z = 1;
            }
            byte[][] arrays = new byte[x + z][];
            byte[] arr;
            for (int i = 0; i < x + z; i++) {
                arr = new byte[len];
                if (i == x + z - 1 && y != 0) {
                    System.arraycopy(data, i * len, arr, 0, y);
                } else {
                    System.arraycopy(data, i * len, arr, 0, len);
                }
                arrays[i] = arr;
            }
            return arrays;
        }
    }
    显示代码

      5.6:Base64算法

    package com.meng.study.security;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
    @SuppressWarnings("restriction")
    public class BASE64Util {
    
        /**
         * base 64 encode
         * 
         * @param bytes
         *            待编码的byte[]
         * @return 编码后的base 64 code
         */
        public static String base64Encode(byte[] bytes) {
            return new BASE64Encoder().encode(bytes);
        }
    
        /**
         * base 64 decode
         * 
         * @param base64Code
         *            待解码的base 64 code
         * @return 解码后的byte[]
         * @throws Exception
         */
        public static byte[] base64Decode(String base64Code) throws Exception {
            return new BASE64Decoder().decodeBuffer(base64Code);
        }
    }
    显示代码

      5.7:测试代码

    package com.meng.study.security;
    
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.util.HashMap;
    
    
    /**
     * 编码工具类 1.将byte[]转为各种进制的字符串 2.base 64 encode 3.base 64 decode
     * 
     * @author uikoo9
     * @version 0.0.5.20140601
     */
    public class EncodeUtilTest {
    
        public static void main(String[] args) throws Exception {
            String msg = "我爱你";
            System.out.println("转换前:" + msg);
            //==Base64==
            String base64Str = BASE64Util.base64Encode(msg.getBytes());
            System.out.println("Base64转换后:" + base64Str);
            System.out.println("Base64解码后:" + new String(BASE64Util.base64Decode(base64Str)));
            //==Md5==
            String md5Base64Str = MD5Util.md5Base64(msg);
            System.out.println("Md5后Base编码转换后:" + md5Base64Str);
            //==Des==
            byte[] des = DESUtil.encryptMode(msg.getBytes());
            System.out.println("【DES加密后】:" + new String(des));
            byte[] myMsgArr = DESUtil.decryptMode(des);
            System.out.println("【DES解密后】:" + new String(myMsgArr));
            String desBase64Str = DESUtil.encryptModeBase64(msg.getBytes());
            System.out.println("Des后Base64编码转换后:" + desBase64Str);
            System.out.println("Base64解码后Des转换后:" + new String(DESUtil.decryptModeBase64(desBase64Str)));
            //==Aes==
             String aesKey = "123456";
            String aesEnStr= AESUtil.aesEncrypt(msg,aesKey);
            System.out.println("【AES加密Base64编码后】:" +aesEnStr);
            String aesDeStr = AESUtil.aesDecrypt(aesEnStr,aesKey);
            System.out.println("【Base64解码AES解密后】:" +aesDeStr);
            //==Rsa==
            HashMap<String, Object> keys = RSAUtil.getKeys();
            RSAPublicKey publicKey = (RSAPublicKey) keys.get("public");
            RSAPrivateKey privateKey =  (RSAPrivateKey) keys.get("private");
            RSAPublicKey pubKey = RSAUtil.getPublicKey(publicKey.getModulus().toString(), publicKey.getPublicExponent().toString());
            RSAPrivateKey priKey = RSAUtil.getPrivateKey(privateKey.getModulus().toString(), privateKey.getPrivateExponent().toString());
            String rsaEnStr = RSAUtil.encryptByPublicKey(msg, pubKey);
            System.out.println("【RSA公钥加密后】:" +rsaEnStr);
            String rsaDeStr= RSAUtil.decryptByPrivateKey(rsaEnStr, priKey);
            System.out.println("【RSA私钥解密后】:" +rsaDeStr);
        }
    }
    显示代码

     

     

     

     

  • 相关阅读:
    MarkDown学习记录
    AngularJS+Ionic开发-2.项目结构介绍
    【二分+贪心+倍增】【NOIP2012】疫情控制
    【考试总结】NOIP模拟 test11-1
    【考试总结】NOIP模拟 test10-27
    【考试总结】AHSOFNU&QZQZ test10-25
    【差分+二分答案】【NOIP2012】借教室
    【动态规划】【NOIP2015】子串
    【高精度+贪心】【NOIP2012】国王游戏
    ICPC Central Russia Regional Contest (CRRC 19)题解
  • 原文地址:https://www.cnblogs.com/NullPointException/p/5054082.html
Copyright © 2020-2023  润新知