注意:本节内容主要参考自《Java加密与解密的艺术(第2版)》第7章“初等加密算法--对称加密算法”

7.1、对称加密算法

特点:

  • 加密与解密使用同一个密钥
  • 是使用最广的算法

常见对称加密算法:

  • DES(已被破解,但是是其他对称算法的基石)
  • DESede(处理速度慢、加密耗时,也不常用)
  • AES(DES的替代者,最常用)
  • IDEA(目前常用的电子邮件加密算法)
  • PBE(对已知对称加密进行包装)

7.2、DES(已破解,基本不用)

实现方式:

  • JDK(提供56位密钥,提供PKCS5Padding的填充模式)
  • Bouncy Castle(提供64位密钥,提供PKCS7Padding的填充模式)

由于DES已被破解,现在企业基本已不再使用,此处只列出基于JDK实现的代码。

package com.util.des;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;

/**
 * 基于JDK的DES算法
 */
public class DESJDK {
    private static final String ENCODING = "UTF-8";
    private static final String KEY_ALGORITHM = "DES";//产生密钥的算法
    private static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";//加解密算法 格式:算法/工作模式/填充模式

    /**
     * 产生密钥
     */
    public static byte[] getKey() throws NoSuchAlgorithmException{
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
        keyGenerator.init(56);//初始化密钥长度
        SecretKey key =keyGenerator.generateKey();//产生密钥
        return key.getEncoded();
    }

    /**
     * 还原密钥:二进制字节数组转换为十六进制字符串
     */
    public static Key toKey(byte[] keyByte) throws InvalidKeyException,
                                                   NoSuchAlgorithmException,
                                                   InvalidKeySpecException{
        DESKeySpec desKeySpec = new DESKeySpec(keyByte);
        return SecretKeyFactory.getInstance(KEY_ALGORITHM).generateSecret(desKeySpec);
    }

    /**
     * DES加密
     * @param data     带加密数据
     * @param keyByte  密钥
     */
    public static byte[] encrypt(String data, byte[] keyByte) throws InvalidKeyException,
                                                                     NoSuchAlgorithmException,
                                                                     InvalidKeySpecException,
                                                                     NoSuchPaddingException,
                                                                     IllegalBlockSizeException,
                                                                     BadPaddingException,
                                                                     UnsupportedEncodingException{
        Key key = toKey(keyByte);//还原密钥
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);//设置加密模式并且初始化key
        return cipher.doFinal(data.getBytes(ENCODING));
    }

    /**
     * DES加密,并转为16进制字符串或Base64编码字符串
     */
    public static String encryptDESHex(String data, byte[] keyByte) throws InvalidKeyException,
                                                                           NoSuchAlgorithmException,
                                                                           InvalidKeySpecException,
                                                                           NoSuchPaddingException,
                                                                           IllegalBlockSizeException,
                                                                           BadPaddingException,
                                                                           UnsupportedEncodingException {
        byte[] encodedByte = encrypt(data, keyByte);
        //return new String(Hex.encode(encodedByte));//借助BC
        //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
        return Base64.encodeBase64String(encodedByte);//借助CC的Base64编码
    }

    /**
     * DES解密
     * @param data        待解密数据为字节数组
     * @param keyByte    密钥
     */
    public static byte[] decrypt(byte[] data, byte[] keyByte) throws InvalidKeyException,
                                                                     NoSuchAlgorithmException,
                                                                     InvalidKeySpecException,
                                                                     NoSuchPaddingException,
                                                                     IllegalBlockSizeException,
                                                                     BadPaddingException,
                                                                     UnsupportedEncodingException {
        Key key = toKey(keyByte);//还原密钥
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);//设置解密模式(这是加解密的唯一不同的地方)并且初始化key
        return cipher.doFinal(data);
    }

    /**
     * DES解密
     * @param data        待解密数据为字符串
     * @param keyByte    密钥
     */
    public static byte[] decrypt(String data, byte[] keyByte) throws InvalidKeyException,
                                                                     NoSuchAlgorithmException,
                                                                     InvalidKeySpecException,
                                                                     NoSuchPaddingException,
                                                                     IllegalBlockSizeException,
                                                                     BadPaddingException,
                                                                     UnsupportedEncodingException {
        Key key = toKey(keyByte);//还原密钥
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);//设置解密模式(这是加解密的唯一不同的地方)并且初始化key
        return cipher.doFinal(Base64.decodeBase64(data));//注意data不可以直接采用data.getByte()方法转化为字节数组,否则会抛异常
    }

    /**
     * 测试
     */
    public static void main(String[] args) throws NoSuchAlgorithmException,
                                                  InvalidKeyException,
                                                  InvalidKeySpecException,
                                                  NoSuchPaddingException,
                                                  IllegalBlockSizeException,
                                                  BadPaddingException,
                                                  UnsupportedEncodingException {
        String data = "找一个好姑娘做老婆是我的梦 想!";
        /*************测试encode()**************/
        System.out.println("原文-->"+data);
        byte[] keyByte = DESJDK.getKey();
        System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
        byte[] encodedByte = DESJDK.encrypt(data, keyByte);
        System.out.println("加密后-->"+encodedByte);
        byte[] encodedByte2 = DESJDK.encrypt(data, keyByte);
        System.out.println("加密后-->"+encodedByte2);
        byte[] decodedByte = DESJDK.decrypt(encodedByte, keyByte);
        System.out.println("解密后-->"+decodedByte);
        for(int i=0;i<encodedByte.length;i++){
            System.out.println(encodedByte[i]==encodedByte2[i]);
        }
        /*************测试encodeHmacMD5Hex()**************/
        System.out.println("原文-->"+data);
        byte[] keyByte3 = DESJDK.getKey();
        System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
        String encodedStr = DESJDK.encryptDESHex(data, keyByte3);
        System.out.println("加密后-->"+encodedStr);
        String encodedByte4 = DESJDK.encryptDESHex(data, keyByte3);
        System.out.println("加密后-->"+encodedByte4);
        byte[] decodedByte3 = DESJDK.decrypt(Base64.decodeBase64(encodedStr), keyByte3);
        System.out.println("解密Byte[]后-->"+decodedByte3);
        byte[] decodedByte4 = DESJDK.decrypt(encodedStr, keyByte3);
        System.out.println("解密String后-->"+decodedByte4);
    }
}

注意点:

  • 整个算法的过程与Hmac系列算法一样,都是发送方先生成一个密钥(二进制的字节数组),然后发送方将密钥通过安全的途径传给接收方。加解密过程:还原密钥(将二进制的字节数组还原成Java对象),然后根据密钥与待加解密数据进行加解密。
  • 加解密算法常量CIPHER_ALGORITHM是一个组合常量,其中的工作模式常用的是ECB和CTR(AES最常用的工作模式)填充模式一般采用PKCS5Padding即可,或者使用BC的PKCS7Padding,具体的工作模式与填充模式的介绍自己去查吧,至于JDK和BC均支持那些工作模式与填充模式直接去查本文最上边的书籍附录即可。
  • 初始化密钥长度的时候指定为56(JDK提供56位的密钥,采用BC可以产生64位的密钥)
  • 还原密钥的时候没有使用通用的方式SecretKey key = new SecretKeySpec(keyByte, ALGORITHM)来还原(当然也可以使用),而是使用了DES自己的还原类,这是DES的推荐做法,但是在AES中推荐使用通用的方式来还原密钥
  • 实际使用中,加密的密文会采用二进制来存储,密钥会采用Base64编码来存储;但是在演示的时候我会提供转化为字符串的密文(转化方法:BC的十六进制转化类 ;CC的十六进制转化类;CC的Base64编码)
  • 在解密过程中,如果传入的待解密数据data是String的,在使用dofinal()方法进行加密时,不可以直接使用doFinal(data.getByte()),否则会抛异常;可以使用doFinal(Base64.decodeBase64(data))
  • 同一段数据使用统一个密钥无论加密多少次,加密后的密文都相同

第七章 对称加密算法--DES的更多相关文章

  1. [转] 对称加密算法DES、3DES

    转自:http://www.blogjava.net/amigoxie/archive/2014/07/06/415503.html 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法, ...

  2. 常用加密算法的Java实现总结(二) ——对称加密算法DES、3DES和AES

    1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...

  3. 对称加密算法DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES。

    对称加密算法:DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES. 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文 ...

  4. 对称加密算法 ~ Des

    一.对称加密 (Symmetric Key Encryption)  对称加密是最快速.最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret ...

  5. 对称加密算法DES、3DES和AES 原理总结(转载)

    1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...

  6. 第九章 对称加密算法--IDEA

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第7章“初等加密算法--对称加密算法” 9.1.IDEA 特点: 先于AES出来取代DES 安全性极高 常用于电子邮件加密算法 ...

  7. java-信息安全(二)-对称加密算法DES,3DES,AES,Blowfish,RC2,RC4

    概述 信息安全基本概念: DES(Data Encryption Standard,数据加密标准) 3DES(Triple DES,三重数据加密算法(TDEA,Triple Data Encrypti ...

  8. 对称加密算法-DES以及DESede算法

    一.简述 对称加密算法就是能将数据加解密.加密的时候用密钥对数据进行加密,解密的时候使用同样的密钥对数据进行解密. DES是美国国家标准研究所提出的算法.因为加解密的数据安全性和密钥长度成正比.des ...

  9. 计算机网络安全 —— 对称加密算法 DES

    一.对称加密算法概念 我们通过计算机网络传输数据时,如果无法防止他人窃听, 可以利用密码学技术将发送的数据变换成对任何不知道如何做逆变换人都不可理解的形式, 从而保证了数据的机密性.这种变换被称为加密 ...

随机推荐

  1. grunt学习二

    1. 新建文件和文件目录 mkdir grunt-in-action cd grunt-in-action cd grunt-in-action mkdir grunt-empty cd grunt- ...

  2. sql优化 性能快速定位

    sql server sql性能快速定位 简介 对于写出实现功能的SQL语句和既能实现功能又能保证性能的SQL语句的差别是巨大的.很多时候开发人员仅仅是把精力放在实现所需的功能上,而忽略了其所写代码的 ...

  3. Python3学习之路~2.3 字符串操作

    字符串操作 特性:不可修改 name="my \tname is alex" print(name.capitalize()) #首字母变大写 print('Alex LI'.ca ...

  4. Python中的__init__.py的作用

    当用 import 导入该目录时,会执行 __init__.py 里面的代码 因此在__init__.py文件中,把深层的包的路径缩短,别的地方就可以在引用到目录级别时引到深层的包.

  5. 登录mysql出现/var/lib/mysql/mysql.sock不存在

    问题描述: 1.mysql安装完成后,使用 service mysqld start 总是出现 start failed. 2.使用mysql -uroot -p登录出现找不到 /var/lib/my ...

  6. SparkSQL UDF使用方法与原理详解

    UDF是SQL中很常见的功能,但在Spark-1.6及之前的版本,只能创建临时UDF,不支持创建持久化的UDF,除非修改Spark源码.从Spark-2.0开始,SparkSQL终于支持持久化的UDF ...

  7. ubuntu系统下怎么安装gcc编译器

    你安装一个名字叫做build-essential的软件包,就可以一次将编译器.make工具.所有的编程头文件.函数库等东东全部安装上,其中也包括gcc编译器,这是非常稳妥的安装方式,安装命令是用roo ...

  8. PAT 1030 Travel Plan[图论][难]

    1030 Travel Plan (30)(30 分) A traveler's map gives the distances between cities along the highways, ...

  9. 转载一篇debug文章

    http://versprite.com/og/ios-reverse-engineering-part-two-debugging-and-tracing-with-lldb/ iOS Revers ...

  10. 7.9 Models -- Connection to An HTTP Server

    一.概述 1. 如果你的Ember应用程序需要从一个HTTP服务器加载JSON数据,在你的服务器返回的任何格式中,配置Ember Data的过程将会加载records. 2. store使用一个被称为 ...