vlambda博客
学习文章列表

Java实现对称密钥算法

  • 简介

    对称密钥算法(英语:Symmetric-key algorithm)又称为对称加密、私钥加密、共享密钥加密,是密码学中的一类加密算法。这类算法在加密和解密时使用相同的密钥,或是使用两个可以简单地相互推算的密钥。事实上,这组密钥成为在两个或多个成员间的共同秘密,以便维持专属的通信联系。与公开密钥加密相比,要求双方获取相同的密钥是对称密钥加密的主要缺点之一。

    常见的对称加密算法有AES、ChaCha20、3DES、Salsa20、DES、Blowfish、IDEA、RC5、RC6、Camellia。对称加密的速度比公钥加密快很多,在很多场合都需要对称加密。

  • 对称加密算法消息传递图示

  • 对称密钥算法--DES

    DES算法在98年之后不断的被破解,当下DES的加密已经不具备安全性了,所以现在一个新项目或者没有使用过加密算法的应用,在加密算法选型的时候不用考虑DES算法。DES目前只出现在一些介绍、案例或者一些遗留的软件或者硬件中。

    在这里介绍下DES算法,因为DES在加密算法(尤其是对称加密算法)中的地位是非常高的。

    DES(Data Encryption Standard)数据加密标准

密钥长度
默认
工作模式
填充方式
实现方


56


56

ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128

NoPadding、

PKCS5Padding、

ISO10126Padding


JDK




64




56


ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128

PKCS7Padding

SO10126d2Padding、

X032Padding、

ISO7816d4Padding、

ZeroBytePadding



Bouncy

Castle

    DES加密示例:

package com.bity.des;
import org.apache.commons.codec.binary.Hex;
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 java.nio.charset.StandardCharsets;import java.security.InvalidKeyException;import java.security.Key;import java.security.NoSuchAlgorithmException;import java.security.spec.InvalidKeySpecException;
import static java.lang.System.*;
/** * <p>Title: JdkDes</p > * <p>Description: DES加密算法 </p > * <p>Company: http://www.agree.com</p > * <p>Project: security</p > * * @author <a href="mailto:[email protected]">WEIQI</a> * @version 1.0 * @date 2022-04-26 20:21 */public class JdkDes { private static final String SRC = "I'm DES encryption algorithm"; public static void main(String[] args) { jdkDes(); } /** * JDK-DES对称密钥算法实现 * * @author: <a href="mailto:[email protected]">WEIQI</a> * @date: 2022-04-26 20:41 */ private static void jdkDes() { try { // generator KEY KeyGenerator keyGenerator = KeyGenerator.getInstance("DES"); keyGenerator.init(56); SecretKey secretKey = keyGenerator.generateKey(); byte[] bytesKey = secretKey.getEncoded(); // convert KEY DESKeySpec desKeySpec = new DESKeySpec(bytesKey); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES"); Key convertSecureKey = secretKeyFactory.generateSecret(desKeySpec); // encryption Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, convertSecureKey); byte[] result = cipher.doFinal(SRC.getBytes(StandardCharsets.UTF_8)); out.println("encryption result is : " + Hex.encodeHexString(result)); //decrypt cipher.init(Cipher.DECRYPT_MODE, convertSecureKey); result = cipher.doFinal(result); out.println("decrypt result is : " + new String(result)); } catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); } }}

    运行结果如下:

encryption result is : 97919bd6b4d1590e773fdc1100564f1fecb6d585cb80015b080bb75c29f15d4ddecrypt result is : I'm DES encryption algorithm

    DES加密算法消息传递如下所示:

  • 对称密钥算法--3重DES

    3重DES的出现是因为DES算法是半公开的,这点恰好违反了柯克霍夫原则,安全性也有问题。3重DES对密码长度做了增强、迭代次数进行了提高,是目前实际应用中用得最多的。

    3DES(Triple DESDESede)

密钥长度
默认
工作模式
填充方式
实现方


112

168


168

ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128

NoPadding、

PKCS5Padding、

ISO10126Padding


JDK



128


192




168


ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128

PKCS7Padding

SO10126d2Padding、

X032Padding、

ISO7816d4Padding、

ZeroBytePadding



Bouncy

Castle

    DES加密示例:

package com.bity.des;
import org.apache.commons.codec.binary.Hex;
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 javax.crypto.spec.DESedeKeySpec;import java.nio.charset.StandardCharsets;import java.security.InvalidKeyException;import java.security.Key;import java.security.NoSuchAlgorithmException;import java.security.spec.InvalidKeySpecException;
import static java.lang.System.out;
/** * <p>Title: Jdk3Des</p > * <p>Description: 3DES加密算法实践 </p > * <p>Company: http://www.agree.com</p > * <p>Project: security</p > * * @author <a href="mailto:[email protected]">WEIQI</a> * @version 1.0 * @date 2022-04-26 20:55 */public class Jdk3Des { private static final String SRC = "I'm 3DES encryption algorithm"; public static void main(String[] args) { jdk3Des(); } /** * JDK-DES对称密钥算法实现 * * @author: <a href="mailto:[email protected]">WEIQI</a> * @date: 2022-04-26 20:41 */ private static void jdk3Des() { try { // generator KEY KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede"); keyGenerator.init(168); SecretKey secretKey = keyGenerator.generateKey(); byte[] bytesKey = secretKey.getEncoded(); // convert KEY DESedeKeySpec desKeySpec = new DESedeKeySpec(bytesKey); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede"); Key convertSecureKey = secretKeyFactory.generateSecret(desKeySpec); // encryption Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, convertSecureKey); byte[] result = cipher.doFinal(SRC.getBytes(StandardCharsets.UTF_8)); out.println("encryption result is : " + Hex.encodeHexString(result)); //decrypt cipher.init(Cipher.DECRYPT_MODE, convertSecureKey); result = cipher.doFinal(result); out.println("decrypt result is : " + new String(result)); } catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); } }}

    运行结果:

encryption result is : c44fb80f098ba6d601032abd18b71cee83f7b533b053c227350cfc89892143cbdecrypt result is : I'm 3DES encryption algorithm
  • 对称密钥算法--AES

    由于DES安全性没有了保证,3DES性能比较低,所以出现了AES对称加密算法。AES是目前使用最多的对称加密算法,AES至今尚未被破解。该算法通常用于移动通信系统的加密以及基于SSH协议的软件。

    AES(Advanced Encryption Standard)

密钥长度
默认
工作模式
填充方式
实现方


128、192、256



128

ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128

NoPadding、

PKCS5Padding、

ISO10126Padding


JDK



128、192、256




128


ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128

PKCS7Padding

ZeroBytePadding


Bouncy

Castle

    这里注意:JDK实现方256位密钥需要获得无政策限制权限文件。无政策限制文件是指因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。

    AES加密示例:

package com.bity.aes;
import org.apache.commons.codec.binary.Base64;
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.spec.SecretKeySpec;import java.nio.charset.StandardCharsets;import java.security.InvalidKeyException;import java.security.Key;import java.security.NoSuchAlgorithmException;
import static java.lang.System.*;
/** * <p>Title: JdkAes</p > * <p>Description: </p > * <p>Company: http://www.agree.com</p > * <p>Project: security</p > * * @author <a href="mailto:[email protected]">WEIQI</a> * @version 1.0 * @date 2022-04-26 21:09 */public class JdkAes { private static final String SRC = "I'm AES encryption algorithm"; public static void main(String[] args) { jdkAes(); } /** * JDK-AES加密实现 * * @author: <a href="mailto:[email protected]">WEIQI</a> * @date: 2022-04-26 21:17 */ private static void jdkAes() { try { // generator KEY KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(128); SecretKey secretKey = keyGenerator.generateKey(); byte[] bytesKey = secretKey.getEncoded(); // convert KEY Key key = new SecretKeySpec(bytesKey, "AES"); // encryption Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] result = cipher.doFinal(SRC.getBytes(StandardCharsets.UTF_8)); out.println("aes encryption result is : " + Base64.encodeBase64String(result)); //decrypt cipher.init(Cipher.DECRYPT_MODE, key); result = cipher.doFinal(result); out.println("aes decrypt result is : " + new String(result)); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); } }}

    运行结果:

aes encryption result is : zbnnZOB0dwJH4V/zeNVbOEjDR5/ltFZXkqqZY7Y+JHw=aes decrypt result is : I'm AES encryption algorithm
  • 对称密钥算法--PBE

    PBE算法结合了消息摘要算法和对称加密算法的优点,对已有算法进行包装,形成了一个特殊的对称加密算法。

    PBE算法消息通信

    PBE(Password Based Encryption)基于口令的加密

算法
密钥长度 默认
工作方式
填充方式
实现
PBEWithMD5AndDES 64
64














CBC









PKCS5Padding


PKCS7Padding


ISO10126Padding


ZeroBytePadding















BC

PBEWithMD5AndRC2 112
112
PBEWithSHA1AndDES 64
64
PBEWithSHA1AndRC2 128
128
PBEWithSHAAndIDEA-CBC 128 128
PBEWithSHAAnd2-KeyTripleDES-CBC 128 128
PBEWithSHAAnd3-KeyTripleDES-CBC 128 128

    PBE加密示例

package com.bity.pbe;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.PBEKeySpec;import javax.crypto.spec.PBEParameterSpec;import java.nio.charset.StandardCharsets;import java.security.InvalidAlgorithmParameterException;import java.security.InvalidKeyException;import java.security.Key;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.spec.InvalidKeySpecException;
/** * <p>Title: JdkPbe</p > * <p>Description: PBE算法实现 </p > * <p>Company: http://www.agree.com</p > * <p>Project: security</p > * * @author <a href="mailto:[email protected]">WEIQI</a> * @version 1.0 * @date 2022-04-26 21:37 */public class JdkPbe { private static final String SRC = "I'm PBE encryption algorithm"; public static void main(String[] args) { jdkPbe(); } private static void jdkPbe() { try { // 初始化盐 SecureRandom random = new SecureRandom(); byte[] salt = random.generateSeed(8); // 口令和密钥 String token = "Abcd1234!@#$"; PBEKeySpec pbeKeySpec = new PBEKeySpec(token.toCharArray()); SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES"); Key key = factory.generateSecret(pbeKeySpec); // 加密 PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 100); Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES"); cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpec); byte[] result = cipher.doFinal(SRC.getBytes(StandardCharsets.UTF_8)); System.out.println("pbe encryption result is : " + Base64.encodeBase64String(result)); // 解密 cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpec); result = cipher.doFinal(result); System.out.println("pbe decrypt reult is : " + new String(result)); } catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); } }}

    运行结果:

pbe encryption result is : 1VcN0rTwdFxFgtKtedxnD2Zr3em8/tKWmg0vW1W6Abk=pbe decrypt reult is : I'm PBE encryption algorithm

    以上就是对称加密算法的基本内容,在实际工作中可以根据业务需要,选择相应的对称加密算法对数据进行加密保护。