JAVA加密解密之对称加密

x33g5p2x  于2021-12-25 转载在 其他  
字(7.0k)|赞(0)|评价(0)|浏览(430)

对称加密简介

需要对加密和解密使用相同密钥的加密算法。由于其速度快,对称性加密通常在消息发送方需要加密大量数据时使用。对称性加密也称为密钥加密。
所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥是控制加密及解密过程的指令。算法是一组规则,规定如何进行加密和解密。
因此加密的安全性不仅取决于加密算法本身,密钥管理的安全性更是重要。因为加密和解密都使用同一个密钥,如何把密钥安全地传递到解密者手上就成了必须要解决的问题。
对称加密算法的优点是算法公开、计算量小、加密速度快、加密效率高。
对称加密算法的缺点是在数据传送前,发送方和接收方必须商定好秘钥,然后使双方都能保存好秘钥。其次如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。
Created with Raphaël 2.1.2甲方甲方乙方乙方甲乙双方约定密钥使用约定密钥对数据进行加密发送数据使用约定密钥对接收到的数据进行解密

DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1976年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),随后在国际上广泛流传开来。

DESede是由DES对称加密算法改进后的一种对称加密算法。使用 168 位的密钥对资料进行三次加密的一种机制;它通常(但非始终)提供极其强大的安全性。如果三个 56 位的子元素都相同,则三重 DES 向后兼容 DES。

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

Blowfish算法是一个64位分组及可变密钥长度的对称密钥分组密码算法,可用来加密64比特长度的字符串。32位处理器诞生后,Blowfish算法因其在加密速度上超越了DES而引起人们的关注。Blowfish算法具有加密速度快、紧凑、密钥长度可变、可免费使用等特点,已被广泛使用于众多加密软件。

RC2是由著名密码学家Ron Rivest设计的一种传统对称分组加密算法,它可作为DES算法的建议替代算法。它的输入和输出都是64比特。密钥的长度是从1字节到128字节可变,但目前的实现是8字节(1998年)。

RC4加密算法是大名鼎鼎的RSA三人组中的头号人物Ronald Rivest在1987年设计的密钥长度可变的流加密算法簇。之所以称其为簇,是由于其核心部分的S-box长度可为任意,但一般为256字节。该算法的速度可以达到DES加密的10倍左右,且具有很高级别的非线性。RC4起初是用于保护商业机密的。但是在1994年9月,它的算法被发布在互联网上,也就不再有什么商业机密了。RC4也被叫做ARC4(Alleged RC4——所谓的RC4),因为RSA从来就没有正式发布过这个算法。

对称加密算法实现

package com.jianggujin.codec;

import java.io.InputStream;
import java.io.OutputStream;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.jianggujin.codec.util.JCipherInputStream;
import com.jianggujin.codec.util.JCipherOutputStream;
import com.jianggujin.codec.util.JCodecException;

/** * 对称加密 * * @author jianggujin * */
public class JSymmetrical {

   /** * 对称算法 * * @author jianggujin * */
   public static enum JSymmetricalAlgorithm {
      DES, DESede, ARCFOUR, AES, Blowfish, RC2, RC4;

      public String getName() {
         return this.name();
      }
   }

   /** * 初始化密钥 * * @param algorithm * @return */
   public static byte[] initKey(String algorithm) {
      try {
         KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
         SecretKey secretKey = keyGenerator.generateKey();
         return secretKey.getEncoded();
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 加密 * * @param data * @param key * @param algorithm * @return * @throws Exception */
   public static byte[] encrypt(byte[] data, byte[] key, String algorithm) throws Exception {
      // 数据加密
      Cipher cipher = getEncryptCipher(key, algorithm);
      try {
         return cipher.doFinal(data);
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 包裹输出流,包裹后的输出流为加密输出流 * * @param out * @param key * @param algorithm * @return */
   public static OutputStream wrap(OutputStream out, byte[] key, String algorithm) {
      // 数据加密
      Cipher cipher = getEncryptCipher(key, algorithm);

      return new JCipherOutputStream(cipher, out);
   }

   /** * 获得加密模式的{@link Cipher} * * @param key * @param algorithm * @return */
   public static Cipher getEncryptCipher(byte[] key, String algorithm) {
      return getCipher(key, algorithm, Cipher.ENCRYPT_MODE);
   }

   /** * 解密 * * @param data * @param key * @param algorithm * @return */
   public static byte[] decrypt(byte[] data, byte[] key, String algorithm) {
      // 数据解密
      Cipher cipher = getDecryptCipher(key, algorithm);
      try {
         return cipher.doFinal(data);
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 包裹输入流,原输入流为加密数据输入流 * * @param in * @param key * @param algorithm * @return */
   public static InputStream wrap(InputStream in, byte[] key, String algorithm) {
      // 数据解密
      Cipher cipher = getDecryptCipher(key, algorithm);
      return new JCipherInputStream(cipher, in);
   }

   /** * 获得解密模式的{@link Cipher} * * @param key * @param algorithm * @return */
   public static Cipher getDecryptCipher(byte[] key, String algorithm) {
      return getCipher(key, algorithm, Cipher.DECRYPT_MODE);
   }

   private static Cipher getCipher(byte[] key, String algorithm, int opmode) {
      // 生成本地密钥
      SecretKey secretKey = getSecretKey(key, algorithm);

      try {
         // 数据加密
         Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
         cipher.init(opmode, secretKey);
         return cipher;
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 获得密钥 * * @param key * @param algorithm * @return */
   private static SecretKey getSecretKey(byte[] key, String algorithm) {
      try {
         // if ("DES".equals(algorithm))
         // {
         // DESKeySpec dks = new DESKeySpec(key);
         // SecretKeyFactory keyFactory =
         // SecretKeyFactory.getInstance(algorithm);
         // SecretKey secretKey = keyFactory.generateSecret(dks);
         // return secretKey;
         // }
         return new SecretKeySpec(key, algorithm);
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }
}

编写测试代码:

package com.jianggujin.codec.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import org.junit.Test;

import com.jianggujin.codec.JBase64;
import com.jianggujin.codec.JBase64.JEncoder;
import com.jianggujin.codec.JSymmetrical;
import com.jianggujin.codec.JSymmetrical.JSymmetricalAlgorithm;

public class SymmetricalTest {
   String str = "jianggujin";
   File file = new File(getClass().getSimpleName() + ".dat");

   @Test
   public void test() throws Exception {
      System.out.println("原串:" + str);
      JEncoder encoder = JBase64.getEncoder();
      for (JSymmetricalAlgorithm algorithm : JSymmetricalAlgorithm.values()) {
         System.out.println("-----------------------------------------");
         System.out.println("算法:" + algorithm.getName());
         byte[] key = JSymmetrical.initKey(algorithm.getName());
         System.out.println("密钥:" + encoder.encodeToString(key, "UTF-8"));

         byte[] encrypt = JSymmetrical.encrypt(str.getBytes(), key, algorithm.getName());
         System.out.println("加密:" + encoder.encodeToString(encrypt, "UTF-8"));
         System.out.println("解密:" + new String(JSymmetrical.decrypt(encrypt, key, algorithm.getName())));

         System.out.print("输出流加密:" + file.getAbsolutePath());
         OutputStream out = JSymmetrical.wrap(new FileOutputStream(file), key, algorithm.getName());
         out.write(str.getBytes());
         out.flush();
         out.close();
         System.out.println();
         System.out.print("输入流解密:");
         InputStream in = JSymmetrical.wrap(new FileInputStream(file), key, algorithm.getName());
         byte[] buffer = new byte[1024];
         int len = in.read(buffer);
         System.out.println(new String(buffer, 0, len));
      }
   }
}

运行结果如下:
原串:jianggujin
—————————————–
算法:DES
密钥:sGQqEzEBkcI=
加密:v6dcAJAoHnPIeXE7AeFLow==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\SymmetricalTest.dat
输入流解密:jianggujin
—————————————–
算法:DESede
密钥:rk/0a5uRum34zbCocJutRadS1ai2UuA7
加密:V+XtMGj5kYuyM8m289r+hg==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\SymmetricalTest.dat
输入流解密:jianggujin
—————————————–
算法:ARCFOUR
密钥:dfvO19TuRVnJCZezzYjXnQ==
加密:8ym1rJDHjzXvvA==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\SymmetricalTest.dat
输入流解密:jianggujin
—————————————–
算法:AES
密钥:Nl/gKp8e15iT/RX2GIpxvQ==
加密:7+S/Kem7mWIroboYy1QvHQ==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\SymmetricalTest.dat
输入流解密:jianggujin
—————————————–
算法:Blowfish
密钥:TIYMdL89Ma/JJxZpEEIDeg==
加密:dxGuUPAML+e9Y1+WXayxQA==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\SymmetricalTest.dat
输入流解密:jianggujin
—————————————–
算法:RC2
密钥:EwkAgYc9WaSoPXf80FwJxA==
加密:LGvc9+y1BUGDHeqporg7Fg==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\SymmetricalTest.dat
输入流解密:jianggujin
—————————————–
算法:RC4
密钥:whC1IoZSGvU7sdw1lEIjDw==
加密:I+uSjycMkGo89Q==
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\SymmetricalTest.dat
输入流解密:jianggujin

相关文章