Python 和java 中使用AES加密算法
温馨提示:
本文最后更新于 2022年11月02日,已超过 825 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
需求场景:出于安全考虑,每三个月都会定期修改数据库的密码。这样导致的问题的是几乎所有的java项目,python项目都将不可用,需要将数据库的用户名和密码修改为最新的,重启之后才可以提供正常的服务。由于采用微服务架构,各种大大小小的服务少说也有几十个,还一些普通的java项目,python脚本等。将这些所有的项目的数据库密码修改一遍,然后重启,将会是一件工作量巨大工作,经过研究,最终确定的方案时采用统一的配置中心,所有的项目都从配置中心获取数据库的用户名和密码,当数据库密码修改之后,我们只需要将更新一下配置中心的密码即可。通过明文传输密码,并不安全,于是配置中心保存的是通过AES加密后的密码,程序从配置中心获取到加密的密码之后,先解密,就可以正常使用了。
java 的AES加解密程序如下
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.lang.StringUtils;
import java.security.SecureRandom;
import java.util.Properties;
/**
* AES方式加解密
*/
public class AESUtils {
public static String iv = "1234567890123456";//偏移量,16位的
/**
* AES加密
* @param content
* @param key
* @return
*/
public static String AESencode(String content ,String key){
if (StringUtils.isEmpty(key) || key.length() != 16) {
throw new RuntimeException("密钥长度为16位");
}
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
byte[] dataBytes = content.getBytes("utf-8");
int plaintextLength = dataBytes.length;
if (plaintextLength % blockSize != 0) {
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return parseByte2HexStr(encrypted);
} catch (Exception e) {
throw new RuntimeException("aes加密发生错误", e);
}
}
/**
* AES解密
* @param encryptContent
* @param password
* @return
*/
public static String AESdecode(String encryptContent, String password) {
if (StringUtils.isEmpty(password) || password.length() != 16) {
throw new RuntimeException("密钥长度为16位");
}
try {
String key = password;
byte[] encrypted1 = parseHexStr2Byte(encryptContent);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] original = cipher.doFinal(encrypted1);
return new String(original,"UTF-8").trim();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("aes解密发生错误", e);
}
}
/**
* 16进制转换为二进制
* @param input
* @return
*/
private static byte[] parseHexStr2Byte(String input) {
if (input.length()<1) {
return null;
}
byte[] bytes = new byte[input.length() / 2];
for (int i = 0;i< input.length()/2; i++) {
int high = Integer.parseInt(input.substring(i*2, i*2+1), 16);
int low = Integer.parseInt(input.substring(i*2+1, i*2+2), 16);
bytes[i] = (byte) (high * 16 + low);
}
return bytes;
}
/**
* 二进制转为16进制
* @param input
* @return
*/
private static String parseByte2HexStr(byte[] input) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < input.length; i++) {
String hex = Integer.toHexString(input[i] & 0xFF);
if (hex.length() == 1) {
hex = "0" + hex;
}
stringBuffer.append(hex.toUpperCase());
}
return stringBuffer.toString();
}
}
python 程序中使用AES加密算法
windows 环境安装pycrypto 模块
pip install pycryptodome
linux 环境安装pycrypto 模块
pip install pycrypto
完整的python AES加解密程序如下
#!/usr/bin/env python
# encoding: utf-8
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
# 如果text不足128位的倍数就用空格补足为128位
def add_to_16(text):
if len(text.encode('utf-8')) % BLOCK_SIZE:
add = BLOCK_SIZE - (len(text.encode('utf-8')) % BLOCK_SIZE)
else:
add = 0
text = text + ('\0' * add)
return text.encode('utf-8')
# 加密函数
def encrypt(text):
key = secretNumber.encode('utf-8')
mode = AES.MODE_ECB
text = add_to_16(text)
cryptos = AES.new(key, mode)
cipher_text = cryptos.encrypt(text)
return b2a_hex(cipher_text)
def aes_encrypt(data, key):
"""aes加密函数,如果data不是16的倍数【加密文本data必须为16的倍数!】,那就补足为16的倍数
:param key:
:param data:
"""
iv = "1234567890123456";
cipher = AES.new(key, AES.MODE_CBC, iv) # 设置AES加密模式 此处设置为CBC模式
block_size = AES.block_size
# 判断data是不是16的倍数,如果不是用b'\0'补足
if len(data) % block_size != 0:
add = block_size - (len(data) % block_size)
else:
add = 0
data += b'\0' * add
encrypted = cipher.encrypt(data) # aes加密
result = b2a_hex(encrypted) # b2a_hex encode 将二进制转换成16进制
return result
def aes_decode(data, key):
"""aes解密
:param key:
:param data:
"""
iv = '1234567890123456'
cipher = AES.new(key, AES.MODE_CBC, iv)
result2 = a2b_hex(data) # 十六进制还原成二进制
decrypted = cipher.decrypt(result2)
return decrypted.rstrip(b'\0') # 解密完成后将加密时添加的多余字符'\0'删除
if __name__ == "__main__":
key = "1234123412341234";
str = aes_encrypt('root',key)
print str
count = aes_decode(str,key)
print count
用java加密过的内容,用python程序也可以解密
正文到此结束
- 本文标签: Linux Python
- 本文链接: http://www.365codemall.com/article/13
- 版权声明: 本文由李俊杰原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权