7、异或加密算法
AES、DES为对称加密,RSA、DSA为非对称加密。今天只详细讲解AES,其他的后期再补充。今天主要是实现AES的128、256位密钥加解密 并 解决Illegal key size or default parameters问题。在AES之前,DES加密比较流行,其密钥较短、加密处理简单,加密速度快,但后来有人通过网络联合运算的方式短时间之内破解了DES的加密数据,使之成为了一种不安全的加密方式,新版本的DES的加密效率有太低;相对来说AES使用的密钥更长(分128、192、256位),内部有更简洁精确的数学算法。
一、128位密钥的加解密算法
因cipher.doFinal(byteContent)加密后的数据是个byte[]类型的数组,而有些时候我们需要的是个String类型的字符创,所以对于加密后的结果进行处理时,用了两种方式做了处理:一种是将加密结果转化为十六进制的数据再做处理;一种是用Base64做完转换功能再做处理。那么有人会问了,为什么不直接将byte[]直接转换为String呢,请接着往下看,代码注释中和最后总结中都有答案。
在这儿,先做一下前期准备:
1、如果想了解所谓的:“加密服务提供者”——即:Provider,“所请求算法的名称”——即:algorithm,“转换名称”——即:transformation(如:AES/ECB/PKCS7Padding)等这样的字眼字眼的详细内容,
那就跟我来
!
(方法一:将加密结果转化为十六进制的数据再做处理)
加解密的代码里面需要用到几个类(接口),我已尽可能做了详细的注释,如果想进一步了解其内容,可以看已下API:
用到的重要API地址:
KeyGenerator ——>
http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/javax/crypto/KeyGenerator.html
SecureRandom ——>
http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/java/security/SecureRandom.html
MessageDigest ——>
http://jszx-jxpt.cuit.edu.cn/JavaAPI/java/security/MessageDigest.html
SecretKey ——>
http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/javax/crypto/SecretKey.html
Cipher ——>
http://jszx-jxpt.cuit.edu.cn/JavaAPI/javax/crypto/Cipher.html
String ——>
http://jszx-jxpt.cuit.edu.cn/JavaAPI/java/lang/String.html
Integer ——>
http://jszx-jxpt.cuit.edu.cn/JavaAPI/java/lang/Integer.html
1、加密:
* @param content 要加密的内容
* @param key 用来生成128位密钥的密码
* @return
public static String encrypt(String content, String key) {
try {
* KeyGenerator : 是个类,此类提供(对称)密钥生成器的功能。在生成密钥后,可以重复使用同一个 KeyGenerator 对象来生成更多的密钥。
* 使用其中的getInstance(String algorithm)方法进行构造对象;
* algorithm : 所请求密钥算法的标准名称。
KeyGenerator kgen = KeyGenerator.getInstance("AES");
* Random : 此类的实例用于生成伪随机数流。
* SecureRandom : 是Random的直接子类。此类提供强加密随机数生成器 (RNG)。还必须生成非确定性输出(而)。
* SecureRandom(byte[] seed) : 构造一个实现默认随机数算法的安全随机数生成器 (RNG)。使用指定的种子字节设置种子。
* init(int keysize, SecureRandom random) : 使用用户提供的随机源初始化此密钥生成器,使其具有确定的密钥大小。
* keysize : 密钥大小。这是特定于算法的一种规格,是以位数为单位指定的。
* random : 此密钥生成器的随机源
kgen.init(128, new SecureRandom(key.getBytes()));
* java.security包中有接口 Key,SecretKey是Key的子接口,SecretKeySpec是SecretKey的实现类。
* Key : Key 是所有密钥的顶层接口。它定义了供所有密钥对象共享的功能。
* SecretKey : 此接口不包含方法或常量。其唯一目的是分组秘密密钥(并为其提供类型安全)。
* SecretKeySpec : 可以使用此类来根据一个字节数组构造一个 SecretKey
* generateKey() : 生成一个密钥。
SecretKey secretKey = kgen.generateKey();
* getEncoded() : 是Key接口中的方法;返回基本编码格式的密钥,如果此密钥不支持编码,则返回 null。
byte[] enCodeFormat = secretKey.getEncoded();
* SecretKeySpec(byte[] key, String algorithm) : SecretKeySpec的构造方法之一,根据给定的字节数组构造一个密钥。
* key : 密钥的密钥内容。复制该数组的内容来防止后续修改。
* algorithm : 与给定的密钥内容相关联的密钥算法的名称。
SecretKeySpec keySpec = new SecretKeySpec(enCodeFormat, "AES");
* Cipher : 该类为加密和解密提供加密密码功能。
* getInstance(String transformation) : 通过指定转换模式的方式获得实例化对象。
* transformation : 转换的名称,例如:AES 或者 DES/CBC/PKCS5Padding。转换始终包括加密算法的名称(例如,DES),后面可能跟有一个反馈模式和填充方案。
Cipher cipher = Cipher.getInstance("AES");
byte[] byteContent = content.getBytes("utf-8");
* init(int opmode, Key key) : 用密钥初始化此 cipher。为以下 4 种操作之一初始化该 cipher:加密、解密、密钥包装或密钥打开,这取决于 opmode 的值。
* opmode : 此 cipher 的操作模式(其为如下之一:ENCRYPT_MODE、DECRYPT_MODE、WRAP_MODE 或 UNWRAP_MODE)
* key : 密钥
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
* doFinal(byte[] input) : 按单部分操作加密或解密数据,或者结束一个多部分操作。数据将被加密或解密(具体取决于此 Cipher 的初始化模式)。
* input : 输入的数组,即:要加密或解密的内容
byte[] result = cipher.doFinal(byteContent);
* parseByte2HexStr(String result) : 自定义的一套将二进制数据转换为十六进制的数据的方法;
* !注:在这儿,加密后的byte数组是不能强制转换成字符串的(即:new String(result)); 换言之,字符串和byte数组在这种情况下不是互逆的。
* 处理方式有两种:
* 1.将result转化为十六进制的数据再做处理(需要自己写一个转换方法);
* 2.将result进行Base64(也可以用 Base64)再次加密在进行强制转换(不需要自己写方法,省事儿)。
return parseByte2HexStr(result);
// return new String(Base64.encode(result));
} catch (Exception e) {
e.printStackTrace();
return null;
其中用到的类和方法与加密的都一样,可以参考加密的注释。
public static String decrypt(String content, String key) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(key.getBytes()));
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec keySpec = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, keySpec);// 初始化
byte[] result = cipher.doFinal(parseHexStr2Byte(content));
// byte[] result = cipher.doFinal(Base64.decode(content.getBytes()));
return new String(result);
} catch (Exception e) {
e.printStackTrace();
return null;
private static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
* Integer : 该类在对象中包装了一个基本类型 int 的值(即:Integer是int的包装类)。该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 int 类型时非常有用的其他一些常量和方法。
* toHexString(int i) : 以十六进制的无符号整数形式返回一个整数参数的字符串表示形式。
* i : 要转换成字符串的整数。
* buf[i] & 0xFF : 将字节数组中每个字节拆解成2位16进制整数(原因是:每个字节(即:byte)占8位(即:bit),16进制的基数是由4位组成)
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
* 因为toHexString(int i)将需要转换的i值转换为十六进制(基数 16)的无前导 0 的 ASCII 数字字符串,所以要重新加上
hex = '0' + hex;
* toUpperCase() : 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
sb.append(hex.toUpperCase());
return sb.toString();
4、十六进制数字 ——> 字符串/字节数组
* 将十六进制数字 ——> 二进制数组
* @param hexStr 要转换的数组
* @return
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length()/2];
* hexStr.length()/2 : 将每2位16进制整数组装成一个字节(原因是:每个字节(即:byte)占8位(即:bit),16进制的基数是由4位组成)
for (int i = 0;i< hexStr.length()/2; i++) {
* parseInt(String s, int radix) : 使用第二个参数指定的基数,将字符串参数解析为有符号的整数。
* s : 包含要分析的整数表示形式的 String。
* radix : 分析 s 时使用的基数。
* 如果发生以下任意一种情况,则抛出一个 NumberFormatException 类型的异常:
* 1、第一个参数为 null 或一个长度为零的字符串。
* 2、基数小于 Character.MIN_RADIX 或者大于 Character.MAX_RADIX。
* 3、假如字符串的长度超过 1,那么除了第一个字符可以是减号 '-' ('u002D’) 外,字符串中的任何字符都不是指定基数的数字(即:第二个参数radix)。
* 4、字符串表示的值不是 int 类型的值。
int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
* String : 该类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例来实现。
* substring(int beginIndex, int endIndex) : 返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的 beginIndex 处开始,一直到索引 endIndex - 1 处的字符。
* beginIndex : 开始处的索引(包括)。
* endIndex : 结束处的索引(不包括)。
int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
result[i] = (byte) (high * 16 + low);
return result;
// 生成密钥需要的密码值
String key = "dafeige";
System.out.println("content: " + content + "\nkey: " + key);
// 内容加密后的值
String encode = encrypt(content, key);
// 被加密的内容解密后的值
String decode = decrypt(encode, key);
System.out.println("encode: " + encode + "\ndecode: " + decode);
输出的结果:
content: 请叫我dafeige
key: dafeige
encode: B49019AC97E24981989A03CFC4B3DF4B2B16B197404F3EA7FC92286E69D4CAE2
decode: 请叫我dafeige
测试完美成功!
(方法二:使用Base64做转码功能处理)
该方法的加解密中会用到的API:
IvParameterSpec ——>
http://jszx-jxpt.cuit.edu.cn/JavaAPI/javax/crypto/spec/IvParameterSpec.html
SecretKey ——>
http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/javax/crypto/SecretKey.html
Cipher ——>
http://jszx-jxpt.cuit.edu.cn/JavaAPI/javax/crypto/Cipher.html
* @param sSrc 待加密的数据
* @param sKey 加密键
* @return 返回加密后的数据
public static String encrypt(String sSrc, String sKey){
if (sKey == null) {
System.out.print("Key为空null");
return null;
// 判断Key是否为16位
if (sKey.getBytes().length != 16) {
System.out.print("Key长度不是16位");
return null;
* SecretKeySpec(byte[] key, String algorithm) : SecretKeySpec的构造方法之一,根据给定的字节数组构造一个密钥。
* key : 密钥的密钥内容。复制该数组的内容来防止后续修改。
* algorithm : 与给定的密钥内容相关联的密钥算法的名称。
SecretKeySpec skeySpec = new SecretKeySpec(sKey.getBytes(), "AES");
try {
* Cipher : 该类为加密和解密提供加密密码功能。
* getInstance(String transformation) : 通过指定转换模式的方式获得实例化对象。
* transformation : 转换的名称,例如:AES 或者 DES/CBC/PKCS5Padding。转换始终包括加密算法的名称(例如,DES),后面可能跟有一个反馈模式和填充方案。
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// "算法/模式/补码方式"
* IvParameterSpec : 该类指定初始化向量(IV)。使用IV的实例是反馈模式中的密码,例如CBC模式下的DES和具有OAEP编码操作的RSA密码。
* IvParameterSpec(byte[] iv) : 使用iv IV中的字节创建IvParameterSpec对象。
* iv : 具有IV的缓冲区。复制缓冲区的内容以防止后续修改。
IvParameterSpec iv = new IvParameterSpec("1234567890123456".getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
* init(int opmode, Key key, AlgorithmParameterSpec params) : 用密钥和一组算法参数初始化此 cipher。为以下 4 种操作之一初始化该 cipher:加密、解密、密钥包装或密钥打开,这取决于 opmode 的值。
* opmode : 此 cipher 的操作模式(其为如下之一:ENCRYPT_MODE、DECRYPT_MODE、WRAP_MODE 或 UNWRAP_MODE)
* key : 密钥
* params : 算法参数(1、可以没有这个参数,那在这儿就可以用init(int opmode, Key key)这个构造方法;2、可以为SecureRandom的对象,即一个随机数(AES不可采用这种方法);3、可以为向量iv)
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
* doFinal(byte[] input) : 按单部分操作加密或解密数据,或者结束一个多部分操作。数据将被加密或解密(具体取决于此 Cipher 的初始化模式)。
* input : 输入的数组,即:要加密或解密的内容
byte[] encrypted = cipher.doFinal(sSrc.getBytes());
// 此处使用Base64做转码功能,同时能起到2次加密的作用。
return new String(Base64.encode(encrypted));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
其中用到的类和方法与加密的都一样,可以参考加密的注释。
public static String decrypt(String sSrc, String sKey){
byte[] content = sSrc.getBytes();
byte[] password = sKey.getBytes();
// 判断Key是否正确
if (content == null) {
System.out.print("Key为空null");
return null;
// 判断Key是否为16位
if (password.length != 16) {
System.out.print("Key长度不是16位");
return null;
// 先用Base64解密,因为需要解密的数据在加密之后进行了Base64二次加密
content = Base64.decode(content);
SecretKeySpec skeySpec = new SecretKeySpec(password, "AES");
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec("1234567890123456".getBytes());
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(content);
return new String(original);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
3、测试结果:
public static void main(String[] args) {
// 需要加密的内容
String content = "请叫我dafeige";
// 密钥的生成密码(注意:长度必须为16的整数倍)
String key = "dafeige123456789";
System.out.println("content: " + content + "\nkey: " + key);
// 内容加密后的值
String encode = encrypt(content, key);
// 被加密的内容解密后的值
String decode = decrypt(encode, key);
System.out.println("encode: " + encode + "\ndecode: " + decode);
输出结果:
content: 请叫我dafeige
key: dafeige123456789
encode: UJV2QTmIiUuMx+r2TH4G+LqVqtcKXrG/+fphsLagZZ4=
decode: 请叫我dafeige
完美的结果!
两种方式的比较:第一种方式对于“生成密钥的密码值”的长度没有要求,多长都行,而第二种方法必须要求其“生成密钥的密码值”的长度为16的整数倍;网上有的说要求第二种方法的待加密和待解密的长度必须为16的整数倍,这个是完全没必要的,因为待加密的内容不管多长,不管是不是16的倍数,加密机制会自动给补够离它最近的并且是大于它的那个16的倍数,也就是说我们待加密的内容长度为16的倍数的时候,刚好不用动,如果不是16的倍数,加密机制会帮我们补齐为16的倍数,只要不修改加密后的内容,用同一个密码值就可以解密出原数据;还有就是后者比前者的代码量少,简单。
2、对于Java自身支持PKCS5Padding填充方式,而Bouncycastle支持PKCS7Padding填充方式,再加上加密解密过程中需要一些密码术算法,所以需要导入jar包:
bcprov-jdk15-133.jar,其下载地址为:
http://pan.baidu.com/s/1cvV7Ca
如果对加密后的数据进行转码处理时选择了用Base64加密,需要导入个jar包(如果使用Eclipse开发,需要下载并导入jar包,如果是
Android
Studio开发,则添加依赖就行):
javabase64-1.3.1.jar,其下载地址为:
http://download.csdn.net/detail/jiangsyace/7690869
加解密的代码里面需要用到几个类(接口),我已尽可能做了详细的注释,如果想进一步了解其内容,可以看已下API:
用到的重要API地址:
KeyGenerator ——>http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/javax/crypto/KeyGenerator.html
SecureRandom ——>http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/java/security/SecureRandom.html
MessageDigest ——>http://jszx-jxpt.cuit.edu.cn/JavaAPI/java/security/MessageDigest.html
SecretKey ——>http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/javax/crypto/SecretKey.html
Cipher ——>http://jszx-jxpt.cuit.edu.cn/JavaAPI/javax/crypto/Cipher.html
String ——>http://jszx-jxpt.cuit.edu.cn/JavaAPI/java/lang/String.html
Integer ——>http://jszx-jxpt.cuit.edu.cn/JavaAPI/java/lang/Integer.html
* KeyGenerator : 是个类,此类提供(对称)密钥生成器的功能。在生成密钥后,可以重复使用同一个 KeyGenerator 对象来生成更多的密钥。
* 使用其中的getInstance(String algorithm)方法进行构造对象;
* algorithm : 所请求密钥算法的标准名称。
KeyGenerator kgen = KeyGenerator.getInstance("AES");
* Random : 此类的实例用于生成伪随机数流。
* SecureRandom : 是Random的直接子类。此类提供强加密随机数生成器 (RNG)。还必须生成非确定性输出(而)。
* SecureRandom(byte[] seed) : 构造一个实现默认随机数算法的安全随机数生成器 (RNG)。使用指定的种子字节设置种子。
* seed : 种子。在这儿用的是一个存放哈希结果的数组,详细看下文的tohash256Deal(String datastr)。
SecureRandom securerandom = new SecureRandom(tohash256Deal(password));
* init(int keysize, SecureRandom random) : 使用用户提供的随机源初始化此密钥生成器,使其具有确定的密钥大小。
* keysize : 密钥大小。这是特定于算法的一种规格,是以位数为单位指定的。
* random : 此密钥生成器的随机源。
kgen.init(256, securerandom);
* java.security包中有接口 Key,SecretKey是Key的子接口,SecretKeySpec是SecretKey的实现类。
* Key : Key 是所有密钥的顶层接口。它定义了供所有密钥对象共享的功能。
* SecretKey : 此接口不包含方法或常量。其唯一目的是分组秘密密钥(并为其提供类型安全)。
* SecretKeySpec : 可以使用此类来根据一个字节数组构造一个 SecretKey
* generateKey() : 生成一个密钥。
SecretKey secretKey = kgen.generateKey();
* getEncoded() : 是Key接口中的方法;返回基本编码格式的密钥,如果此密钥不支持编码,则返回 null。
byte[] enCodeFormat = secretKey.getEncoded();
* SecretKeySpec(byte[] key, String algorithm) : SecretKeySpec的构造方法之一,根据给定的字节数组构造一个密钥。
* key : 密钥的密钥内容。复制该数组的内容来防止后续修改。
* algorithm : 与给定的密钥内容相关联的密钥算法的名称。
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
* Security : 此类集中了所有的安全属性和常见的安全方法。其主要用途之一是管理提供程序。
* addProvider(Provider provider) : 将提供程序添加到下一个可用位置。
* provider : 要添加的提供程序。
Security.addProvider(new BouncyCastleProvider());
* Cipher : 该类为加密和解密提供加密密码功能。
* getInstance(String transformation, String provider) : 创建一个实现指定转换的 Cipher 对象,该转换由指定的提供程序提供。
* transformation : 转换的名称,例如 DES/CBC/PKCS5Padding。描述为产生某种输出而在给定的输入上执行的操作(或一组操作)的字符串。转换始终包括加密算法的名称(例如,DES),后面可能跟有一个反馈模式和填充方案。
* provider : 提供程序的名称
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
* init(int opmode, Key key) : 用密钥初始化此 cipher。为以下 4 种操作之一初始化该 cipher:加密、解密、密钥包装或密钥打开,这取决于 opmode 的值。
* opmode : 此 cipher 的操作模式(其为如下之一:ENCRYPT_MODE、DECRYPT_MODE、WRAP_MODE 或 UNWRAP_MODE)
* key : 密钥
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteContent = content.getBytes("utf-8");
* doFinal(byte[] input) : 按单部分操作加密或解密数据,或者结束一个多部分操作。数据被加密还是解密取决于此 cipher 的初始化方式。
* input : 输入缓冲区
byte[] cryptograph = cipher.doFinal(byteContent);
* !注:在这儿,加密后的byte数组是不能强制转换成字符串的(即:new String(result)); 换言之,字符串和byte数组在这种情况下不是互逆的。
* 处理方式有两种:
* 1.将result转化为十六进制的数据再做处理(需要自己写一个转换方法)—— 用法和“128位密钥的加解密算法”的一模一样,可以参考上文;
* 2.将result进行Base64(也可以用 BASE64Encode)再次加密在进行强制转换(不需要自己写方法,省事儿)。(主要编解码方式有Base64, HEX, UUE, 7bit等等。此处看服务器需要什么编码方式)
return new String(Base64.encode(cryptograph));
} catch (Exception e) {
e.printStackTrace();
return null;
public static String decrypt(String cryptograph, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom securerandom = new SecureRandom(tohash256Deal(password));
kgen.init(256, securerandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] content = cipher.doFinal(Base64.decode(cryptograph.getByte()));
return new String(content);
} catch (Exception e) {
e.printStackTrace();
return null;
3、hash算法处理
* 将指定字符串做hash算法处理
* @param datastr 需要被处理的字符串
* @return
private static byte[] tohash256Deal(String datastr) {
try {
* MessageDigest : 该类是个抽象类,此类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。信息摘要是安全的单向哈希函数,它接收任意大小的数据,输出固定长度的哈希值。
* getInstance(String algorithm) : 生成实现指定摘要算法的 MessageDigest 对象。
* algorithm : 所请求算法的名称。
* 该对象通过使用 update 方法处理数据。任何时候都可以调用 reset 方法重置摘要。一旦所有需要更新的数据都已经被更新了,应该调用 digest 方法之一完成哈希计算。
MessageDigest digester=MessageDigest.getInstance("SHA-256");
* update(byte[] input) : 使用指定的字节数组更新摘要。
digester.update(datastr.getBytes());
* digest() : 通过执行诸如填充之类的最终操作完成哈希计算。调用此方法后摘要被重置。
byte[] hex=digester.digest();
* hex : 存放哈希值结果的字节数组。
return hex;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e.getMessage());
4、测试结果
public static void main(String[] args) {
// 待加密的内容
String content = "0f我7264在6318a这92b9e13儿c65db7cd大飞哥3c";
// 密钥的生成密码
String password = "1^da_fei$g=e.";
System.out.println("content:" + content);
System.out.println("password:" + password);
String encodeResult = encrypt(content, password);
System.out.println("encryptResult:" + encodeResult);
String decodeResult = decrypt(encodeResult, password);
System.out.println("decodeResult:" + decodeResult);
输出结果:
content:0f我7264在6318a这92b9e13儿c65db7cd大飞哥3c
password:1^da_fei$g=e.
encryptResult:8HVOPIDA4cvFTSpaLy6xE25abLgqG7Qtyd9LFa4YrC+OEE5lU27JhFoAcUmd6Epld+dyOJYzb4p0mYlQcA7kaA==
decodeResult:0f我7264在6318a这92b9e13儿c65db7cd大飞哥3c
1、为什么会报“java.security.InvalidKeyException: Illegal key size or default parameters”异常:
因为我们在安装JDK的时候,jre中自带的“local_policy.jar ”和“US_export_policy.jar”是支持128位密钥的加密算法,而当我们要使用256位密钥算法的时候,因其不支持,所以需要下载支持更长的密钥算法jar包,oracle官网有不同JDK版本的无限长密钥算法包——“Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files X”(“X”代表不同版本的JDK),这儿可以直接给链接,有需要的可以点击下面一句话:
注意:在这儿为什么要导入一个第三方的Base64的jar包,因为Base64是Apache公司提供的技术,从JDK_1.8(改名后也叫JDK8)开始,java.util 包中才包含了对 Base64 的处理,其具体操作为:
// 编码
String encodeBase64 = Base64.getEncoder().encodeToString(“需要Encode的字符串”.getBytes());
今日遇到如下错误:java.security.InvalidKeyException: Illegal key size
因为美国法律限制,JAVA默认支持AES 128 Bit 的key, 如果你计划使用 192 Bit 或者 256 Bit key, java complier 会抛出 Illegal key size Exception
解决办法也很简单:
将下面链接中的jar包下载下来,替换jdk 与jre下两个jar包:local_policy.jar和US_export_policy.jar即可。
jdk对应jar包的路径:D:\Java\jdk1.7.0_25\jre\lib\security
jre对应jar包的路径:D:\Java\jre7\lib\security
记录下最近学到的加密方式。废话少说,直接上菜。
首先,AES是对称性加密,加密解密使用的密钥是一样的。其次,AES-128-CBC模式加密,要求密钥key和偏移量IV的长度要一致,且长度都是16才可以加密。
中间进行加密。
最后,为了提高安全性,可以再进行一次base64编码。
package utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.
(一)KeyGenerator
Java提供了一个名称为KeyGenerator的类,该类用于生成密钥,此类的对象是可重用的。
要使用KeyGenerator类生成密钥,请按照以下步骤操作
第1步:创建KeyGenerator对象
KeyGenerator类提供getInstance()方法,该方法接受表示所需密钥生成算法的String变量,并返回生成密钥的KeyGenerator对象。
第2步:创建SecureRandom对象java.Security包的SecureRand
AES的256位密钥加解密报 java.security.InvalidKeyException: Illegal key size or default parameters 异常的处理及处理工具
38032
AES的256位密钥加解密报 java.security.InvalidKeyException: Illegal key size or default parameters 异常的处理及处理工具
FoolishGoose:
Java Cryptography Architecture(JCA)——加密的那点儿事儿(加密服务提供者、算法名称、转换名称)
titer1:
java正则表达式提取html中的图片标签<img src="">
Run-ning: