AES加密解密

栏目: 编程工具 · 发布时间: 5年前

内容简介:在项目开发中遇到AES加密解密的问题,因为一个参数问题卡了比较久,做个记录。并给出AES加密解密分别用Java、Python和C++的实现代码。AES加密算法即密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。AES加密算法涉及4种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(

在项目开发中遇到AES加密解密的问题,因为一个参数问题卡了比较久,做个记录。并给出AES加密解密分别用 JavaPython 和C++的实现代码。

一、AES简介

AES加密算法即密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。

AES加密算法涉及4种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。数据块分组长度必须为128比特,密钥长度可以是128比特、192比特、256比特中的任意一个(如果数据块及密钥长度不足时,会补齐)。

解密算法的每一步分别对应加密算法的逆操作,加解密所有操作的顺序正好是相反的。

二、AES加密解密-Java实现

/**
 * PAD模式
 * NoPadding
 * PKCS7Padding
 * PKCS5Padding
 * PKCS1Padding
 */
private final String AES_PATTERN = "AES/CBC/NoPadding";
/**
 * AES加密KEY参数值,16个字符
 */
private final String AES_KEY = "aaaaaaaaaaaaaaaa";
/**
 * AES加密向量参数值,16个字符
 */
private final String AES_IV = "bbbbbbbbbbbbbbbb";
/**
 * 字符编码
 */
private final String CHARSET_ISO ="ISO8859-1"; 
/**
 * 解密
 *
 * @param content 要解密的文本内容,也可以直接替换成byte[]数组
 * @param pattern 模式参数
 * @param key     解密KEY值
 * @param iv      解密向量值
 * @param charSet 字符编码
 * @return
 */
public String decrypt(String content, String pattern, String key, 
String iv, String charSet) {
    try {
        Cipher cipher = Cipher.getInstance(pattern);
        Key sKeySpec = new SecretKeySpec(key.getBytes(charSet), "AES");
        cipher.init(Cipher.DECRYPT_MODE, sKeySpec, 
generateIV(iv.getBytes(charSet)));
        byte[] result = cipher.doFinal(content.getBytes(charSet));
        return new String(result, charSet);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
/**
 * 加密
 *
 * @param content 要加密的文本内容,也可以直接替换成byte[]数组
 * @param pattern 模式参数
 * @param key     解密KEY值
 * @param iv      解密向量值
 * @param charSet 字符编码
 * @return
 */
public String encrypt(String content, String pattern, String key,
String iv, String charSet) {
    try {
        Cipher cipher = Cipher.getInstance(pattern);
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(charSet), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, 
new IvParameterSpec(iv.getBytes(charSet)));
        byte[] encrypted = cipher.doFinal(content.getBytes(charSet));
        return new String(encrypted, charSet);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
/**
 * 初始化向量参数
 *
 * @param iv
 * @return
 * @throws Exception
 */
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
    AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
    params.init(new IvParameterSpec(iv));
    return params;
}

1)关于为何用”ISO8859-1″的编码方式,见 Android AES加密报错处理

javax.crypto.IllegalBlockSizeException: error:1e00007b:
Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH

2)Padding参数要特别注意下

如果项目中配置文件用Python脚本加密了,解密要使用Java代码来实现,需要注意下Python脚本使用的Padding模式,就是因为在Python脚本的实现中,没有设置Padding参数,Java代码中设置了PKCS5Padding,使得解密一直出异常。如果是输出下面的异常,查下Padding参数是否设置正确。

java.lang.RuntimeException: javax.crypto.BadPaddingException: error:1e000065:
Cipher functions:OPENSSL_internal:BAD_DECRYPT 
java.lang.RuntimeException: javax.crypto.BadPaddingException: error:1e000065:
Cipher functions:OPENSSL_internal:BAD_DECRYPT
at java.lang.Thread.run(Thread.java:776) 
Caused by: javax.crypto.BadPaddingException: error:1e000065:
Cipher functions:OPENSSL_internal:BAD_DECRYPT
at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:568)
at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:350)
at javax.crypto.Cipher.doFinal(Cipher.java:2056)
... 4 more

三、AES加密解密-Python实现

#!/usr/bin/env python

# -*- coding:utf-8 -*-

from binascii import b2a_hex, a2b_hex

from Crypto.Cipher import AES

import struct

import os

MODE = AES.MODE_CBC

KEY = ‘aaaaaaaaaaaaaaaa’

IV = ‘bbbbbbbbbbbbbbbb’

def aes_encrypt(content):

cryptor = AES.new(KEY, MODE, IV)

# 密钥key,长度:16(AES-128)、24(AES-192)、32(AES-256)

length = 16

count = len(content)

if count < length:

add = (length – count)

content = content + (‘\0’ * add)

elif count > length:

add = (length – (count % length))

content = content + (‘\0’ * add)

encrypted = cryptor.encrypt(content)

return encrypted

def aes_decrypt(content):

cryptor = AES.new(KEY, MODE, IV)

decrypt = cryptor.decrypt(content)

return decrypt

def encrypt_file(input, output):

if not os.path.exists(input):

print(‘encrypt_file: input file %s not exits.’ % input)

return

print(“encrypt_file file %s to %s” % (input, output))

with open(input, ‘r’) as origin:

data = origin.read()

encrypt_content = aes_encrypt(data)

with open(output, ‘w’) as encrypt:

encrypt.write(encrypt_content)

def decrypt_file(input, output):

if not os.path.exists(input):

print(‘decrypt_file: input file %s not exits.’ % input)

return

print(“decrypt_file file %s to %s” % (input, output))

with open(input, ‘r’) as origin:

data = origin.read()

decrypt_content = aes_decrypt(data)

with open(output, ‘w’) as decrypt:

decrypt.write(decrypt_content)

四、AES加密解密-C++实现

/**
 * 加密
 */
gbool ConfigEncrypt(char *pData, int nLen, char **ppOutData, int *pnOutLen, 
char *KEY, char *VEC) {
     if (pData == NULL) {
         return gfalse;
     }
     char ivec[16] ={0} ;
     AES_KEY aes_ks1;
     int nRet = 0;
     char *pInData = NULL;
     int nBlock = 0;
     char *pOutData = NULL;
     int nOutLen = 0;
     if (pData <= 0) {
         return (gfalse);
     }
     int nTmpLen = 16 - nLen % 16;
     pInData = (char*)malloc(nLen + 64);
     memset(pInData, 0, nLen + 64);
     memcpy(pInData, pData, nLen);
     pOutData = (char*)malloc(nLen + 64);
     memset(pOutData, 0, nLen + 64);
     memcpy(ivec, VEC, 16u);
     nLen += nTmpLen;
     nRet = AES_set_encrypt_key((const unsigned char *)KEY, 128, &aes_ks1);
     AES_cbc_encrypt((const unsigned char *)pInData, (unsigned char *)pOutData, 
nLen + 16, &aes_ks1, (unsigned char *)ivec, AES_ENCRYPT);
     free(pInData);
     nOutLen = nLen + 16;
     *ppOutData = pOutData;
     *pnOutLen = nOutLen;
     return (gtrue);
}
/**
 * 解密
 */
gbool ConfigDecrypt(char *pData, int nLen, char **ppOutData, int *pnOutLen, 
char *KEY, char *VEC) {
     if (pData == NULL || nLen == 0) {
         return gfalse;
     }
     gbool bRet = gfalse;
     char ivec[16] ={0} ;
     AES_KEY aes_ks1 = {0};
     int nRet = 0;
     char *pTemp = NULL;
     if (pData <= 0) {
         return gfalse;
     }
     memcpy(ivec, VEC, sizeof(ivec));
     nRet = AES_set_decrypt_key((const unsigned char *)KEY, 128, &aes_ks1);
     pData = pData + 16;
     char *pDstData = (char*)calloc(nLen + 16, 1);
     if (pDstData) {
         AES_cbc_encrypt((const unsigned char *)pData, (unsigned char *)pDstData, 
nLen - 16, &aes_ks1, (unsigned char *)ivec, AES_DECRYPT);
         memcpy(pnOutLen, pDstData, 4);
         char *pOutData = (char *)calloc((*pnOutLen) + 1, 1);
         if (pOutData && *pnOutLen > 0)
         {
            memcpy(pOutData, pDstData + 4, *pnOutLen);
            *ppOutData = pOutData;
            bRet = gtrue;
         }
         free(pDstData);
         pDstData = NULL;
     }
     return bRet;
 }

五、参考资料

java学习-AES加解密之AES-128-CBC算法

ByteArrayOutputStream的内存溢出问题

Blocktype异常的几种解决办法

数据加密

JAVA AES加密与解密

AES算法简介


以上所述就是小编给大家介绍的《AES加密解密》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Agile Web Development with Rails 4

Agile Web Development with Rails 4

Sam Ruby、Dave Thomas、David Heinemeier Hansson / Pragmatic Bookshelf / 2013-10-11 / USD 43.95

Ruby on Rails helps you produce high-quality, beautiful-looking web applications quickly. You concentrate on creating the application, and Rails takes care of the details. Tens of thousands of deve......一起来看看 《Agile Web Development with Rails 4》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换