JAVA加解密

【前言】java

本文簡單的介紹了加密技術相關概念,最後總結了java中現有的加密技術以及使用方法和例子

【最簡單的加密】算法

1.簡單的概念apache

明文:加密前的信息數組

密文:機密後的信息app

算法:加密或解密的算法dom

密鑰:算法使用的鑰匙(讀做miyao,正確應該是miyue,可是你們都讀miyao)ide

 

2.簡單的例子函數

將123456每位數字都加1後獲得234567,工具

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

 

3.對稱加密和非對稱加密

以上爲例,

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

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

其中加密算法(+)和解密算法(-)相對稱,這種加密算法就稱做對稱加密,

一樣,若是加密算法和解密算法不對稱就稱之爲非對稱加密。

 

4.算法舉例

衆多的加密手段大體能夠分爲單項加密和雙向加密。單項加密指經過對數據進行摘要計算生成密文,密文不可逆推還原,好比有Base6四、MD五、SHA等;雙向加密則相反,指能夠把密文逆推還原成明文,其中雙向加密又分爲對稱加密和非對稱加密。對稱加密是指數據使用者必須擁有一樣的密鑰才能夠進行加密解密,就像你們共同約定了一組暗號同樣,對稱加密的手段有DES、3DES、AES、IDEA、RC四、RC5等;而非對稱加密相對於對稱加密而言,無需擁有同一組密鑰,它是一種「信息公開的密鑰交換協議」。非對稱加密須要公開密鑰和私有密鑰兩組密鑰,公開密鑰和私有密鑰是配對起來的,也就是說使用公開密鑰進行數據加密,只有對應的私有密鑰才能進行解密。此類的加密手段有RSA、DSA等

對稱加密算法:DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法,AES算法

非對稱加密算法:RSA、Elgamal、揹包算法、Rabin、D-H、ECC。

經典的哈希算法:MD二、MD四、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);
    }
}
顯示代碼
相關文章
相關標籤/搜索