对称加密算法

   博客分类: 学习笔记 文章类型: 原创

对称加密算法

本文字数为 7223 字, 预计读完大约需要 21 分钟

对称加密算法

[TOC]

java对称加密算法:

对称加密算法:DES

Data Encryption Standard)数据加密标准 实际上DES已经不具备安全性

密钥长度 默认 工作模式 填充方式 实现方
56 56 ECB、CBC、PCBC NoPadding、CTR、CTS、CFB、 CFB8、到128、OFB、OFB8、到128 PKCS5Padding,ISO10126Padding JDK
64 56 同上 PKCS7Padding、ISO10126d2Padding、X932Padding、ISO7816d4Padding、ZeroBytePadding BC

不同的工作模式和填充方式决定了破解的难度

对称加密算法使用场景

发送者–构建密钥–公布密钥–使用密钥对数据进行加密–发送加密数据–根据密钥对数据进行解密

例子:

要进行加密的字符串

private static final String src = "I'm Learing DES";
jdk
/**
	 * jdk实现DES加密
	 */
	public static void jdkDES() {
		try {
			//生成密钥
			KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");//获取DES的密钥
			keyGenerator.init(56);//设定keySize
			SecretKey secretKey = keyGenerator.generateKey();
			byte[] byteKey = secretKey.getEncoded();

			DESKeySpec desKeySpec = new DESKeySpec(byteKey);
			SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
			Key convertSecretKey = factory.generateSecret(desKeySpec);

			//加密
			Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");//设置工作方式和填充方式
			cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);//加密模式
			byte[] jdkDESBytes = cipher.doFinal(src.getBytes());
			System.out.println("jdkEncodeDESStr:" + Hex.encodeHexString(jdkDESBytes));
			//解密操作
			cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);//解密模式
			byte[] decodeJdkDESBytes = cipher.doFinal(jdkDESBytes);
			System.out.println("jdkDecodeDESStr:" + new String(decodeJdkDESBytes));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
BC
/**
	 * 两种方式:
	 * 1、通过添加Provider
	 * 2、通过调用BC的API
	 */
	public static void bcDES() {
		Security.addProvider(new BouncyCastleProvider());//添加Provider

		try {
			//生成密钥
			KeyGenerator keyGenerator = KeyGenerator.getInstance("DES","BC");//获取DES的密钥,指定使用BC的
			keyGenerator.init(56);//设定keySize
			SecretKey secretKey = keyGenerator.generateKey();
			byte[] byteKey = secretKey.getEncoded();

			DESKeySpec desKeySpec = new DESKeySpec(byteKey);
			SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
			Key  factory.generateSecret(desKeySpec);

			//加密
			Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");//设置工作方式和填充方式
			cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);//加密模式
			byte[] bcDESBytes = cipher.doFinal(src.getBytes());
			System.out.println("bcEncodeDESStr:" + Hex.encodeHexString(bcDESBytes));

			//揭秘操作
			cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);//解密模式
			byte[] decodeBcDESBytes = cipher.doFinal(bcDESBytes);
			System.out.println("bcDecodeDESStr:" + new String(decodeBcDESBytes));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

对称加密算法–3重DES

|密钥长度 |默认 |工作模式 |填充方式 |实现方 | |———-|—–|———|———-|——–| |112、168| 56 |ECB、CBC、PCBC、CTR、CTS、CFB、CFB8、到128、OFB、OFB8、到128| NoPadding、PKCS5Padding、ISO10126Padding|JDK| |168、192|56 |同上|PKCS7Padding、ISO10126d2Padding、X932Padding、ISO7816d4Padding、ZeroBytePadding |BC|

例子:

jdk
/**
	 * jdk实现3DES加密解密
	 */
	public static void jdk3DES() {
		try {
			// 生成密钥
			KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");// 获取DES的密钥
			keyGenerator.init(168);// 设定keySize
			SecretKey secretKey = keyGenerator.generateKey();
			byte[] byteKey = secretKey.getEncoded();

			DESedeKeySpec desKeySpec = new DESedeKeySpec(byteKey);
			SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
			Key convertSecretKey = factory.generateSecret(desKeySpec);

			// 加密
			Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");// 设置工作方式和填充方式
			cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);// 加密模式
			byte[] jdkDESBytes = cipher.doFinal(src.getBytes());
			System.out.println("jdkEncode3DESStr:" + Hex.encodeHexString(jdkDESBytes));

			// 揭秘操作
			cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);// 解密模式
			byte[] decodeJdkDESBytes = cipher.doFinal(jdkDESBytes);
			System.out.println("jdkDecode3DESStr:" + new String(decodeJdkDESBytes));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

事实上和DES加密的方式是一样的,只不过在上面所有使用DES的地方都是用DESede替换了

bc

通过上面DES使用BounceCstle实现可以看出其实就是给jdk动态添加了bc的实现,3DES的实现和上面的类似。这里也就不写了

对称加密算法–AES

密钥长度 默认 工作模式 填充方式 实现方
128、192、256 128 ECB、CBC、PCBC、CTR、CTS、CFB、CFB8、到128、OFB、OFB8、到128 NoPadding、ISO10126Padding JDK(256位密钥需要获得无政策限制权限文件)
同上 128 同上 PKCS7Padding、ZeroBytePadding BC

无政策限制权限文件是指:因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制

使用方式:

发送者 – 构建密钥 – 公布密钥 – 使用密钥对数据进行加密 – 发送加密数据 – 接收者 – 使用密钥对数据进行解析

例子

jdk
public static void jdkAES() {

		try {
			//生成Key
			KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
			keyGenerator.init(128);//设置keySize
//			keyGenerator.init(new SecureRandom());//生成默认的长度
			SecretKey secretKey = keyGenerator.generateKey();
			byte[] keyBytes = secretKey.getEncoded();//生成Key的内容,这里就要求进行加密和解密的keyBytes内容一定要一致,否则就解密不了
			//Key的转换
			Key key = new SecretKeySpec(keyBytes, "AES");

			//加密
			Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//设置加解密模式(加解密模式,工作模式,填充方式)
			cipher.init(Cipher.ENCRYPT_MODE, key);
			byte[] jdkAESBytes = cipher.doFinal(src.getBytes());//得到加密后的结果
			System.out.println("jdkEncodeAESStr:" + Hex.encodeHexString(jdkAESBytes));

			//进行解密
			cipher.init(Cipher.DECRYPT_MODE, key);
			byte[] jdkDecodeAESBytes = cipher.doFinal(jdkAESBytes);
			System.out.println("jdkDecodeAESStr:" + new String(jdkDecodeAESBytes));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

PBE算法(基于口令的加密)

PBE加密算法应用:

发送者 -- 构建口令 -- 公布口令 -- 构建盐 -- 使用口令和盐对数据进行加密 -- 发送盐、加密数据 -- 使用口令、盐对数据进行解密

例子:

jdk
public static void jdkPBE() {
		try {
			// 初始化盐
			SecureRandom random = new SecureRandom();
			byte[] salt = random.generateSeed(8);

			// 口令与密钥
			String password = "imooc";
			PBEKeySpec pbeKeySpec = new PBEKeySpec(password.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[] jdkPBEBytes = cipher.doFinal(src.getBytes());
			System.out.println("jdkEncodePBEStr" + Hex.encodeHexString(jdkPBEBytes));


			//解密
			cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpec);
			byte[] jdkDecodePBEBytes = cipher.doFinal(jdkPBEBytes);
			System.out.println("jdkDecodePBEStr:" + new String(jdkDecodePBEBytes));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

另:

其实上面的那么多例子我们可以看到生成Key的方式都是这样

	KeyGenerator keyGenerator = KeyGenerator.getInstance("***");// 获取DES的密钥
    keyGenerator.init(***);// 设定keySize
    SecretKey secretKey = keyGenerator.generateKey();
    byte[] byteKey = secretKey.getEncoded();

    DESedeKeySpec desKeySpec = new DESedeKeySpec(byteKey);
    SecretKeyFactory factory = SecretKeyFactory.getInstance("***");
    Key convertSecretKey = factory.generateSecret(desKeySpec);

在这些例子里面我们的加密和解密都是在同一个方法里面进行的 使用的都是上面生成的同一个key 而生成key的byte数组是由数组动态生成的 因此如果涉及到在不同位置进行加解密的话 就得考虑我应该如何让加解密的key保持一致 是通过网络传输将key和加密好的内容一起传输呢(这样同样存在被破解的风险) 还是双方约定好一个密钥进行加解密呢? 这就需要我们自己考虑了 而上面定义的key都是用程序自动生成的,我们应该怎么来自定义key呢? ** 其实Key的生成主要依赖上面生成的byte数组,我们只要获取一个byte数组就可以了(但要注意不同算法对byte数组的要求**) 例如我们知道md5对字符摘要后可以得到一个byte数组,因此我们可以这样来自定义key

String miyao = "我是密钥";

byte[] miyaoBytes = DigestUtils.md5(miyao.getBytes());
Key key = new SecretKeySpec(miyaoBytes, "AES");
...加密...解密

对称加密算法小结:

  • 上一篇:Base64
  • 下一篇:消息摘要算法