[Java 安全]对称加密算法

简介

对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi
yao)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。

特点

优点:

计算量小、加密速度快、加密效率高。

缺点:

算法是公开的,安全性得不到保证。

通信双方每次使用对称加密算法时,都需要使用其他人不知道的惟一密钥,这会使得通信双方所拥有的密钥数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。

而与公钥、密钥加密算法比起来,对称加密算法能够提供加密和认证却缺乏了签名功能,使得使用范围有所缩小。

常用算法

对称加密算法主要有DES、3DES(TripleDES)、AES、IDEA、RC2、RC4、RC5和Blowfish等。

原理

对称加密要求加密与解密使用同一个密钥,解密是加密的逆运算。由于加密、解密使用同一个密钥,这要求通信双方必须在通信前商定该密钥,并妥善保存该密钥。

对称加密体制分为两种:

一种是对明文的单个位(或字节)进行运算,称为流密码,也称为序列密码;

一种是把明文信息划分为不同的组(或块)结构,分别对每个组(或块)进行加密、解密,称为分组密码。

假设甲乙方作为通信双方。假定甲乙双方在消息传递前已商定加密算法,欲完成一次消息传递需要经过如下步骤。

工作模式

以DES算法的工作模式为例,DES算法根据其加密算法所定义的明文分组的大小(56位),将数据分割成若干56位的加密区块,再以加密区块为单位,分别进行加密处理。如果最后剩下不足一个区块的大小,称之为短块。短块的处理方法有填充法、流密码加密法、密文挪用技术。

根据数据加密时每个加密区块见得关联方式来区分,可以分为以下种工作模式:

(1) 电子密码本模式(Electronic Code Book, ECB)

用途:适合加密密钥,随机数等短数据。例如,安全地传递DES密钥,ECB是最合适的模式。

(2) 密文链接模式(Cipher Booki Chaining, CBC)

用途:可加密任意长度的数据,适用于计算产生检测数据完整性的消息认证MAC。

(3) 密文反馈模式(Cipher Feed Back, CFB)

用途:因错误传播无界,可以用于检查发现明文密文的篡改。

(4) 输出反馈模式(Output Feed Back, OFB)

用途:使用于加密冗余性较大的数据,比如语音和图像数据。

AES算法除了以上4中模式外,还有一种新的工作模式:

(5) 计数器模式(Counter, CTR)

用途:适用于各种加密应用。

本文对于各种工作模式的原理展开描述。个人认为,作为工程应用,了解其用途即可。

填充方法

Java中对称加密对于短块的处理,一般是采用填充方式。

常采用的是:NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充。

ZerosPadding

方式:全部填充为0的字节

结果如下:

F1 F2 F3 F4 F5 F6 F7 F8 //第一块

F9 00 00 00 00 00 00 00 //第二块

PKCS5Padding

方式:每个填充的字节都记录了填充的总字节数

结果如下:

F1 F2 F3 F4 F5 F6 F7 F8 //第一块

F9 07 07 07 07 07 07 07 //第二块

术语

明文(Plaintext):指待加密信息。明文可以是文本文件、图片文件、二进制数据等。

密文(Ciphertext):指经过加密后的明文。密文通常以文本、二进制等形式存在。

加密(Encryption):指将明文转换为密文的过程。

解密(Decryption):指将密文转换为明文的过程。

加密密钥(Encryption Key):指通过加密算法进行加密操作用的密钥。

解密密钥(Decryption Key):指通过解密算法进行解密操作用的密钥。

信道(Channel):通信的通道,是信号传输的媒介。

Java对于对称加密的支持

基于密钥加密的流程(DES、DESede、AES和IDEA)

DES、DESede、AES和IDEA等算法都是基于密钥加密的对称加密算法,它们的实现流程也基本一致。步骤如下:

(1)生成密钥

KeyGenerator kg =
KeyGenerator.getInstance("DES");
SecureRandom random = new SecureRandom();
kg.init(random);
SecretKey secretKey = kg.generateKey();

建议使用随机数来初始化密钥的生成。

(2)初始化密码对象

Cipher cipher =
Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);

ENCRYPT_MODE:加密模式

DECRYPT_MODE:解密模式

(3)执行

String plaintext = "Hello World";
byte[] ciphertext =
cipher.doFinal(plaintext.getBytes());

完整实例

一个完整的DES加密解密范例

1 import org.bouncycastle.util.encoders.Base64;
  2 
  3 import javax.crypto.BadPaddingException;
  4 import javax.crypto.Cipher;
  5 import javax.crypto.IllegalBlockSizeException;
  6 import javax.crypto.KeyGenerator;
  7 import javax.crypto.NoSuchPaddingException;
  8 import javax.crypto.spec.IvParameterSpec;
  9 import java.security.InvalidAlgorithmParameterException;
 10 import java.security.InvalidKeyException;
 11 import java.security.Key;
 12 import java.security.NoSuchAlgorithmException;
 13 import java.security.NoSuchProviderException;
 14 import java.security.SecureRandom;
 15 
 16 /**
 17  * @Title DESCoder
 18  * @Description DES安全编码:是经典的对称加密算法。密钥仅56位,且迭代次数偏少。已被视为并不安全的加密算法。
 19  * @Author zhangpeng0913
 20  * @Date 2016年7月14日
 21  */
 22 public class DESCoder {
 23     public static final String KEY_ALGORITHM_DES = "DES";
 24     public static final String CIPHER_DES_DEFAULT = "DES";
 25     public static final String CIPHER_DES_ECB_PKCS5PADDING = "DES/ECB/PKCS5Padding"; // 算法/模式/补码方式
 26     public static final String CIPHER_DES_CBC_PKCS5PADDING = "DES/CBC/PKCS5Padding";
 27     public static final String CIPHER_DES_CBC_NOPADDING = "DES/CBC/NoPadding";
 28     private static final String SEED = "%%%today is nice***"; // 用于生成随机数的种子
 29 
 30     private Key key;
 31     private Cipher cipher;
 32     private String transformation;
 33 
 34     public DESCoder() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
 35         this.key = initKey();
 36         this.cipher = Cipher.getInstance(CIPHER_DES_DEFAULT);
 37         this.transformation = CIPHER_DES_DEFAULT;
 38     }
 39 
 40     public DESCoder(String transformation)
 41             throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
 42         this.key = initKey();
 43         this.cipher = Cipher.getInstance(transformation);
 44         this.transformation = transformation;
 45     }
 46 
 47     /**
 48      * @Title decrypt
 49      * @Description 解密
 50      * @Author zhangpeng0913
 51      * @Date 2016年7月20日
 52      * @param input 密文
 53      * @return byte[] 明文
 54      * @throws InvalidKeyException
 55      * @throws IllegalBlockSizeException
 56      * @throws BadPaddingException
 57      * @throws InvalidAlgorithmParameterException
 58      */
 59     public byte[] decrypt(byte[] input) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
 60             InvalidAlgorithmParameterException {
 61         if (transformation.equals(CIPHER_DES_CBC_PKCS5PADDING) || transformation.equals(CIPHER_DES_CBC_NOPADDING)) {
 62             cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(getIV()));
 63         } else {
 64             cipher.init(Cipher.DECRYPT_MODE, key);
 65         }
 66         return cipher.doFinal(input);
 67     }
 68 
 69     /**
 70      * @Title encrypt
 71      * @Description 加密
 72      * @Author zhangpeng0913
 73      * @Date 2016年7月20日
 74      * @param input 明文
 75      * @return byte[] 密文
 76      * @throws InvalidKeyException
 77      * @throws IllegalBlockSizeException
 78      * @throws BadPaddingException
 79      * @throws InvalidAlgorithmParameterException
 80      */
 81     public byte[] encrypt(byte[] input) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
 82             InvalidAlgorithmParameterException {
 83         if (transformation.equals(CIPHER_DES_CBC_PKCS5PADDING) || transformation.equals(CIPHER_DES_CBC_NOPADDING)) {
 84             cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(getIV()));
 85         } else {
 86             cipher.init(Cipher.ENCRYPT_MODE, key);
 87         }
 88         return cipher.doFinal(input);
 89     }
 90 
 91     /**
 92      * @Title initKey
 93      * @Description 根据随机数种子生成一个密钥
 94      * @Author zhangpeng0913
 95      * @Date 2016年7月14日
 96      * @Return Key
 97      * @throws NoSuchAlgorithmException
 98      * @throws NoSuchProviderException
 99      */
100     private Key initKey() throws NoSuchAlgorithmException, NoSuchProviderException {
101         // 根据种子生成一个安全的随机数
102         SecureRandom secureRandom = null;
103         secureRandom = new SecureRandom(SEED.getBytes());
104 
105         KeyGenerator keyGen = KeyGenerator.getInstance(KEY_ALGORITHM_DES);
106         keyGen.init(secureRandom);
107         return keyGen.generateKey();
108     }
109 
110     private byte[] getIV() {
111         String iv = "01234567"; // IV length: must be 8 bytes long
112         return iv.getBytes();
113     }
114 
115     public static void main(String[] args) throws Exception {
116         DESCoder aes = new DESCoder(CIPHER_DES_CBC_PKCS5PADDING);
117 
118         String msg = "Hello World!";
119         System.out.println("[DES加密、解密]");
120         System.out.println("message: " + msg);
121         byte[] encoded = aes.encrypt(msg.getBytes("UTF8"));
122         String encodedBase64 = Base64.toBase64String(encoded);
123         System.out.println("encoded: " + encodedBase64);
124 
125         byte[] decodedBase64 = Base64.decode(encodedBase64);
126         byte[] decoded = aes.decrypt(decodedBase64);
127         System.out.println("decoded: " + new String(decoded));
128     }
129 }

基于口令加密的流程(PBE)

DES、DESede、AES、IDEA这几种算法的应用模型几乎如出一辙。

但是,并非所有对称加密算法都是如此。

基于口令加密(Password Based Encryption,
PBE)是一种基于口令加密的算法。其特点是:口令由用户自己掌管,采用随机数(这里叫做盐)杂凑多重加密等方法保证数据的安全性。

PBE没有密钥概念,密钥在其他对称加密算法中是经过计算得出的,PBE则使用口令替代了密钥。

流程:

步骤如下:

(1)  产生盐

SecureRandom
secureRandom = new SecureRandom();
byte[] salt =
secureRandom.generateSeed(8); // 盐长度必须为8字节

(2)  根据密码产生Key

String password = "123456";
PBEKeySpec keySpec
= new PBEKeySpec(password.toCharArray());
SecretKeyFactory
keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
SecretKey secretKey
= keyFactory.generateSecret(keySpec);

(3)  初始化加密或解密对象

PBEParameterSpec
paramSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
Cipher cipher =
Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);

(4)  执行

byte[] plaintext = "Hello World".getBytes();
byte[] ciphertext =
cipher.doFinal(plaintext);

时间: 2024-11-10 05:13:21

[Java 安全]对称加密算法的相关文章

JAVA加密解密DES对称加密算法

1 下面用DES对称加密算法(设定一个密钥,然后对所有的数据进行加密)来简单举个例子. 2 3 首先,生成一个密钥KEY. 4 我把它保存到key.txt中.这个文件就象是一把钥匙.谁拥有它,谁就能解开我们的类文件.代码参考如下: 5 package com.neusoft.jiami; 6 import Java.io.File; 7 import java.io.FileOutputStream; 8 import java.security.SecureRandom; 9 import j

Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES RSA

[前言] 本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及用法和样例 [最简单的加密] 1.简单的概念 明文:加密前的信息 密文:机密后的信息 算法:加密或解密的算法 密钥:算法使用的钥匙(读作miyao.正确应该是miyue,可是大家都读miyao) 2.简单的样例 将123456每位数字都加1后得到234567, 当中123456就是明文.234567就是密文.加密密钥就是1,加密算法是每位加 3.对称加密和非对称加密 以上为例. 123456-->234567的加密

Java加密技术(二)对称加密算法DES&AES

接下来我们介绍对称加密算法,最常用的莫过于DES数据加密算法. DES  DES-Data Encryption Standard,即数据加密算法.是IBM公司于1975年研究成功并公开发表的.DES算法的入口参数有三个:Key.Data.Mode.其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密. DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位. 通过jav

Java 加密 AES 对称加密算法

题目链接:https://oj.leetcode.com/problems/set-matrix-zeroes/ Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. 一个个找肯定会超时,我们可以分别用一个行向量和一个列向量进行维护.这样O(m*n) 能出来 class Solution { public: void setZeroes(vector<vector

Java 加密解密之对称加密算法AES

Java 加密解密之对称加密算法AES 密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用.经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准.2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一.该算法

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

常用加密算法的Java实现总结(二) ——对称加密算法DES.3DES和AES 日期:2014/7/6 文:阿蜜果 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去.收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文.在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥

Java加密技术(二)——对称加密算法DES&AES

接下来我们介绍对称加密算法,最常用的莫过于DES数据加密算法. DES DES-Data Encryption Standard,即数据加密算法.是IBM公司于1975年研究成功并公开发表的.DES算法的入口参数有三个:Key.Data.Mode.其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密. DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位. 通过java

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

注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第7章“初等加密算法--对称加密算法” 9.1.IDEA 特点: 先于AES出来取代DES 安全性极高 常用于电子邮件加密算法 9.2.实现方式 Bouncy Castle(BC,工作模式只有ECB,密钥长度为128位) 9.2.1.基于BC实现的IDEA算法 1 package com.util.idea; 2 3 import java.io.UnsupportedEncodingException; 4 import java

对称加密算法:DES加密和DESede加密和AES和PBE

对称加密算法是说加密方和解密方使用相同的密钥.常见的对称加密算法包括4个,DES,DESede(3DES),AES,PBE. 本文讨论的内容是加密算法,不是Message Digest,不是编码.下面区分一下这三个概念. 加密算法是一对一映射,明文密文一一对应.加密是不明确的,是隐晦的. 信息摘要是一个密文对应多个明文,它只是明文整体的一个指纹,一个反映,一个摘要. 编码是一对一映射,是明确的,是显然易见的,比如base64编码. DES(Data Encryption Standard)名叫数