Python 和java 中使用AES加密算法

13 篇文章 0 订阅

需求场景:出于安全考虑,每三个月都会定期修改数据库的密码。这样导致的问题的是几乎所有的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程序也可以解密

致敬大佬:https://www.cnblogs.com/sammy1989/p/9663517.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

www.365codemall.com

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值