目录
1.BASE64Encoder / BASE64Decoder 报错java:sun.misc程序包不存在
2.java.security.InvalidKeyException: Illegal key size
3.Python 与 Java 算法对照
JDK1.8 包括小于1.8的版本可以使用,但JDK1.8可能IDE还是会提示Access restriction.
Access restriction: The constructor 'BASE64Encoder()' is not API (restriction on required library 'D:\Environment\Java\jdk1.8.0_131\jre\lib\rt.jar')
Access restriction: The constructor 'BASE64Decoder()' is not API (restriction on required library 'D:\Environment\Java\jdk1.8.0_131\jre\lib\rt.jar')
其实从JDK1.8开始,SUN公司就已经建议不再使用 sun.misc.BASE64Encoder与sun.misc.BASE64Decoder了,推荐使用 java.util.Base64 工具类来将其替换.
//原代码
new sun.misc.BASE64Encoder().encode(encrypted);
//替换为
java.util.Base64.getEncoder().encodeToString(encrypted);
//原代码
byte[] encrypted1 = new sun.misc.BASE64Decoder().decodeBuffer(text);
//替换为
byte[] encrypted1 = java.util.Base64.getDecoder().decode(text);
此外,还可以通过引入Apache提供的commons-codec.jar解决.
//原代码
new sun.misc.BASE64Encoder().encode(encrypted);
//替换为
org.apache.commons.codec.binary.Base64.encodeBase64String(encrypted);
//原代码
byte[] encrypted1 = new sun.misc.BASE64Decoder().decodeBuffer(text);
//替换为
byte[] encrypted1 = org.apache.commons.codec.binary.Base64.decodeBase64(text);
之前在公司开发的时候,一直可以正常的加密解密,但在自己更新了JDK后,发现加密时始终抛出InvalidKeyException.
java.lang.Exception: Operator password encrypt error.
at com.xxx.framework.codec.PwdEncryptor.encryptoptpwd(PwdEncryptor.java:16)
Caused by: java.security.InvalidKeyException: Illegal key size
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
at javax.crypto.Cipher.implInit(Cipher.java:805)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at com.xxx.framework.codec.Encryptor.encrypt(Encryptor.java:25)
at com.xxx.framework.codec.PwdEncryptor.encryptoptpwd(PwdEncryptor.java:11)
分析是JDK版本问题,但收集信息后发现问题并不是那么简单,故在此记录留痕.
在我们安装的JRE目录下有这样一个文件夹:%JAVE_HOME%\jre\lib\security(%JAVE_HOME%是自己电脑的Java路径,),其中包含有两个.jar文件:“local_policy.jar ”和“US_export_policy.jar”,也就是我们平时说的jar包,这两个jar包就是我们JCE中的核心类库了。JRE中自带的“local_policy.jar ”和“US_export_policy.jar”是支持128位密钥的加密算法,而当我们要使用256位密钥算法的时候,已经超出它的范围,无法支持,所以才会报:“java.security.InvalidKeyException: Illegal key size or default parameters”的异常。
解决问题分两种情况,首先进入
%JAVE_HOME%/jre/lib/security/
目录.
1.若目
录里面存在的是 policy
文件夹:
说明此版本为JVM启用 无限制强度管辖策略 有了一种新的更简单的方法。请在当前文件夹中查找文件 java.security,使用文本编辑器打开java.security,并找到定义java安全性属性crypto.policy的行,它可以有两个值limited 或 unlimited - 默认值是limited。
默认情况下,您应该能找到一条注释掉的行:
#crypto.policy=unlimited
您可以通过取消注释该行来启用无限制,删除#:
crypto.policy=unlimited
然后重新启动指向JVM的Java应用程序即可。
2.若目录里面没有policy
文件夹,存在的是local_policy.jar,US_export_policy.jar两个jar包:
去官方下载JCE无限制权限策略文件。
jdk 5: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html#jce_policy-1.5.0-oth-JPR
jdk6: http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
JDK7的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK8的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt
将两个jar文件放到%JAVE_HOME%\jre\lib\security目录下覆盖原来文件即可。
————————————————
以上内容原文链接:https://blog.csdn.net/zhuwangxiangbie/article/details/105124612
了解更多加密解密算法内容,可访问:https://blog.csdn.net/dafeige8/article/details/75637058
以AES加密算法为例,其Java代码实现如下:
public class Encryptor {
/**
* 加密因子
*/
private static final String cryptKey = "Zz2aAhN86By947mNh+QfQs4+iiYzvXdBpuIWcrHaIQQ=";
/**
* 向量(增强算法)
*/
private static final String cryptIV = "5IjGHGqTqHuaff4prjyMGg==";
public static String encryptPassword(String data) throws Exception{
return base64Encode(aesEncryptToBytes(data, cryptKey));
}
private static String base64Encode(byte[] bytes) {
return new sun.misc.BASE64Encoder().encode(bytes);
}
private static byte[] base64Decode(String base64Code) throws Exception {
if (base64Code == null)
return null;
return new sun.misc.BASE64Decoder().decodeBuffer(base64Code);
}
private static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
byte[] key = base64Decode(encryptKey);
byte[] iv = base64Decode(cryptIV);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec _iv = new IvParameterSpec(iv);// 使用EBC模式,需要一个向量iv,可增加加密算法的强度
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//算法/模式/补码方式
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, _iv);
return cipher.doFinal(content.getBytes("utf-8"));
}
private static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey)
throws Exception {
byte[] key = base64Decode(decryptKey);
byte[] iv = base64Decode(cryptIV);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec _iv = new IvParameterSpec(iv);// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, _iv);
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes);
}
public static void main(String[] args) {
try {
String pwd = encryptPassword("test1234");
System.out.println(pwd);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Python 标准库不支持加密算法,可以安装PyCrypto模块来实现常见的加密解密,具体代码实现如下:
由于 PyCrypto 已经超过三年无人维护,安装过程踩无数坑(我只安装成功一次,还修改了vc底层).因此 Github 上的开发者 Varbin 在该项目的 Github issue 里呼吁开发们不要再使用 PyCrypto ,而应该将 PyCrypto 替换为 PyCryptoDome。对于使用 PyCrypto 的已有项目而言,PyCryptodome 保持了与 PyCrypto 相当高的兼容性并且处于良好的维护状态,可放心更换。对于要使用 Python 加密库的项目,建议开发者使用 PyCryptoDome.(详参链接:https://www.jianshu.com/p/fdc5a5854b04)
# coding=utf-8
# AES AES/CBC/PKCS5|Zero
import base64
from Crypto.Cipher import AES
# 加密因子
AES_SECRET_KEY = b"Zz2aAhN86By947mNh+QfQs4+iiYzvXdBpuIWcrHaIQQ=\n"
# 向量(增强算法)
IV = b"5IjGHGqTqHuaff4prjyMGg==\n"
def ByteToHex(bins):
"""
Convert a byte string to it's hex string representation e.g. for output.
"""
return ''.join(["%02X" % x for x in bins]).strip()
'''
采用AES对称加密算法
'''
# str不是16的倍数那就补足为16的倍数. ZeroPadding
'''
在PKCS5Padding中,明确定义Block的大小是8位
而在PKCS7Padding定义中,对于块的大小是不确定的,可以在1-255之间
PKCS #7 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。
假定块长度为 8,数据长度为 9,
数据: FF FF FF FF FF FF FF FF FF
PKCS7 填充: FF FF FF FF FF FF FF FF FF 01 01 01 01 01 01 01 ?应该是填充01
python3:填充bytes(这个说法不对,AES的参数是字符串,不是byte)
length = 16 - (len(data) % 16)
data += bytes([length])*length
python2:填充字符串
length = 16 - (len(data) % 16)
data += chr(length)*length
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]
'''
def ZeroPadding(value, bs):
while len(value) % bs != 0:
value += '\0'
return str.encode(value) # 返回bytes
# 对于python,不需要zerounpadding? 去掉尾部的\0
def PKCS7Padding(value, bs):
pad = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs) # PKS7
return str.encode(pad(value)) # 返回bytes
def PKCS7UnPadding(value):
# value = value[:-value[-1]]
unpad = lambda s: s[0:-ord(s[-1])] # 获得数据的长度,截取
return unpad(value)
# 加密方法
def encrypt_oracle(text=str):
key = base64.decodebytes(AES_SECRET_KEY)
iv = base64.decodebytes(IV)
# 初始化加密器
aes = AES.new(key, AES.MODE_CBC, iv)
bs = AES.block_size
pad2 = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs) # PKS7
# 先进行aes加密
# encrypt_aes = aes.encrypt(add_to_16(text))
# Zeropadding
# encrypt_aes = aes.encrypt(add_to_16(text))
# Pkcs7 padding
encrypt_aes = aes.encrypt(str.encode(pad2(text)))
# 转为hex
print(ByteToHex(encrypt_aes)) # 转为字符串 71462668992DB7B3FE76ABFE22376CF6
# 用base64转成字符串形式
encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8') # 执行加密并转码返回bytes
# zeropadding: UR5c4C1iW5mIdxrv5rxo4w== Pkcs7/Pkcs7: jE7BUAKWpdJWb2ulcFWd/g==
# 和js的 结果相同 http://tool.chacuo.net/cryptaes
return encrypted_text
# 解密方法
def decrypt_oralce(text=str):
key = base64.decodebytes(AES_SECRET_KEY)
iv = base64.decodebytes(IV)
# 初始化加密器
aes = AES.new(key, AES.MODE_CBC, iv)
# 优先逆向解密base64成bytes
base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))
#
decrypted_text = str(aes.decrypt(base64_decrypted), encoding='utf-8') # 执行解密密并转码返回str
unpad = lambda s: s[0:-ord(s[-1])]
# PADDING = '\0'
# print decrypted_text.rstrip(PADDING) #zeropadding只见诶去掉结尾\0
return unpad(decrypted_text)
if __name__ == '__main__':
en = encrypt_oracle('2323@#dFCSD.?')
decrypt_oralce(en)