阅读794 返回首页    go 阿里云 go 技术社区[云栖]


JAVA加密与解密

摘要算法
摘要算法主要包含三大类型:MD算法,SHA算法,已经基于KEY的MAC算法

MD算法
MD算法主要有MD2,MD3,MD4以及最常用的MD5。
SHA算法主要有SHA-1,SHA-224,SHA-256,SHA-384,SHA-512。
MAC算法是基于哈西散列算法(MD系列或者SHA系列等),在HASH散列进行KEY加密

JAVA密码体系对主流摘要算法的支持
screenshot

MD5算法的调用示例

package com.rcl.platform.demo;

import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class ProviderTest {

    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        messageDigest.update("我是MD".getBytes());
        byte [] md5 = messageDigest.digest();
        System.out.println(byte2HexStr(md5));


        Security.addProvider(new BouncyCastleProvider());//注册BouncyCastleProvider
        Provider provider = Security.getProvider("BC");
        messageDigest = MessageDigest.getInstance("MD4", provider);
        messageDigest.update("我是MD".getBytes());
        byte [] md4 = messageDigest.digest();
        System.out.println(byte2HexStr(md4));

        messageDigest = MessageDigest.getInstance("SHA512");//调用SHA算法
        messageDigest.update("我是SHA".getBytes());
        byte [] sha512 = messageDigest.digest();
        System.out.println(byte2HexStr(sha512));

        SecretKey secretKey = new SecretKeySpec("woshikey".getBytes(), "HmacSHA512");//HMAC算法调用
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        byte [] hmacSHA224 = mac.doFinal("我是SHA".getBytes());
        System.out.println(byte2HexStr(hmacSHA224));


    }

    public static String byte2HexStr(byte[] b) {    
        String stmp="";    
        StringBuilder sb = new StringBuilder("");    
        for (int n=0;n<b.length;n++) {    
            stmp = Integer.toHexString(b[n] & 0xFF);    
            sb.append((stmp.length()==1)? "0"+stmp : stmp);    
            sb.append("");    
        }    
        return sb.toString().toLowerCase().trim();    
    }  


}

执行结果

f610c6a17a31eec9d36c5ef646149ea6
d40694ae1650fdb9bfe807833a3b6c89
e7046e9687398575eadf7eadf5854103b9a98fbedc1333cd553bc288b3518f997884cb7b827bc789b973d2dcf818253359133361602518d045d2cc2ff0eb0871
4e8f13266500448abf27d54aeaeb7825ed62c62d6c40633b3066faf10f6b3b9e933ec2e335b9ab5388da1c09161bf75a2e6fdac7f01ebeb1910f187824fc2562

对称加密
1、对称加密体制要求加密与解密使用同一个共享密钥,解密是加密的逆运算,对于共享密钥,要求通讯双方在通讯前协商共享密钥并妥善保存
2、对称加密体制分为两种:一种是对明文的单个位(或单个字节)进行加密,称为流密码;另一种是明文划分为不同的组(或块),分别对组加密,称为分组加密
3、常用的为分组加密,分组加密的安全性与分组长度有关,但是一般默认的长度为56位
4、对称加密有DES,DESede,AES,Blowfish,RC2,RC4,IDEA。相关概念可以百度百科

分组密码工作模式
1、电子密码本模式ECB:每次加密均产生独立的密文分组,每组加密的结果不会对其他组产生影响,无初始化向量
2、密文连接模式CBC:目前应用最广泛的工作模式,组明文加密前需先与前面的组密文进行异或运算(XOR)在加密
3、密文反馈模式CFB:类似于自同步流密码,分组加密后,按8位分组将密文和明文进行位移异或得到输出并同时反馈回位移寄存器
4、输出反馈模式OFB:和CFB类似,不过OFB用的是前一个n位密文输出分组反馈回位移寄存器
5、计数器模式CTR:将计数器从初始值开始计数,所得到的值发送给分组密码,随着计数器的增加,分组密码算法输出连续的分组来构成一个位串,该串用来与明文分组进行异或运算。在AES中,经常使用的是CBC和CTR,CTR用的比CBC更多些

填充模式
对于明文进行分组,最后一个分组长度不满足默认长度,称为短分组。对于短分组如何处理,需要使用到填充模式。

Java对对称加密算法的支持
DES
screenshot
DESede
screenshot
AES
screenshot
IDEA
screenshot
PBE
screenshot
示例代码

package com.rcl.platform.demo;

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public abstract class DESCoder {

    public static void main(String[] args) throws Exception {
        String inputStr = "我是加密内容";
        byte[] inputData = inputStr.getBytes();
        byte[] key = "key123321".getBytes();

        inputData = encrypt(inputData, key);
        byte[] outputData = decrypt(inputData, key);
        System.out.println("解密后:\t" + new String(outputData));

        byte [] iv = "11111111".getBytes();
        inputData = encryptCBC(inputStr.getBytes(), key, iv);
        outputData = decryptCBC(inputData, key, iv);
        System.out.println("解密后   CBC模式:\t" + new String(outputData));


        byte[] data = encrypt(inputStr.getBytes(), "snowolf1", "11111111".getBytes());//SALT必须为8字节
        byte[] output = decrypt(data, "snowolf1", "11111111".getBytes());
        System.out.println("PBE解密后:\t" + new String(output));
    }

    private static Key toKey(byte[] key) throws Exception {
        // 实例化DES密钥材料
        DESKeySpec dks = new DESKeySpec(key);
        // 实例化秘密密钥工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        // 生成秘密密钥
        SecretKey secretKey = keyFactory.generateSecret(dks);
        return secretKey;
    }

    /**
     * 转换密钥
     * 
     * @param key
     *            二进制密钥
     * @return Key 密钥
     * @throws Exception
     */
    private static Key toKeyDESede(byte[] key) throws Exception {

        // 实例化DES密钥材料
        DESedeKeySpec dks = new DESedeKeySpec(key);

        // 实例化秘密密钥工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");

        // 生成秘密密钥
        SecretKey secretKey = keyFactory.generateSecret(dks);

        return secretKey;
    }

    /**
     * 转换密钥
     * 
     * @param key
     *            二进制密钥
     * @return Key 密钥
     * @throws Exception
     */
    private static Key toKeyAESOrIDEA(byte[] key) throws Exception {
        // 实例化AES密钥材料
        SecretKey secretKey = new SecretKeySpec(key, "AES");
//      SecretKey secretKey = new SecretKeySpec(key, "IDEA");

        return secretKey;
    }

    /**
     * 转换密钥
     * 
     * @param password
     *            密码
     * @return Key 密钥
     * @throws Exception
     */
    private static Key toKeyPBE(String password) throws Exception {

        // 密钥材料转换
        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());

        // 实例化
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndTripleDES");

        // 生成密钥
        SecretKey secretKey = keyFactory.generateSecret(keySpec);

        return secretKey;
    }

    /**
     * 解密
     * 
     * @param data
     *            待解密数据
     * @param key
     *            密钥
     * @param ivParameterSpec
     *            加密向量
     * @return byte[] 解密数据
     * @throws Exception
     */
    public static byte[] decryptCBC(byte[] data, byte[] key, byte [] ivParameterSpec) throws Exception {
        // 还原密钥
        Key k = toKey(key);
        // 实例化
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        //初始化加密向量,CBC模式必须参数,参数最少8位
        IvParameterSpec param = new IvParameterSpec(ivParameterSpec);//CBC
        // 初始化,设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, k, param);
        // 执行操作
        return cipher.doFinal(data);
    }

    /**
     * 加密
     * 
     * @param data
     *            待加密数据
     * @param key
     *            密钥
     * @param ivParameterSpec
     *            加密向量
     * @return byte[] 加密数据
     * @throws Exception
     */
    public static byte[] encryptCBC(byte[] data, byte[] key, byte [] ivParameterSpec) throws Exception {
        // 还原密钥
        Key k = toKey(key);
        // 实例化
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        IvParameterSpec param = new IvParameterSpec(ivParameterSpec);//CBC
        // 初始化,设置为加密模式
        cipher.init(Cipher.ENCRYPT_MODE, k, param);
        // 执行操作
        return cipher.doFinal(data);
    }

    /**
     * 解密
     * 
     * @param data
     *            待解密数据
     * @param key
     *            密钥
     * @return byte[] 解密数据
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        // 还原密钥
        Key k = toKey(key);
        // 实例化
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5PADDING");
        // 初始化,设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, k);
        // 执行操作
        return cipher.doFinal(data);
    }

    /**
     * 加密
     * 
     * @param data
     *            待加密数据
     * @param key
     *            密钥
     * @return byte[] 加密数据
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
        // 还原密钥
        Key k = toKey(key);
        // 实例化
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5PADDING");
        // 初始化,设置为加密模式
        cipher.init(Cipher.ENCRYPT_MODE, k);
        // 执行操作
        return cipher.doFinal(data);
    }


    /**
     * 加密
     * 
     * @param data
     *            数据
     * @param password
     *            密码
     * @param salt
     *            盐
     * @return byte[] 加密数据
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, String password, byte[] salt)
            throws Exception {

        // 转换密钥
        Key key = toKeyPBE(password);

        // 实例化PBE参数材料
        PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);

        // 实例化
        Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");

        // 初始化
        cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);

        // 执行操作
        return cipher.doFinal(data);

    }

    /**
     * 解密
     * 
     * @param data
     *            数据
     * @param password
     *            密码
     * @param salt
     *            盐
     * @return byte[] 解密数据
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, String password, byte[] salt)
            throws Exception {

        // 转换密钥
        Key key = toKeyPBE(password);

        // 实例化PBE参数材料
        PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);

        // 实例化
        Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");

        // 初始化
        cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

        // 执行操作
        return cipher.doFinal(data);

    }
}

执行结果

解密后:  我是加密内容
解密后   CBC模式:  我是加密内容
PBE解密后:   我是加密内容

最后更新:2017-10-30 10:03:48

  上一篇:go  阿里云双11访谈之数据智能
  下一篇:go  AI翻译离无障碍交流有多远