AES加密算法 Java与Python跨平台实现

本文介绍了一种使用AES128+Base64实现的跨平台加密方案,详细展示了在Java和Python中如何进行AES加密和解密的过程。通过对比不同加密模式、密钥长度和填充方式,解释了跨平台实现的复杂性。

AES加密算法 Java与Python跨平台实现

什么是AES

Note:

  1. 网上有很多实现代码但是鱼龙混杂,笔者摸索了半天,实现了AES加密文本跨平台的安全传输
  2. 这里以Python和Java为例,方案采用AES128+Base64.这里以Python和Java为例,方案采用AES128+Base64。

AES的算法本身是跨平台的,只不过以下这些要素决定了跨平台不是那么简单:

  • 加密模式: ECB,CBC,CFB,OFB,CTR,XTS…
  • 密钥长度: 128, 256
  • iv向量(init vector): 需要与密钥同时设置
  • padding: NoPadding,ZeroPadding,PKCS5Padding,ISO10126Padding,ANSI X.923,SSL3Padding…
  • 密钥: 用于加解密的key
    参见: Github aes-cross

Java的实现

Note:

  1. Base64 需要第三方jar包 http://www.java2s.com/Code/Jar/a/Downloadaxis103jar.htm
  2. 注意padding与unpadding的方法
import java.util.Arrays;
import java.lang.Throwable;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.axis.encoding.Base64;

public class aesEncryption {
    private static final String CYPHER_MODE = "AES/CBC/NoPadding";

    public static byte[] encrypt(byte[] key, byte[] initVector, byte[] value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector);
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

            Cipher cipher = Cipher.getInstance(CYPHER_MODE);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            int blockSize = cipher.getBlockSize();
            byte[] plaintext = padding(value, blockSize);
            return cipher.doFinal(plaintext);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static byte[] decrypt(byte[] key, byte[] initVector, byte[] encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector);
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

            Cipher cipher = Cipher.getInstance(CYPHER_MODE);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            return unpadding(cipher.doFinal(encrypted));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    private static byte[] padding(byte[] value, int blockSize) {
        int plaintextLength = value.length;
        if (plaintextLength % blockSize != 0) {
            plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
        }
        byte[] plaintext = new byte[plaintextLength];
        System.arraycopy(value, 0, plaintext, 0, value.length);
        return plaintext;
    }

    private static byte[] unpadding(byte[] bytes) {
        int i = bytes.length - 1;
        while (i >= 0 && bytes[i] == 0)
        {
            --i;
        }

        return Arrays.copyOf(bytes, i + 1);
    }

    public static void main(String[] args) {
        try {
            byte[] key = "keyskeyskeyskeys".getBytes();
            byte[] iv = "keyskeyskeyskeys".getBytes();
            byte[] content = "123".getBytes("utf-8");
            byte[] cyphertext = encrypt(key, iv, content);
            String b64 = Base64.encode(cyphertext);
            System.out.println(b64);
            byte[] de_b64 = decrypt(key, iv, Base64.decode(b64));
            String plaintext = new String(de_b64);
            System.out.println(plaintext);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

Python的实现

Note:

  1. key 和 iv 值要与之前的Java代码里分别
  2. 注意padding与unpadding的方法
from Crypto.Cipher import AES
import base64


class AESEncrypt:
    def __init__(self, key, iv):
        self.key = key
        self.iv = iv
        self.mode = AES.MODE_CBC

    def encrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.key)
        length = AES.block_size
        text_pad = self.padding(length, text)
        ciphertext = cryptor.encrypt(text_pad)
        cryptedStr = str(base64.b64encode(ciphertext), encoding='utf-8')
        return cryptedStr

    def padding(self, length, text):
        count = len(text.encode('utf-8'))
        if count % length != 0:
            add = length - (count % length)
        else:
            add = 0
        text1 = text + ('\0' * add)
        return text1

    def decrypt(self, text):
        base_text = base64.b64decode(text)
        cryptor = AES.new(self.key, self.mode, self.key)
        plain_text = cryptor.decrypt(base_text)
        ne = plain_text.decode('utf-8').rstrip('\0')
        return ne


if __name__ == '__main__':
    aes_encrypt = AESEncrypt(key='keyskeyskeyskeys', iv="keyskeyskeyskeys")  # 初始化key和IV
    text = '123'
    sign_data = aes_encrypt.encrypt(text)
    print(sign_data)
    data = aes_encrypt.decrypt(sign_data)
    print(data)

结果

明文:123
密文:nUY/Ft988QAYJYbKh2pxyw==

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值