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: 我tm也是。。。大家一定要记得换jdk里面的jre Java Cryptography Architecture(JCA)——加密的那点儿事儿(加密服务提供者、算法名称、转换名称) titer1: java正则表达式提取html中的图片标签<img src=""> Run-ning: reg_html_img_src_http: 获取src中 "" 图片地址的正则("\"http?(.*?)(\"|>|\\s+)") java正则表达式提取html中的图片标签<img src=""> 勤劳的小猪: reg_html_img_src_http 这个是什么变量? AES的256位密钥加解密报 java.security.InvalidKeyException: Illegal key size or default parameters 异常的处理及处理工具 q6823221: 完美解决问题