AES加密解密与代码实现详解
JAVA实现AES的加密和解密算法
JAVA实现AES的加密和解密算法AES(高级加密标准)是一种对称加密算法,可以通过Java的javax.crypto库来实现。
下面我们将介绍一种基于Java的AES加密和解密算法的实现方法。
1.导入所需的包在Java中使用AES加密和解密算法需要导入以下两个包:```import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;```2.创建加密和解密函数首先,我们需要创建加密函数和解密函数。
加密函数将输入的明文数据加密为密文,解密函数将输入的密文数据解密为明文。
```javaprivate static byte[] encrypt(byte[] key, byte[] data) throws ExceptionSecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);return cipher.doFinal(data);private static byte[] decrypt(byte[] key, byte[] encryptedData) throws ExceptionSecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);return cipher.doFinal(encryptedData);```3.测试加密和解密函数为了验证加密和解密函数的正确性,我们可以创建一个测试函数来测试它们。
AES算法C语言讲解与实现
AES算法C语言讲解与实现AES(Advanced Encryption Standard)是一种对称加密算法,被广泛应用于各种应用中,如保护通信、数据安全等。
AES算法采用分组密码的方式,将明文数据分成若干个大小相等的分组,然后对每个分组进行加密操作。
1. 密钥扩展(Key Expansion):AES算法中使用的密钥长度分为128位、192位和256位三种,密钥长度不同,密钥扩展的轮数也不同。
根据密钥长度,需要扩展成多少个轮密钥。
扩展过程中需要进行字节代换、循环左移、模2乘法等操作。
2. 子密钥生成(Subkey Generation):根据密钥扩展的结果,生成每一轮需要使用的子密钥。
3. 字节替换(SubBytes):将每个字节替换为S盒中对应的值。
S盒是一个固定的预先计算好的查找表。
4. 行移位(ShiftRows):对矩阵的行进行循环左移,左移的位数根据行数而定。
5. 列混合(MixColumns):将每列的四个字节进行混合。
混合操作包括乘法和异或运算。
6. 轮密钥加(AddRoundKey):将每一轮得到的结果与轮密钥进行异或运算。
以上就是AES算法的六个步骤的实现过程,下面我们来具体讲解一下。
首先,我们需要定义一些辅助函数,如字节代换函数、循环左移函数等。
```cuint8_t substitution(uint8_t byte) return sBox[byte];void shiftRows(uint8_t *state)uint8_t temp;//第二行循环左移1位temp = state[1];state[1] = state[5];state[5] = state[9];state[9] = state[13];state[13] = temp;//第三行循环左移2位temp = state[2];state[2] = state[10];state[10] = temp;temp = state[6];state[6] = state[14];state[14] = temp;//第四行循环左移3位temp = state[15];state[15] = state[11];state[11] = state[7];state[7] = state[3];state[3] = temp;void mixColumns(uint8_t *state)int i;uint8_t temp[4];for(i = 0; i < 4; i++)temp[0] = xTime(state[i * 4]) ^ xTime(state[i * 4 + 1]) ^ state[i * 4 + 1] ^state[i * 4 + 2] ^ state[i * 4 + 3];temp[1] = state[i * 4] ^ xTime(state[i * 4 + 1]) ^xTime(state[i * 4 + 2]) ^state[i * 4 + 2] ^ state[i * 4 + 3];temp[2] = state[i * 4] ^ state[i * 4 + 1] ^ xTime(state[i * 4 + 2]) ^xTime(state[i * 4 + 3]) ^ state[i * 4 + 3];temp[3] = xTime(state[i * 4]) ^ state[i * 4] ^ state[i * 4 + 1] ^state[i * 4 + 2] ^ xTime(state[i * 4 + 3]);state[i * 4] = temp[0];state[i * 4 + 1] = temp[1];state[i * 4 + 2] = temp[2];state[i * 4 + 3] = temp[3];}```接下来,我们实现密钥扩展和子密钥生成的过程。
A E S 加 密 算 法 的 原 理 详 解 ( 2 0 2 0 )
# AES加密原理-详解0 AES简介美国国家标准技术研究所在2001年发布了高级加密标准(AES)。
AES 是一个对称分组密码算法,旨在取代DES成为广泛使用的标准。
根据使用的密码长度,AES最常见的有3种方案,用以适应不同的场景要求,分别是AES-128、AES-192和AES-256。
本文主要对AES-128进行介绍,另外两种的思路基本一样,只是轮数会适当增加。
1 算法流程AES加解密的流程图如下:AES加密过程涉及到4种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。
解密过程分别为对应的逆操作。
由于每一步操作都是可逆的,按照相反的顺序进行解密即可恢复明文。
加解密中每轮的密钥分别由初始密钥扩展得到。
算法中16字节的明文、密文和轮密钥都以一个4x4的矩阵表示。
接下来分别对上述5种操作进行介绍。
1.1 字节代替下图(a)为S盒,图(b)为S-1(S盒的逆)S和S-1分别为16x16的矩阵。
假设输入字节的值为a=a7a6a5a4a3a2a1a0,则输出值为S[a7a6a5a4][a3a2a1a0],S-1的变换也同理。
例如:字节00替换后的值为(S[0][0]=)63,再通过S-1即可得到替换前的值,(S-1 [6][3]=)00。
1.2 行移位行移位的功能是实现一个4x4矩阵内部字节之间的置换。
1.2.1 正向行移位正向行移位的原理图如下:实际移位的操作即是:第一行保存不变,第二行循环左移1个字节,第三行循环左移2个字节,第四行循环左移3个字节。
假设矩阵的名字为state,用公式表示如下:state’[i][j] = state[i][(j+i)%4];其中i、j属于[0,3]1.2.2 逆向行移位逆向行移位即是相反的操作,用公式表示如下:state’[i][j] = state[i][(4+j-i)%4];其中i、j属于[0,3]1.3 列混淆列混淆:利用GF(28)域上算术特性的一个代替。
python实现aes加密解密
python实现aes加密解密引⼦: 在windows中python3使⽤ pycryptodemo 模块实现Aes加密解密。
Aes加密有多种⽅式,⾃⼰可以上⽹了解下。
AES是每16位⼀加密,并且保证key和vi都是16位的。
废话不多说直接上代码。
import base64from Crypto.Cipher import AESfrom binascii import b2a_hex,a2b_hexclass PrpCrypt(object):def __init__(self,key,iv):self.key=key.encode('utf-8')self.mode=AES.MODE_CBCself.iv=iv.encode('utf-8')def pad_byte(self, b):'''1 先计算所传⼊bytes类型⽂本与16的余数2 在将此余数转成bytes 当然⽤0补位也可以3 已知了余数那么就⽤余数*被转成的余数,就得到了需要补全的bytes4 拼接原有⽂本和补位:param b: bytes类型的⽂本:return: 返回补全后的bytes⽂本'''bytes_num_to_pad = AES.block_size - (len(b) % AES.block_size)# python3 中默认unicode转码# 实际上byte_to_pad 就已经将数字转成了unicode 对应的字符即使你的⼊参正好是16的倍数,那么bytes也是把列表整体的转码也是有值的# 后边解密的匿名函数拿到最后⼀个数字后,就知道应该截取的长度,在反着切⽚就⾏了# 这样保证了数据的完整性byte_to_pad = bytes([bytes_num_to_pad])padding = byte_to_pad * bytes_num_to_padpadded = b + paddingreturn paddeddef encrypt(self,text):'''1 先⽣成aes实例2 对传⼊的text转成bytes3 对传⼊的text补全4 调⽤encrypt 加密得到密⽂5 先将密⽂转16进制,在将16进制⽤base64转码,然后在将得到的base64解码其实在步骤4 就已经完成了aes加密,我所在的公司加密⽐较复杂,需要的可以直接返回步骤4的值:param text::return:'''cryptor = AES.new(self.key,self.mode,self.iv)text = text.encode('utf-8')text = self.pad_byte(text)self.ciphertext = cryptor.encrypt(text)cryptbase64 = base64.b64encode(b2a_hex(self.ciphertext)).decode('utf8')return cryptbase64def decrypt(self,text):'''解密和加密的顺序是相反的1 定义匿名函数,去掉补位2 base64解码3 ⽣成aes实例4 16进制转2进制5 使⽤decrypt解码得到补全的bytes类型明⽂:param text::return: 解密且去掉补位的明⽂'''unpad = lambda s: s[:-ord(s[len(s) - 1:])]base64Str = base64.b64decode(text.encode('utf8'))cryptor = AES.new(self.key, self.mode, self.iv)aesStr = cryptor.decrypt(a2b_hex(base64Str))aesStr = str(unpad(aesStr), encoding='utf8')return aesStrif __name__ == '__main__':data='sadfsasdgsdfgdsf123'pc=PrpCrypt('daajanbaqa654321','1234567890123456')redata = pc.encrypt(data)print(redata)result=pc.decrypt(redata)print(result) 思路: 这⾥引⽤⼀句前辈的话,思路很重要。
AES加密解密C语言实现
快毕业了,最后一个课程设计,《基于Windows Socket的安全通信》,内容就是基于AES加密的SOCKET通信,貌似挺简单,不过要用VC++6.0开发,C++我确实没有任何代码经验,虽然不是强制性,但由于机房里各种纠结,只能用它了(用Java没有挑战性,封装得太好了...也算熟悉下VC++吧)先搞定AES算法,基本变换包括SubBytes(字节替代)、ShiftRows(行移位)、MixColumns(列混淆)、AddRoundKey(轮密钥加)其算法一般描述为明文及密钥的组织排列方式(其中c i是6310即011000112的第i位),用矩阵表示为本来打算把求乘法逆和仿射变换算法敲上去,最后还是放弃了...直接打置换表行移位变换完成基于行的循环位移操作,变换方法:即行移位变换作用于行上,第0行不变,第1行循环左移1个字节,第2行循b(x) = (03·x + 01·x + 01·x + 02) ·a(x) mod(x + 1)矩阵表示形式:其中FFmul为有限域GF(28)上的乘法,标准算法应该是循环8次(b与a的每一位相乘,结果相加),但这里只用到最低2位,解密时用到的逆列混淆也只用了低4位,所以在这里高4位的运算是多余的,只计算低4位。
KeyExpansion(密钥扩展)将输入的密钥扩展为11组128位密钥组,其中第0组为输入密钥本身其后第n组第i列为第n-1组第i列与第n组第i-1列之和(模2加法,1 <= i <=3)对于每一组第一列即i=0,有特殊的处理将前一列即第n-1组第3列的4个字节循环左移1个字节,加密时默认参数length=0,为要加密的数据长度,如果使用默认值,则作为字符串处理,以'\0'为结尾计算长度加密时传进的指针要预留够16整数倍字节的空间,因为加密操作直接修改原数据,不足128位可能造成内存溢出。
Python中如何使用AES算法进行加密和解密
Python中如何使用AES算法进行加密和解密一、引言随着互联网的快速发展,财务交易、个人资料和敏感数据被传输在网络上的频率越来越高。
因此,保护数据的安全性和私密性成为了一项至关重要的任务。
加密技术是一种重要的手段,可以解决这个问题。
其中最受欢迎和应用广泛的加密算法是AES。
本文主要介绍Python中如何使用AES算法进行加密和解密的方法。
二、AES算法简介AES算法是高级加密标准(Advanced Encryption Standard)的缩写。
它是目前广泛使用的对称加密算法之一,是一种分组密码,加密和解密使用相同的秘钥(Key)进行。
AES算法的加密和解密都是基于密钥和明文的操作。
AES算法对明文进行加密时需要三个参数:明文、密钥和向量(IV),其中向量是用于增加随机性和异质性以增强密码体制的安全性的。
加密后,得到的密文只有通过使用相同的密钥和向量才能被解密。
因此,必须确保密钥和向量的安全性。
AES算法的强度与密钥长度有关,通常使用128、192或256位密钥。
三、Python中使用AES算法加密和解密的方法Python中使用AES算法加密和解密需要使用Crypto库,它是Python中专门提供密码学操作的库。
在使用之前,需要先安装Crypto 库:```pythonpip install pycrypto```在Crypto库中,有很多算法可以使用。
在这里,我们使用AES算法。
首先,需要导入Crypto库中的AES模块,如下所示:```pythonfrom Crypto.Cipher import AES```接下来,定义用于加密和解密的key和iv:```pythonkey = '0123456789abcdef'iv = 'fedcba9876543210'```key和iv都是以字符串形式定义的,长度分别为16个字符(128位)和16个字符(128位)。
AES加密C语言实现代码
AES加密C语言实现代码以下是一个简单的C语言实现AES加密算法的代码:```c#include <stdio.h>#include <stdlib.h>#include <stdint.h>//定义AES加密的轮数#define NR 10//定义AES加密的扩展密钥长度#define Nk 4//定义AES加密的行数和列数#define Nb 4//定义AES加密的状态矩阵typedef uint8_t state_t[4][4];//定义AES加密的S盒变换表static const uint8_t sbox[256] =//S盒变换表};//定义AES加密的轮常量表static const uint8_t Rcon[11] =//轮常量表};//定义AES加密的密钥扩展变换函数void KeyExpansion(const uint8_t* key, uint8_t* expandedKey) uint32_t* ek = (uint32_t*)expandedKey;uint32_t temp;//密钥拷贝到扩展密钥中for (int i = 0; i < Nk; i++)ek[i] = (key[4 * i] << 24) , (key[4 * i + 1] << 16) ,(key[4 * i + 2] << 8) , (key[4 * i + 3]);}//扩展密钥生成for (int i = Nk; i < Nb * (NR + 1); i++)temp = ek[i - 1];if (i % Nk == 0)//对上一个密钥的字节进行循环左移1位temp = (temp >> 8) , ((temp & 0xFF) << 24);//对每个字节进行S盒变换temp = (sbox[temp >> 24] << 24) , (sbox[(temp >> 16) & 0xFF] << 16) , (sbox[(temp >> 8) & 0xFF] << 8) , sbox[temp & 0xFF];// 取轮常量Rcontemp = temp ^ (Rcon[i / Nk - 1] << 24);} else if (Nk > 6 && i % Nk == 4)//对每个字节进行S盒变换temp = (sbox[temp >> 24] << 24) , (sbox[(temp >> 16) & 0xFF] << 16) , (sbox[(temp >> 8) & 0xFF] << 8) , sbox[temp & 0xFF];}//生成下一个密钥ek[i] = ek[i - Nk] ^ temp;}//定义AES加密的字节替换函数void SubBytes(state_t* state)for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)(*state)[i][j] = sbox[(*state)[i][j]];}}//定义AES加密的行移位函数void ShiftRows(state_t* state) uint8_t temp;//第2行循环左移1位temp = (*state)[1][0];(*state)[1][0] = (*state)[1][1]; (*state)[1][1] = (*state)[1][2]; (*state)[1][2] = (*state)[1][3]; (*state)[1][3] = temp;//第3行循环左移2位temp = (*state)[2][0];(*state)[2][0] = (*state)[2][2]; (*state)[2][2] = temp;temp = (*state)[2][1];(*state)[2][1] = (*state)[2][3]; (*state)[2][3] = temp;//第4行循环左移3位temp = (*state)[3][0];(*state)[3][0] = (*state)[3][3];(*state)[3][3] = (*state)[3][2];(*state)[3][2] = (*state)[3][1];(*state)[3][1] = temp;//定义AES加密的列混淆函数void MixColumns(state_t* state)uint8_t temp, tmp, tm;for (int i = 0; i < 4; i++)tmp = (*state)[i][0];tm = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;temp = (*state)[i][0] ^ (*state)[i][1];(*state)[i][0] ^= temp ^ tm;temp = (*state)[i][1] ^ (*state)[i][2];(*state)[i][1] ^= temp ^ tm;temp = (*state)[i][2] ^ (*state)[i][3];(*state)[i][2] ^= temp ^ tm;temp = (*state)[i][3] ^ tmp;(*state)[i][3] ^= temp ^ tm;}//定义AES加密的轮密钥加函数void AddRoundKey(state_t* state, const uint8_t* roundKey) for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)(*state)[j][i] ^= roundKey[i * 4 + j];}}//定义AES加密函数void AES_Encrypt(const uint8_t* plainText, const uint8_t* key, uint8_t* cipherText)state_t* state = (state_t*)cipherText;uint8_t expandedKey[4 * Nb * (NR + 1)];//密钥扩展KeyExpansion(key, expandedKey);//初始化状态矩阵for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)(*state)[j][i] = plainText[i * 4 + j];}}//第1轮密钥加AddRoundKey(state, key);//迭代执行第2至第10轮加密for (int round = 1; round < NR; round++) SubBytes(state);ShiftRows(state);MixColumns(state);AddRoundKey(state, expandedKey + round * 16); }//执行第11轮加密SubBytes(state);ShiftRows(state);AddRoundKey(state, expandedKey + NR * 16);int maiuint8_t plainText[16] =//明文数据};uint8_t key[16] =//密钥数据};uint8_t cipherText[16];AES_Encrypt(plainText, key, cipherText);。
mysql_aes解密_填充方法_概述及解释说明
mysql aes解密填充方法概述及解释说明1. 引言1.1 概述本文将详细介绍MySQL中的AES解密方法及其填充方法。
随着信息安全的日益重视,对数据进行加密保护成为了不可或缺的一环。
AES(Advanced Encryption Standard)作为一种流行的对称加密算法,在数据库领域也得到了广泛应用。
MySQL作为最流行的关系型数据库管理系统之一,提供了内置函数和存储过程用于实现AES解密操作。
1.2 文章结构为了系统地介绍MySQL中的AES解密及其填充方法,本文将分为五个主要部分。
首先,引言部分将简述文章内容并概括本文结构。
其次,正文部分将首先对AES加密算法进行简单介绍,并重点阐述MySQL中的AES解密方法。
然后,将详细说明填充方法及其在MySQL中的应用。
接下来,将深入探讨AES解密过程的三个关键步骤,并逐步进行解释说明。
在第四部分中,通过给出操作实例和说明来进一步帮助读者理解如何使用MySQL内置函数以及自定义存储过程实现AES解密功能,并针对常见问题进行了注意事项和解答。
最后,在结论和总结部分,将总结已掌握的知识点,并对MySQL AES解密填充方法的理解和意义进行评价,同时对未来发展方向和可能改进的地方进行展望。
1.3 目的本文旨在帮助读者了解MySQL中的AES解密方法及其填充方法,并掌握如何使用相关函数和存储过程来实现AES解密操作。
通过对AES解密过程的详细解释和操作实例的演示,读者将能够深入理解AES解密的原理和应用,并能够灵活运用于实际项目中。
此外,本文还将介绍常见问题及其解答,以便读者更好地应对实际开发中可能遇到的挑战。
通过阅读本文,读者可以为数据库安全性提升做出贡献,保护重要数据免受未经授权访问和窃取的风险。
2. 正文:2.1 AES加密算法简介AES(Advanced Encryption Standard)是一种对称加密算法,是目前最常用的加密算法之一。
python实现AES加密解密
python实现AES加密解密本⽂实例为⼤家分享了python实现AES加密解密的具体代码,供⼤家参考,具体内容如下(1)对于AES加密解密相关知识(2)实现的功能就是输⼊0-16个字符,然后经过AES的加密解密最后可以得到原先的输⼊,运⾏的结果如下开始的字符串就是输⼊的明⽂,第⼀个矩阵,是明⽂对应的状态矩阵,下⾯的字典是得到的经过扩展后的密钥,再下⾯的矩阵是经过加密之后的矩阵,最后的矩阵就是解密之后的矩阵,最后的输出就是还原的明⽂,可以发现AES加密解密的过程没⽑病。
(3)字节代换:输⼊输出都是⼗六进制的矩阵格式,define_byte_subdtitution()函数的功能是完成字节代换,⾸先使⽤hex_to_int_number()函数将⼗六进制数转换为对应的⼗进制数,然后到S盒与逆S盒中进⾏字节的代换,这个过程中⽐较⿇烦的是S盒与逆S盒数据的输⼊,好家伙。
⽽逆字节代换就是使⽤逆S盒;(4)⾏移位:输⼊输出都是⼗六进制的矩阵格式,define_line_shift()函数是在加密时使⽤的,define_line_inverse_shift()函数是在解密时使⽤的;(5)列混合:输⼊是使⽤的⼗进制矩阵,输出是⼗六进制的矩阵,在列混合前为了⽅便操作,使⽤函数define_column_rotation()将矩阵进⾏了⾏列交换位置,然后对每⼀个数据进⾏操作,get_2()函数是实现与2相乘的结果,在加密与解密中会多次⽤到,XOR()函数实现两个⼆进制数的异或操作,在逆列混合中就是左乘的矩阵有所不同;(6)轮密钥加:输⼊输出都是⼗六进制的矩阵格式,在进⾏加密解密之前先将密钥进⾏扩展,得到加解密过程中使⽤的所有的密钥,并放在⼀个字典中,然后在加密解密过程中使⽤相应的密钥即可,get_extend_key()函数得到扩展密钥,⼀共有44个字,每次在进⾏轮密钥加时使⽤4个字,get_round_key_plus()函数实现轮密钥加的操作,就是进⾏异或操作;(7)最后就是实现加密与解密的详细的过程,其中的九轮是⼀样的,最后⼀轮单独拿出来进⾏处理即可,主要的问题可能会出现在⼀些⼩细节的处理上,像我遇到的就是在解密中控制使⽤轮密钥的变量k,开始把k放在了10轮循环中,导致k的值⼀直是初值没有改变,所以加密解密没有成功,之后我就在各个步骤中⼀个⼀个的测试,发现字节代换,⾏移位,列混合,甚⾄轮密钥加单独使⽤的时候都可以实现还原明⽂,然后,我⼜仔细的检查了下,加密解密的函数,终于发现了这个问题,问题虽⼩,但是影响很⼤,使得整个的程序没有得到预想的结果,幸好最后的结局还算满意,就是写的代码有点乱,⾃⼰也懒得改了,希望有⼤佬要是有什么意见,可以随时交流。
AES加密解密与代码实现详解
AES加密解密与代码实现详解AES(Advanced Encryption Standard)是一种对称加密算法,其安全性和性能都得到了广泛的认可和应用。
在AES中,采用的是分组密码算法,即将明文分组加密,每个明文分组的长度为128比特(16字节),密钥长度可为128比特、192比特或256比特。
1.初始化轮秘钥:根据密钥生成一系列轮秘钥,用于每轮加密操作。
2.轮加密:对明文进行一系列的轮操作,每轮操作包括字节代换、行移位、列混淆和轮秘钥加。
- 字节代换(SubBytes):将每个字节替换为S盒中对应字节的值,S盒是一个由固定变换生成的字节替代表。
- 行移位(ShiftRows):将第1、2、3行循环左移0、1、2个字节。
- 列混淆(MixColumns):通过一系列的线性变换,完成每个列的混淆操作。
- 轮秘钥加(AddRoundKey):将当前轮的秘钥与状态矩阵进行异或操作。
3.最后一轮加密操作:最后一轮操作不包括列混淆操作。
4.密文生成:将最后一轮加密操作的状态矩阵输出为密文。
解密操作与加密操作相反,主要是将轮操作中的逆变换应用到密文上,恢复出明文。
以下是一个AES加密解密算法的示例代码(使用Python语言实现):```pythonfrom Crypto.Cipher import AESfrom Crypto.Util.Padding import pad, unpadfrom Crypto.Random import get_random_bytes#生成一个随机的16字节密钥key = get_random_bytes(16)def encrypt(plain_text):#创建一个AES对象并使用密钥进行初始化cipher = AES.new(key, AES.MODE_ECB)#对明文进行填充padded_plain_text = pad(plain_text, 16)#加密明文cipher_text = cipher.encrypt(padded_plain_text) return cipher_textdef decrypt(cipher_text):#创建一个AES对象并使用密钥进行初始化cipher = AES.new(key, AES.MODE_ECB)#解密密文decrypted_text = cipher.decrypt(cipher_text)#对解密后的明文进行去填充plain_text = unpad(decrypted_text, 16)return plain_text#要加密的明文plain_text = b"Hello World!"#加密明文得到密文cipher_text = encrypt(plain_text)#解密密文得到明文decrypted_text = decrypt(cipher_text)print("明文:", plain_text)print("密文:", cipher_text)print("解密后明文:", decrypted_text)```通过以上代码,可以实现对称加密算法AES的加密和解密操作。
AES算法加密与解密的设计与实现
AES算法加密与解密的设计与实现
AES(Advanced Encryption Standard)是一种对称加密算法,其设计和实现确保了数据在传输和存储过程中的安全性。
AES算法被广泛应用于各种领域,包括网络通信、数据库存储和文件加密等。
一、AES算法的设计原理
1.替代和置换:AES算法将输入的明文数据进行初始处理,包括字节替代、行置换和列混淆等操作,以增加数据的混乱程度。
2.轮函数:AES算法使用多轮迭代的方式对数据进行加密。
每轮都使用一个轮密钥与数据进行异或运算,然后通过字节替代、行置换和列混淆等操作来加密数据。
3.密钥扩展:AES算法通过密钥扩展算法生成多轮的轮密钥,以增加密钥长度和复杂性,从而增强算法的安全性。
二、AES算法的实现过程
1.初始化:AES算法需要初始化密钥和输入明文数据。
密钥的长度可以是128位、192位或256位,根据密钥长度选择不同的密钥扩展算法。
2.密钥扩展:根据选定的密钥长度,使用密钥扩展算法生成多轮的轮密钥。
3.加密过程:将输入的明文数据按照分组长度(128位)进行划分,使用前面生成的轮密钥进行多轮的加密操作。
4.解密过程:与加密过程相反,使用逆向的字节替代、行置换和列混淆操作,以及逆向的轮密钥进行解密操作。
c,java,php,python和javascript的aes加密解密实现
C#, Java, PHP, Python 和Javascript 的AES 加密解密实现c#里面的AES加密解密其中加密后以及解密后的字符串都能成功打印,但Console.WriteLine( =3== 之后的输出就没有了,最后输出个线程返回值0,然后就没有然后了。
c#不懂,就不深究了,就已执行的部分,是符合要求了。
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Security.Cryptography;namespace testclass Class1static void Main(string[] args)Console.WriteLine( I am commingString source = Test StringString encryptData = Class1.Encrypt(source, 1234567812345678 , 1234567812345678Console.WriteLine( =1==Console.WriteLine(encryptData);Console.WriteLine( =2==String decryptData = Class1.Decrypt( 2fbwW9+8vPId2/foafZq6Q== , 1234567812345678 , 1234567812345678Console.WriteLine(decryptData);Console.WriteLine( =3==Console.WriteLine( I will go outpublic static string Encrypt(string toEncrypt, string key, string iv)byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.IV = ivArray;rDel.Mode = CipherMode.CBC;rDel.Padding = PaddingMode.Zeros;ICryptoTransform cTransform = rDel.CreateEncryptor();byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);return Convert.ToBase64String(resultArray, 0, resultArray.Length);public static string Decrypt(string toDecrypt, string key, string iv)byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);RijndaelManaged rDel = new RijndaelManaged();rDel.Key = keyArray;rDel.IV = ivArray;rDel.Mode = CipherMode.CBC;rDel.Padding = PaddingMode.Zeros;ICryptoTransform cTransform = rDel.CreateDecryptor();byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);return UTF8Encoding.UTF8.GetString(resultArray);}php的AES加密解密php代码,php很多东西都是提供好的,直接用函数,但是php目前所知填充模式只有ZeroPadding,于是其他语言就只能跟着它来了:php$privateKey = 1234567812345678$iv = 1234567812345678$data = Test String$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $privateKey, $data, MCRYPT_MODE_CBC, $iv);echo($encrypted);echo ‘ br/echo(base64_encode($encrypted));echo ‘ br/$encryptedData = base64_decode( 2fbwW9+8vPId2/foafZq6Q==$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $privateKey, $encryptedData, MCRYPT_MODE_CBC, $iv);echo($decrypted);Javascript下aes加解密需要在https:///p/crypto-js/下载工具包script type= text/javascript src= aes.js /scriptscript type= text/javascript src= pad-zeropadding.js /script导入文件,aes.js需要导入crypto-js压缩包中rollups文件夹下的那个aes.js文件,如果引入的是components文件夹下的aes.j s是会报错的script type= text/javascriptvar data = Test Stringvar key = tin1.parse(‘1234567812345678’);var iv = tin1.parse(‘1234567812345678’);//加密var encrypted = CryptoJS.AES.encrypt(data,key,{iv:iv,mode:CryptoJS.mode.CBC,padding:CryptoJS.pad.ZeroPad ding});document.write(encrypted.ciphertext);document.write(‘ br/document.write(encrypted.key);document.write(‘ br/document.write(encrypted.iv);document.write(‘ br/document.write(encrypted.salt);document.write(‘ br/document.write(encrypted);document.write(‘ br///解密var decrypted = CryptoJS.AES.decrypt(encrypted,key,{iv:iv,padding:CryptoJS.pad.ZeroPadding});console.log(decrypted.toString(CryptoJS.enc.Utf8));/scriptpython的AES加密解密最后加一个python下的aes,需要安装python Crypto:#!/usr/bin/env python# -*- coding: utf-8 -*-from Crypto.Cipher import AESimport base64PADDING = ‘\0’#PADDING = ‘ ‘pad_it = lambda s: s+(16 - len(s)%16)*PADDINGkey = ‘1234567812345678’iv = ‘1234567812345678’source = ‘Test String’generator = AES.new(key, AES.MODE_CBC, iv)crypt = generator.encrypt(pad_it(source))cryptedStr = base64.b64encode(crypt)print cryptedStrgenerator = AES.new(key, AES.MODE_CBC, iv)recovery = generator.decrypt(crypt)print recovery.rstrip(PADDING)注意python下需要用’\0’来填充,如果是空格来填充,python加密得到的字符串会跟其他语言不同。
C语言实现AES加密解密
C语言实现AES加密解密AES(Advanced Encryption Standard)是一种对称加密算法,它是目前广泛使用的加密标准之一、本文将介绍如何使用C语言实现AES加密和解密。
AES算法使用128位(16字节)的块进行加密和解密。
它支持128位、192位和256位长度的密钥。
在下面的示例中,我们将演示如何使用128位的密钥进行AES加密和解密。
首先,我们需要准备一个AES加密所需的密钥。
我们可以通过一个字符串来表示密钥,然后将其转换为字节数组。
在C语言中,可以使用`strncpy`函数将字符串复制到字节数组中。
```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <openssl/aes.h>#define AES_KEY_SIZE 128int mai//准备AES密钥unsigned char key[AES_KEY_SIZE/8];strncpy((char*)key, keyStr, AES_KEY_SIZE/8);//创建AES加密上下文AES_KEY aesKey;AES_set_encrypt_key(key, AES_KEY_SIZE, &aesKey); //待加密的数据unsigned char input[] = "Hello, AES!";int inputLen = sizeof(input)/sizeof(input[0]); //加密数据unsigned char encrypted[AES_BLOCK_SIZE];AES_encrypt(input, encrypted, &aesKey);//输出加密结果printf("Encrypted: ");for (int i = 0; i < AES_BLOCK_SIZE; i++)printf("%02x", encrypted[i]);}printf("\n");//创建AES解密上下文AES_set_decrypt_key(key, AES_KEY_SIZE, &aesKey); //解密数据unsigned char decrypted[AES_BLOCK_SIZE];AES_decrypt(encrypted, decrypted, &aesKey);//输出解密结果printf("Decrypted: ");for (int i = 0; i < AES_BLOCK_SIZE; i++)printf("%c", decrypted[i]);}printf("\n");return 0;```在上面的示例中,我们使用OpenSSL库提供的AES函数来执行加密和解密操作。
AES加密算法的原理详解与实现分析
AES加密算法的原理详解与实现分析AES(Advanced Encryption Standard)是一种对称加密算法,使用相同的密钥进行加密和解密操作。
它是目前应用最广泛的加密算法之一,被广泛用于保护数据的安全性。
AES的原理可以分为四个主要步骤:字节代换(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。
字节代换(SubBytes):AES中使用的S盒(Substitution box)是AES中唯一一个非线性元素。
S盒是一个16×16的字节查找表,将输入的每个字节替换为查找表中对应的字节。
通过这种替换,AES增加了非线性性,增强了加密的安全性。
行移位(ShiftRows):AES的状态矩阵被转换为四行四列的矩阵。
在行移位阶段,每一行循环左移不同的位数。
第一行不变,第二行左移一位,第三行左移两位,第四行左移三位。
这个操作使得矩阵中的每个字节在不同的列中被混淆,增加了加密的随机性。
列混淆(MixColumns):在列混淆阶段,每一列都与一个固定的矩阵进行乘法运算。
这个固定矩阵称为混淆矩阵。
列混淆阶段通过改变每一列中的字节,增加了密文中每个字节之间的相关性,增强了加密的安全性。
轮密钥加(AddRoundKey):AES使用一个密钥扩展算法生成轮密钥,在每一轮加密中,将对应轮的密钥与状态矩阵进行异或运算。
这个操作可以认为是对状态矩阵进行了"加密",增加了加密的复杂性。
AES加密的实现可以通过软件或硬件来完成。
在软件实现中,可以通过编程语言如C、C++、Java等来实现AES算法。
在硬件实现中,可以通过使用FPGA(Field-Programmable Gate Array)或ASIC(Application-Specific Integrated Circuit)等专门的硬件设备来加速加密的过程。
AES算法的实现需要注意以下几个关键点:1.如何选择密钥长度:AES算法支持多种密钥长度,包括128位、192位和256位。
AES加密解密(根据指定秘钥)
AES加密解密(根据指定秘钥)最近在做调⽤第三⽅接⼝,要求⼊参AES加密,并且秘钥为16位的长度,在此记录⼀下。
⾸先引⽤命名空间:using System.IO;using System.Text;using System.Security.Cryptography;1///<summary>2/// AES加密(⽆向量)3///</summary>4///<param name="plainBytes">被加密的明⽂</param>5///<param name="key">密钥</param>6///<returns>密⽂</returns>7public string AESEncrypt(string Data, string Key)8 {9 MemoryStream mStream = new MemoryStream();10 RijndaelManaged aes = new RijndaelManaged();1112byte[] plainBytes = Encoding.UTF8.GetBytes(Data);13 Byte[] bKey = new Byte[16];14 Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);1516 aes.Mode = CipherMode.ECB;17 aes.Padding = PaddingMode.PKCS7;18 aes.KeySize = 128;19//aes.Key = _key;20 aes.Key = bKey;21//aes.IV = _iV;22 CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateEncryptor(), CryptoStreamMode.Write);23try24 {25 cryptoStream.Write(plainBytes, 0, plainBytes.Length);26 cryptoStream.FlushFinalBlock();27return Convert.ToBase64String(mStream.ToArray());28 }29finally30 {31 cryptoStream.Close();32 mStream.Close();33 aes.Clear();34 }35 }1#region解密2///<summary>3/// AES解密(⽆向量)4///</summary>5///<param name="encryptedBytes">被加密的明⽂</param>6///<param name="key">密钥</param>7///<returns>明⽂</returns>8public string AESDecrypt(String Data, String Key)9 {10 Byte[] encryptedBytes = Convert.FromBase64String(Data);11 Byte[] bKey = new Byte[16];12 Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);1314 MemoryStream mStream = new MemoryStream(encryptedBytes);15//mStream.Write( encryptedBytes, 0, encryptedBytes.Length );16//mStream.Seek( 0, SeekOrigin.Begin );17 RijndaelManaged aes = new RijndaelManaged();18 aes.Mode = CipherMode.ECB;19 aes.Padding = PaddingMode.PKCS7;20 aes.KeySize = 128;21 aes.Key = bKey;22//aes.IV = _iV;23 CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Read);24try25 {26byte[] tmp = new byte[encryptedBytes.Length + 32];27int len = cryptoStream.Read(tmp, 0, encryptedBytes.Length + 32);28byte[] ret = new byte[len];29 Array.Copy(tmp, 0, ret, 0, len);30return Encoding.UTF8.GetString(ret);31 }32finally33 {34 cryptoStream.Close();35 mStream.Close();36 aes.Clear();37 }38 }39#endregion调⽤时:string sendData = publicSH.AESDecrypt(sendData, "HYYSIENDEUFHVKDA");//返回信息解密 sendData 为要加密或者解密的信息,第⼆个参数是16位的秘钥。
Python的AES加密与解密
Python的AES加密与解密AES加密⽅式有五种:ECB, CBC, CTR, CFB, OFB从安全性⾓度推荐CBC加密⽅法,本⽂介绍了CBC,ECB两种加密⽅法的python实现python 在 Windows下使⽤AES时要安装的是pycryptodome 模块 pip install pycryptodome python 在 Linux下使⽤AES时要安装的是pycrypto模块 pip install pycryptoCBC加密需要⼀个⼗六位的key(密钥)和⼀个⼗六位iv(偏移量)ECB加密不需要ivAES CBC 加密的python实现1from Crypto.Cipher import AES2from binascii import b2a_hex, a2b_hex345# 如果text不⾜16位的倍数就⽤空格补⾜为16位6def add_to_16(text):7if len(text.encode('utf-8')) % 16:8 add = 16 - (len(text.encode('utf-8')) % 16)9else:10 add = 011 text = text + ('\0' * add)12return text.encode('utf-8')131415# 加密函数16def encrypt(text):17 key = '9999999999999999'.encode('utf-8')18 mode = AES.MODE_CBC19 iv = b'qqqqqqqqqqqqqqqq'20 text = add_to_16(text)21 cryptos = AES.new(key, mode, iv)22 cipher_text = cryptos.encrypt(text)23# 因为AES加密后的字符串不⼀定是ascii字符集的,输出保存可能存在问题,所以这⾥转为16进制字符串24return b2a_hex(cipher_text)252627# 解密后,去掉补⾜的空格⽤strip() 去掉28def decrypt(text):29 key = '9999999999999999'.encode('utf-8')30 iv = b'qqqqqqqqqqqqqqqq'31 mode = AES.MODE_CBC32 cryptos = AES.new(key, mode, iv)33 plain_text = cryptos.decrypt(a2b_hex(text))34return bytes.decode(plain_text).rstrip('\0')353637if__name__ == '__main__':38 e = encrypt("hello world") # 加密39 d = decrypt(e) # 解密40print("加密:", e)41print("解密:", d)AES ECB加密的python实现1"""2ECB没有偏移量3"""4from Crypto.Cipher import AES5from binascii import b2a_hex, a2b_hex678def add_to_16(text):9if len(text.encode('utf-8')) % 16:10 add = 16 - (len(text.encode('utf-8')) % 16)11else:12 add = 013 text = text + ('\0' * add)14return text.encode('utf-8')151617# 加密函数18def encrypt(text):19 key = '9999999999999999'.encode('utf-8')20 mode = AES.MODE_ECB21 text = add_to_16(text)22 cryptos = AES.new(key, mode)2324 cipher_text = cryptos.encrypt(text)25return b2a_hex(cipher_text)262728# 解密后,去掉补⾜的空格⽤strip() 去掉29def decrypt(text):30 key = '9999999999999999'.encode('utf-8')31 mode = AES.MODE_ECB32 cryptor = AES.new(key, mode)33 plain_text = cryptor.decrypt(a2b_hex(text)) 34return bytes.decode(plain_text).rstrip('\0') 353637if__name__ == '__main__':38 e = encrypt("hello world") # 加密39 d = decrypt(e) # 解密40print("加密:", e)41print("解密:", d)。
js aes加密使用方法
js aes加密使用方法摘要:1.JS AES加密简介2.JS AES加密使用方法3.示例代码及解析4.加密和解密实战应用5.安全性与性能考虑正文:近年来,网络安全越来越受到重视,加密技术在保障数据安全方面发挥着重要作用。
在JavaScript中,AES加密算法是一种常用的加密方法。
本文将详细介绍JS AES加密的使用方法,并通过示例代码演示如何在实际项目中应用加密和解密技术。
一、JS AES加密简介AES(Advanced Encryption Standard)是一种对称加密算法,其核心思想是将原始数据分成128位、192位或256位块,然后通过多轮加密操作生成密文。
在JavaScript中,我们可以使用第三方库如`crypto-js`来实现AES加密和解密功能。
二、JS AES加密使用方法1.安装`crypto-js`库:```bashpm install crypto-js```2.导入相关模块:```javascriptconst CryptoJS = require("crypto-js");```3.初始化加密器:```javascriptconst secretKey = "your-secret-key"; // 密钥长度为16字节const cipherText = CryptoJS.AES.encrypt(plainText, secretKey).toString(); // 加密原始数据const encryptedData = CryptoJS.AES.encrypt(data, secretKey).toString(); // 加密JSON数据```4.解密数据:```javascriptconst encryptedData = "your-encrypted-data";const decryptedData = CryptoJS.AES.decrypt(encryptedData, secretKey).toString(CryptoJS.enc.Utf8); // 解密JSON数据const decryptedText = CryptoJS.AES.decrypt(cipherText, secretKey).toString(CryptoJS.enc.Utf8); // 解密原始数据```三、示例代码及解析以下是一个简单的加密和解密示例:```javascript// 原始数据const plainT ext = "Hello, World!";// 生成密钥const secretKey = CryptoJS.enc.Utf8.parse("your-secret-key");// 加密原始数据const cipherText = CryptoJS.AES.encrypt(plainText, secretKey).toString();console.log("加密后的文本:", cipherText);// 加密JSON数据const data = {text: "Hello, World!",num: 123};const encryptedData = CryptoJS.AES.encrypt(JSON.stringify(data), secretKey).toString();console.log("加密后的JSON数据:", encryptedData);// 解密JSON数据const decryptedData = CryptoJS.AES.decrypt(encryptedData, secretKey).toString(CryptoJS.enc.Utf8);console.log("解密后的JSON数据:", decryptedData);// 解密原始数据const decryptedText = CryptoJS.AES.decrypt(cipherText, secretKey).toString(CryptoJS.enc.Utf8);console.log("解密后的文本:", decryptedText);```四、加密和解密实战应用在实际项目中,我们可以使用JS AES加密算法对敏感数据进行加密存储,同时在需要使用时进行解密。
AES加密算法C++实现
AES加密算法C++实现 我从⽹上下载了⼀套AES加密算法的C++实现,代码如下:(1)aes.h#ifndef SRC_UTILS_AES_H#define SRC_UTILS_AES_Hclass AES{public:AES(unsigned char* key);virtual ~AES();unsigned char* Cipher(unsigned char* input); // 加密,传⼊的数组⼤⼩必须是16字节unsigned char* InvCipher(unsigned char* input); // 解密,传⼊的数组也必须是16字节void* Cipher(void* input, int length=0); // 可以传⼊数组,⼤⼩必须是16的整数倍,如果不是将会越界操作;如果不传length⽽默认为0,那么将按照字符串处理,遇'\0'结束void* InvCipher(void* input, int length); // 必须传⼊数组和⼤⼩,必须是16的整数倍private:unsigned char Sbox[256];unsigned char InvSbox[256];unsigned char w[11][4][4];void KeyExpansion(unsigned char* key, unsigned char w[][4][4]);unsigned char FFmul(unsigned char a, unsigned char b);void SubBytes(unsigned char state[][4]);void ShiftRows(unsigned char state[][4]);void MixColumns(unsigned char state[][4]);void AddRoundKey(unsigned char state[][4], unsigned char k[][4]);void InvSubBytes(unsigned char state[][4]);void InvShiftRows(unsigned char state[][4]);void InvMixColumns(unsigned char state[][4]);};#endif// SRC_UTILS_AES_H(2)aes.cpp1 #include "aes.h"2 #include "string.h"34 AES::AES(unsigned char* key)5 {6 unsigned char sBox[] =7 { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */80x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, /*0*/90xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, /*1*/100xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, /*2*/110x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, /*3*/120x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, /*4*/130x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, /*5*/140xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, /*6*/150x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, /*7*/160xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, /*8*/170x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, /*9*/180xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, /*a*/190xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, /*b*/200xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, /*c*/210x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, /*d*/220xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, /*e*/230x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16/*f*/24 };25 unsigned char invsBox[256] =26 { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */270x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, /*0*/280x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, /*1*/290x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, /*2*/300x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, /*3*/310x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, /*4*/320x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, /*5*/330x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, /*6*/340xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, /*7*/350x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, /*8*/360x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, /*9*/370x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, /*a*/380xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, /*b*/390x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, /*c*/400x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, /*d*/410xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, /*e*/420x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d/*f*/43 };44 memcpy(Sbox, sBox, 256);45 memcpy(InvSbox, invsBox, 256);46 KeyExpansion(key, w);47 }49 AES::~AES()50 {5152 }5354 unsigned char* AES::Cipher(unsigned char* input)55 {56 unsigned char state[4][4];57int i,r,c;5859for(r=0; r<4; r++)60 {61for(c=0; c<4 ;c++)62 {63 state[r][c] = input[c*4+r];64 }65 }6667 AddRoundKey(state,w[0]);6869for(i=1; i<=10; i++)70 {71 SubBytes(state);72 ShiftRows(state);73if(i!=10)MixColumns(state);74 AddRoundKey(state,w[i]);75 }7677for(r=0; r<4; r++)78 {79for(c=0; c<4 ;c++)80 {81 input[c*4+r] = state[r][c];82 }83 }8485return input;86 }8788 unsigned char* AES::InvCipher(unsigned char* input)89 {90 unsigned char state[4][4];91int i,r,c;9293for(r=0; r<4; r++)94 {95for(c=0; c<4 ;c++)96 {97 state[r][c] = input[c*4+r];98 }99 }100101 AddRoundKey(state, w[10]);102for(i=9; i>=0; i--)103 {104 InvShiftRows(state);105 InvSubBytes(state);106 AddRoundKey(state, w[i]);107if(i)108 {109 InvMixColumns(state);110 }111 }112113for(r=0; r<4; r++)114 {115for(c=0; c<4 ;c++)116 {117 input[c*4+r] = state[r][c];118 }119 }120121return input;122 }123124void* AES::Cipher(void* input, int length)125 {126 unsigned char* in = (unsigned char*) input;127int i;128if(!length) // 如果是0则当做字符串处理129 {130while(*(in+length++));131in = (unsigned char*) input;132 }133for(i=0; i<length; i+=16)134 {135 Cipher(in+i);136 }137return input;139140void* AES::InvCipher(void* input, int length)141 {142 unsigned char* in = (unsigned char*) input;143int i;144for(i=0; i<length; i+=16)145 {146 InvCipher(in+i);147 }148return input;149 }150151void AES::KeyExpansion(unsigned char* key, unsigned char w[][4][4])152 {153int i,j,r,c;154 unsigned char rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; 155for(r=0; r<4; r++)156 {157for(c=0; c<4; c++)158 {159 w[0][r][c] = key[r+c*4];160 }161 }162for(i=1; i<=10; i++)163 {164for(j=0; j<4; j++)165 {166 unsigned char t[4];167for(r=0; r<4; r++)168 {169 t[r] = j ? w[i][r][j-1] : w[i-1][r][3];170 }171if(j == 0)172 {173 unsigned char temp = t[0];174for(r=0; r<3; r++)175 {176 t[r] = Sbox[t[(r+1)%4]];177 }178 t[3] = Sbox[temp];179 t[0] ^= rc[i-1];180 }181for(r=0; r<4; r++)182 {183 w[i][r][j] = w[i-1][r][j] ^ t[r];184 }185 }186 }187 }188189 unsigned char AES::FFmul(unsigned char a, unsigned char b)190 {191 unsigned char bw[4];192 unsigned char res=0;193int i;194 bw[0] = b;195for(i=1; i<4; i++)196 {197 bw[i] = bw[i-1]<<1;198if(bw[i-1]&0x80)199 {200 bw[i]^=0x1b;201 }202 }203for(i=0; i<4; i++)204 {205if((a>>i)&0x01)206 {207 res ^= bw[i];208 }209 }210return res;211 }212213void AES::SubBytes(unsigned char state[][4])214 {215int r,c;216for(r=0; r<4; r++)217 {218for(c=0; c<4; c++)219 {220 state[r][c] = Sbox[state[r][c]];221 }222 }223 }224225void AES::ShiftRows(unsigned char state[][4])226 {227 unsigned char t[4];228int r,c;229for(r=1; r<4; r++)230 {231for(c=0; c<4; c++)232 {233 t[c] = state[r][(c+r)%4];234 }235for(c=0; c<4; c++)236 {237 state[r][c] = t[c];238 }239 }240 }241242void AES::MixColumns(unsigned char state[][4])243 {244 unsigned char t[4];245int r,c;246for(c=0; c< 4; c++)247 {248for(r=0; r<4; r++)249 {250 t[r] = state[r][c];251 }252for(r=0; r<4; r++)253 {254 state[r][c] = FFmul(0x02, t[r])255 ^ FFmul(0x03, t[(r+1)%4])256 ^ FFmul(0x01, t[(r+2)%4])257 ^ FFmul(0x01, t[(r+3)%4]);258 }259 }260 }261262void AES::AddRoundKey(unsigned char state[][4], unsigned char k[][4]) 263 {264int r,c;265for(c=0; c<4; c++)266 {267for(r=0; r<4; r++)268 {269 state[r][c] ^= k[r][c];270 }271 }272 }273274void AES::InvSubBytes(unsigned char state[][4])275 {276int r,c;277for(r=0; r<4; r++)278 {279for(c=0; c<4; c++)280 {281 state[r][c] = InvSbox[state[r][c]];282 }283 }284 }285286void AES::InvShiftRows(unsigned char state[][4])287 {288 unsigned char t[4];289int r,c;290for(r=1; r<4; r++)291 {292for(c=0; c<4; c++)293 {294 t[c] = state[r][(c-r+4)%4];295 }296for(c=0; c<4; c++)297 {298 state[r][c] = t[c];299 }300 }301 }302303void AES::InvMixColumns(unsigned char state[][4])304 {305 unsigned char t[4];306int r,c;307for(c=0; c< 4; c++)308 {309for(r=0; r<4; r++)310 {311 t[r] = state[r][c];312 }313for(r=0; r<4; r++)314 {315 state[r][c] = FFmul(0x0e, t[r])316 ^ FFmul(0x0b, t[(r+1)%4])317 ^ FFmul(0x0d, t[(r+2)%4])318 ^ FFmul(0x09, t[(r+3)%4]);319 }320 }321 }View Code 上⾯的加密算法是没问题的,但是接⼝有两个需要注意的地⽅,也就是在头⽂件中备注的地⽅:1、数组的⼤⼩必须是16字节或者16的整数倍。
A E S 加 密 算 法 的 详 细 介 绍
Java 实现 AES 对称加密算法的加密和解密AES(Advanced Encryption Standard,高级加密标准)是一种对称加密算法,加密和解密使用相同的密钥。
1. AES 加密-解密代码实例Java 代码实现 AES 加密-解密一般步骤:先根据原始的密码(字节数组-字符串)生成 AES密钥对象;再使用 AES密钥对象加密-解密数据。
package com.xiets.aes;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import java.security.SecureRandom;* @author xietanshengpublic class Main {public static void main(String[] args) throws Exception { String key = "123456"; -- AES加密-解密用的原始密码-- 加密数据, 返回密文byte[] cipherBytes = encrypt(content.getBytes(), key.getBytes());-- 解密数据, 返回明文byte[] plainBytes = decrypt(cipherBytes, key.getBytes());-- 输出解密后的明文: "Hello world!"System.out.println(new String(plainBytes));* 生成密钥对象private static SecretKey generateKey(byte[] key) throws Exception {-- 根据指定的 RNG 算法, 创建安全随机数生成器SecureRandom random = SecureRandom.getInstance("SHA1PRNG");-- 设置密钥key的字节数组作为安全随机数生成器的种子random.setSeed(key);-- 创建 AES算法生成器KeyGenerator gen = KeyGenerator.getInstance("AES");-- 初始化算法生成器gen.init(128, random);-- 生成 AES密钥对象, 也可以直接创建密钥对象: return new SecretKeySpec(key, ALGORITHM);return gen.generateKey();* 数据加密: 明文 - 密文public static byte[] encrypt(byte[] plainBytes, byte[] key) throws Exception {-- 生成密钥对象SecretKey secKey = generateKey(key);-- 获取 AES 密码器Cipher cipher = Cipher.getInstance("AES");-- 初始化密码器(加密模型)cipher.init(Cipher.ENCRYPT_MODE, secKey);-- 加密数据, 返回密文return cipher.doFinal(plainBytes);* 数据解密: 密文 - 明文public static byte[] decrypt(byte[] cipherBytes, byte[] key) throws Exception {-- 生成密钥对象SecretKey secKey = generateKey(key);-- 获取 AES 密码器Cipher cipher = Cipher.getInstance("AES");-- 初始化密码器(解密模型)cipher.init(Cipher.DECRYPT_MODE, secKey);-- 解密数据, 返回明文return cipher.doFinal(cipherBytes);2. AES 工具类封装: AESUtils.java为了方便直接使用,将 AES 加密-解密相关方法封装成工具类,并且支持对文件的 AES 加密-解密。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
先搞定AES算法,基本变换包括SubBytes(字节替代)、ShiftRows(行移位)、MixColumns(列混淆)、AddRoundKey(轮密钥加)
其算法一般描述为
明文及密钥的组织排列方式
ByteSubstitution(字节替代)
非线性的字节替代,单独处理每个字节:
求该字节在有限域GF(28)上的乘法逆,"0"被映射为自身,即对于α∈GF(28),求β∈GF(28),
使得α·β=β·α=1mod(x8+x4+x2+x+1)。
对上一步求得的乘法逆作仿射变换
y i=x i + x(i+4)mod8 + x(i+6)mod8 + x(i+7)mod8 + c i
(其中c i是6310即011000112的第i位),用矩阵表示为
本来打算把求乘法逆和仿射变换算法敲上去,最后还是放弃了...直接打置换表
下面是逆置换表,解密时使用
这里遇到问题了,本来用纯c初始化数组很正常,封装成类以后发现不能初始化,不管是声明、构造函数都无法初始化,百歌谷度了一通后没有任何答案,无奈只能在构造函数中声明一个局部变量数组并初始化,然后用memcpy,(成员变量名为Sbox/InvSbox,局部变量名sBox/invsBox)
ShiftRows(行移位变换)
行移位变换完成基于行的循环位移操作,变换方法:
即行移位变换作用于行上,第0行不变,第1行循环左移1个字节,第2行循环左移2个字节,第3行循环左移3个字节。
MixColumns(列混淆变换)
逐列混合,方法:
b(x) = (03·x3 + 01·x2 + 01·x + 02) · a(x) mod(x4 + 1)
其中FFmul为有限域GF(28)上的乘法,标准算法应该是循环8次(b与a的每一位相乘,结果相加),但这里只用到最低2位,解密时用到的逆列混淆也只用了低4位,所以在这里高4位的运算是多余的,只计算低4位。
AddRoundKey(轮密钥加变换)
简单来说就是逐字节相加,有限域GF(28)上的加法是模2加法,即异或
void AES::AddRoundKey(unsigned char state[][4], unsigned char k[][4])
{
int r,c;
for(c=0; c<4; c++)
{
for(r=0; r<4; r++)
{
state[r][c] ^= k[r][c];
}
}
}
KeyExpansion(密钥扩展)
将输入的密钥扩展为11组128位密钥组,其中第0组为输入密钥本身
其后第n组第i列为第n-1组第i列与第n组第i-1列之和(模2加法,1<= i <=3)
对于每一组第一列即i=0,有特殊的处理
将前一列即第n-1组第3列的4个字节循环左移1个字节,
并对每个字节进行字节替代变换SubBytes
将第一行(即第一个字节)与轮常量rc[n]相加
最后再与前一组该列相加
void AES::KeyExpansion(unsigned char* key, unsigned char w[][4][4])
{
int i,j,r,c;
unsigned char rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
for(r=0; r<4; r++)
{
for(c=0; c<4; c++)
{
w[0][r][c] = key[r+c*4];
}
}
for(i=1; i<=10; i++)
{
for(j=0; j<4; j++)
{
unsigned char t[4];
for(r=0; r<4; r++)
{
t[r] = j ? w[i][r][j-1] : w[i-1][r][3];
}
if(j == 0)
{
unsigned char temp = t[0];
for(r=0; r<3; r++)
{
t[r] = Sbox[t[(r+1)%4]];
}
t[3] = Sbox[temp];
t[0] ^= rc[i-1];
}
for(r=0; r<4; r++)
{
w[i][r][j] = w[i-1][r][j] ^ t[r];
}
}
}
}
解密的基本运算
AES解密算法与加密不同,基本运算中除了AddRoundKey(轮密钥加)不变外,其余的都需要进行逆变换,即
InvSubBytes(逆字节替代)、InvShiftRows(逆行移位)、InvMixColumns (逆列混淆)
加密过程
先将输入的明文按列序组合成4*4的矩阵,直接与第0组密钥(即输入的密钥)相加(异或),作为轮加密的输入
然后循环10次进行SubBytes、ShiftRows、MixColumns、AddRoundKey 运算,最后恢复原序列
需要注意的是最后一轮并不进行MixColumns(列混淆变换)
unsigned char* AES::Cipher(unsigned char* input)
{
unsigned char state[4][4];
int i,r,c;
for(r=0; r<4; r++){
for(c=0; c<4 ;c++) {
state[r][c] = input[c*4+r];
}
}
AddRoundKey(state,w[0]);
for(i=1; i<=10; i++){
SubBytes(state);
ShiftRows(state);
if(i!=10)MixColumns(state);
AddRoundKey(state,w[i]);
}
for(r=0; r<4; r++) {
for(c=0; c<4 ;c++){
input[c*4+r] = state[r][c];
}
}
return input;
}
解密过程
unsigned char* AES::InvCipher(unsigned char* input) {
unsigned char state[4][4];
int i,r,c;
for(r=0; r<4; r++)
{
for(c=0; c<4 ;c++)
{
state[r][c] = input[c*4+r];
}
}
AddRoundKey(state, w[10]);
for(i=9; i>=0; i--)
{
InvShiftRows(state);
InvSubBytes(state);
AddRoundKey(state, w[i]);
if(i)InvMixColumns(state);
}
for(r=0; r<4; r++)
{
for(c=0; c<4 ;c++)
{
input[c*4+r] = state[r][c];
}
}
return input;
}
对外部数据的加密/解密
至此已经实现了AES加密与解密的原型,在使用的时候一般处理的是字符串等,而不是直接传入128位的数据,所以要封装一下对外部数据的加解密处理
void* AES::Cipher(void* input, int length)
{
unsigned char* in = (unsigned char*) input;
int i;
if(!length) {
while(*(in+length++));
in = (unsigned char*) input;
}
for(i=0; i<length; i+=16){
Cipher(in+i);
}
return input;
}
void* AES::InvCipher(void* input, int length){
unsigned char* in = (unsigned char*) input;
int i;
for(i=0; i<length; i+=16){
InvCipher(in+i);
}
return input;
}
加密时默认参数length=0,为要加密的数据长度,如果使用默认值,则作为字符串处理,以'\0'为结尾计算长度
加密时传进的指针要预留够16整数倍字节的空间,因为加密操作直接修改原数据,不足128位可能造成内存溢出。