1.对称加密算法

加密和解密使用同一个密钥,例如WinRAR。

  • WinRAR在对文件进行打包的时候,可以设置一个密码,在解压的时候需要使用同样的密码才能正确的解压。
  • 加密:encrypt(key,message) -> s
  • 解密:decrypt(key,s) -> message

算法 密钥长度(决定加密的强度) 工作模式(参数) 填充模式(格式的选择)
DES 56/64 ECB, CBC, PCBC, CTR... NoPadding, PKCS5Padding
AES 128/192/256 ECB,CBC,PCBC,CTR... NoPadding,PKCS5Padding, PKCS7Padding
IDEA 128 ECB PKCS5Padding, PKCS7Padding

JDK提供的算法并没有包括所有的工作模式和填充模式,但我们通常只需要挑选常用的模式使用就可以了。

DES因为密钥过短,可以在短时间内被暴力破解,所以并不安全。

2.AES/ECB

package com.testList;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Base64; public class SplitString {
//指定算法为AES,工作模式为ECB,填充模式为PKCS5Padding
static final String CIPHER_NAME = "AES/ECB/PKCS5Padding";
//加密
public static byte[] encrypt(byte[] key,byte[] input) throws GeneralSecurityException{
//传入算法、工作模式、填充模式,创建Cipher示例
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
//将一个byte数组,转化为一个AES的key
SecretKeySpec secretKeySpec = new SecretKeySpec(key,"AES");
//初始化:采用加密模式,并传入key
cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec);
//通过doFinal传入input数组获取加密后的byte数组
return cipher.doFinal(input);
}
//解密
public static byte[] decrypt(byte[] key,byte[] input) throws GeneralSecurityException{
//传入算法、工作模式、填充模式,创建Cipher示例
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
//将byte数组,转化为一个AES的key
SecretKeySpec secretKeySpec = new SecretKeySpec(key,"AES");
//初始化:采用解密模式,并传入key
cipher.init(Cipher.DECRYPT_MODE,secretKeySpec);
//通过doFinal传入input数组获取加密后的byte数组
return cipher.doFinal(input);
}
public static void main(String[] args) throws Exception{
String message = "Hello,world!encrypted using AES!";
System.out.println(message);
//密钥为128位,需要传入128/8=16个byte的字符串
byte[] key = "1234567890abcdef".getBytes("utf-8");
byte[] input = message.getBytes(StandardCharsets.UTF_8); byte[] encrypted = encrypt(key,input);
//把秘闻转化为61位编码打印
System.out.println("Encrypted data:"+Base64.getEncoder().encodeToString(encrypted)); byte[] decrypted = decrypt(key,encrypted);
//将解密后的数组还原为字符串
System.out.println("Decrypted data:"+new String(decrypted,"utf-8"));
}
}

3.AES/CBC

package com.testList;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Base64; public class AES_CBC {
//指定算法为为AES,工作模式为CBC,填充模式为PKCS5Padding
static final String CIPHER_NAME = "AES/CBC/PKCS5Padding";
//加密
public static byte[] encrypt(byte[] key,byte[] input) throws GeneralSecurityException{
//传入算法、工作模式、填充模式,创建Cipher实例
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
//传入key数组,获取SecretKeySpec的实例
SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
//创建SecureRandom实例,用于获取随机数
SecureRandom sr = SecureRandom.getInstanceStrong();
//获取一个16位字节的数组
byte[] iv = sr.generateSeed(16);
//传入随机数组,获取IVParameterSpec实例
IvParameterSpec ivps = new IvParameterSpec(iv);
//初始化:指定加密模式,并传入SecretKeySpec实例keySpec、IvParameterSpec实例ivps
cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivps);
//通过doFinal传入input数组,获取加密后的byte数组
byte[] data = cipher.doFinal(input);
//将iv,data一并返回
return join(iv,data);
}
public static byte[] join(byte[] bs1,byte[] bs2){
byte[] r = new byte[bs1.length+bs2.length];
System.arraycopy(bs1,0,r,0,bs1.length);
System.arraycopy(bs2,0,r,bs1.length,bs2.length);
return r;
}
public static byte[] decrypt(byte[] key,byte[] input) throws GeneralSecurityException{
//将input数组拆分为iv,data
byte[] iv = new byte[16];
byte[] data = new byte[input.length-16];
System.arraycopy(input,0,iv,0,16);
System.arraycopy(input,16,data,0,data.length);
//传入算法、工作模式、填充模式,创建Cipher实例
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
//传入key数组,获取AES加密后的SecretKeySpec类型实例
SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
//获取IvParameter实例ivps
IvParameterSpec ivps = new IvParameterSpec(iv);
//初始化:指定解密模式,并传入SecretKeySpec实例,IvParameterSpec实例
cipher.init(Cipher.DECRYPT_MODE,keySpec,ivps);
//返回解密后的数组
return cipher.doFinal(data);
}
public static void main(String[] args) throws Exception {
String message = "Hello,world!encryptd using AES!";
System.out.println("Message:"+message);
byte[] key = "1234567890abcefg".getBytes("utf-8");
byte[] data = message.getBytes(StandardCharsets.UTF_8);
byte[] encrypted = encrypt(key,data);
System.out.println("Encrypt data:"+Base64.getEncoder().encodeToString(encrypted));
byte[] decryptd = decrypt(key,encrypted);
System.out.println("Decrypted data:"+new String(decryptd,"utf-8"));
}
}

4.AES/ECB使用256位加密

import jdk.nashorn.internal.runtime.ECMAException;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Base64; public class AES256_ECB {
static final String CIPHER_NAME = "AES/ECB/PKCS5Padding";
public static byte[] encrypt(byte[] key,byte[] input) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
cipher.init(Cipher.ENCRYPT_MODE,keySpec);
return cipher.doFinal(input);
}
public static byte[] decrypt(byte[] key,byte[] input) throws GeneralSecurityException{
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
cipher.init(Cipher.ENCRYPT_MODE,keySpec);
return cipher.doFinal(input);
}
public static void main(String[] args) throws Exception {
String message = "Hello world!encrypted using AES!";
System.out.println(message);
byte[] key = "1234567890abcdef1234567890abcdef".getBytes("utf-8");
byte[] data = message.getBytes(StandardCharsets.UTF_8);
byte[] encrypted = encrypt(key,data);
System.out.println(Base64.getEncoder().encodeToString(encrypted));
byte[] decrypted = decrypt(key,encrypted);
System.out.println(new String(decrypted,"utf-8"));
}
}


问题:256位加密执行失败

搜索jdk jce policy,[下载jar包](https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html),
window:将下载的jar包复制到jdk/jre/lib/security和jdk/lib/security目录下。
Mac:
```#shell
#查看Java目录
which java
#寻找jre/lib/security目录
find . -name lcoal_policy.jar
```
如我的目录是:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/security。将下载的jar包复制到该文件。
再次运行,不再报错

5.总结:

  • 对称加密算法使用同一个密钥进行加密和解密
  • 常用算法:DES/AES/IDEA等
  • 密钥长度由算法设计决定给,AES的密钥长度是128/192/256
  • 使用256位加密需要修改JDK的policy文件
  • 使用对称加密算法需要指定:算法名称/工作模式/填充模式

廖雪峰Java10加密与安全-4加密算法-1对称加密算法的更多相关文章

  1. 廖雪峰Java10加密与安全-4加密算法-4密钥交换算法

    1DH算法 1.1.原根公式:g^i mod P 条件:1<g<P,0<i<P 原根:介于[1, p-1]之间的任意2个数i,j(p为素数,i≠j)的结果不相等,即 g^i m ...

  2. 廖雪峰Java10加密与安全-4加密算法-2口令加密算法

    对称加密key是一个byte数组,如AES256算法的key是一个32字节的数组,普通的加密软件由用户输入加密口令.如果由用户输入口令,进行加密/解密,需要用到PBE算法. 1.PBE:Passwor ...

  3. 廖雪峰Java10加密与安全-4加密算法-5非对称加密算法

    1.非对称加密 非对称加密就是加密和解密使用的不是相同的密钥 方法1: * 加密:用自己的私钥加密,然后发送给对方:encrypt(privateKeyA, message)->s * 解密:对 ...

  4. 廖雪峰Java10加密与安全-2加密算法-2Base64编码

    1.Base64编码 Base64一种把二进制数据用文本表示的编码算法.例如 中有3个字节{\xe4, \xb8, \xad},一共是24位,每6位分组,变成4个字节{39, 0b, 22, 2d}, ...

  5. 廖雪峰Java10加密与安全-2加密算法-1URL编码

    1.URL编码 URL编码是浏览器发送数据给服务器时使用的编码. 如通过百度搜索美女: 编码前:https://www.baidu.com/s?wd=美女 编码后:https://www.baidu. ...

  6. 廖雪峰Java10加密与安全-6数字证书-1数字证书

    数字证书: 非对称加密算法:对数据进行加密/解密 签名算法:确保数据完整性和抗否认性 摘要算法:确保证书本身没有被篡改

  7. 廖雪峰Java10加密与安全-1数据安全-1加密与安全概念

    数据安全 防窃听 防篡改 防伪造 古代加密方式: 移位密码:HELLO =>IFMMP 替代密码:HELLO=>p12,5,3 现代加密方式: 建立在严格的数学理论基础上 密码学逐渐发展成 ...

  8. 廖雪峰Java10加密与安全-5签名算法-1RSA签名算法

    1.数字签名 甲在发送加密消息的时候,还要发送自己的签名,而这个签名是用甲的privateKey计算的:而乙要验证这个签名是否是合法的,会用甲的publicKey去验证,如果验证成功,这个消息确实是甲 ...

  9. 廖雪峰Java10加密与安全-3摘要算法-5Hmac

    1 比较MD5和HamcMD5 HmacMD5可以看作带安全salt的MD5 import javax.crypto.KeyGenerator; import javax.crypto.Mac; im ...

随机推荐

  1. [JZOJ6344] 【NOIP2019模拟2019.9.7】Huge Counting

    题目 题目大意自己看题去-- 正解 比赛时在刚第二题,所以根本没有时间思考-- 模型可以转化为从\((x_1,x_2,..,x_n)\)出发到\((1,1)\)的方案数模\(2\). 方案数就用有重复 ...

  2. [JZOJ6340] 【NOIP2019模拟2019.9.4】B

    题目 题目大意 给你个非负整数数列\(a\),每次等概率选择大于零的\(a_i\),使其减\(1\). 问\(a_1\)被减到\(0\)的时候期望经过多少次操作. 思考历程 对于这题的暴力做法,显然可 ...

  3. 校园商铺-2项目设计和框架搭建-8升级mysql驱动相关的配置以支持mysql8

    1.如何升级驱动 1.1步骤: a 确保当前程序能正常访问数据库 b 更新mysql驱动重新运行程序进行校验 maven依赖https://mvnrepository.com/artifact/mys ...

  4. BIO 详解

    调用者主动等待调用的结果 简介 早期的jdk中,采用BIO通信模式: 通常有一个acceptor(消费者) 去负责监听客户端的连接. 它接收到客户端的连接请求之后为每个客户端创建一个线程进行链路处理, ...

  5. C/C++ nullptr

    nullptr 关键字表示空指针值. 空指针值可用于指明对象句柄.内部指针或本机指针类型不指向对象. 结合使用 nullptr 与托管代码或本机代码. 编译器为托管空指针值和本机空指针值发出相应但不同 ...

  6. C++ 俄罗斯方块

    #include <iostream> #include <string.h> #include <stdlib.h> #include <time.h> ...

  7. dos中文乱码怎么办?

    最简单的方法: 通过 chcp命令改变代码页,UTF-8的代码页为65001 即chcp 65001 chcp 65001  就是换成UTF-8代码页 chcp 936 可以换回默认的GBK chcp ...

  8. JavaScript中纯JS写21点游戏

    // 21点游戏 分为人机对战和人人对战 // 玩家每次抽一张牌 牌的点数为1-10点随机数 谁更接近21点谁就获胜 let readline = require("readline-syn ...

  9. git push到多个不同的远程仓库

    1.若现在本地有一个已经和github远程仓库关联好的本地仓库,平时都会将本地仓库push到github上. 2.有一天突然发现"码云"这个远程仓库网站,咦!这个还可以创建priv ...

  10. 05_mybatis动态sql

    1.sql片段 1.sql片段**** mybatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接.组装. 2.需求 用户信息综合查询列表和用户信息查询列表总数这两个sta ...