Rijndael Advanced Encryption Standard
- 格式:ppt
- 大小:97.50 KB
- 文档页数:15
AES加密算法原理AES加密算法原理AES是作为DES的替代标准出现的,全称Advanced Encryption Standard,即:高级加密标准。
AES加密算法,经历了公开的选拔,最终2000年,由比利时密码学家Joan Daemen和Vincent Rijmen设计的Rijndael算法被选中,成为了AES标准。
AES明文分组长度为128位,即16个字节,密钥长度可以为16个字节、24个字节、或32个字节,即128位密钥、192位密钥、或256位密钥。
总体结构AES中没有使用Feistel网络,其结构称为SPN结构。
和DES相同,AES也由多个轮组成,其中每个轮分为SubBytes、ShiftRows、MixColumns、AddRoundKey 4个步骤,即:字节代替、行移位、列混淆和轮密钥加。
根据密钥长度不同,所需轮数也不同,128位、192位、256位密钥,分别需要10轮、12轮和14轮。
第1轮之前有一次AddRoundKey,即轮密钥加,可以视为第0轮;之后1至N-1轮,执行SubBytes、ShiftRows、MixColumns、AddRoundKey;最后一轮仅包括:SubBytes、MixColumns、AddRoundKey。
AES总体结构示意图:加密整体流程加密的代码实现:func encryptBlockGo(xk []uint32, dst, src []byte) {var s0, s1, s2, s3, t0, t1, t2, t3 uint32--按4x4矩阵排列s0 = uint32(src[0])24 | uint32(src[1])16 | uint32(src[2])8 | uint32(src[3])s1 = uint32(src[4])24 | uint32(src[5])16 | uint32(src[6])8 | uint32(src[7])s2 = uint32(src[8])24 | uint32(src[9])16 | uint32(src[10])8 | uint32(src[11])s3 = uint32(src[12])24 | uint32(src[13])16 | uint32(src[14])8 | uint32(src[15])-- 第1次轮密钥加s0 ^= xk[0]s1 ^= xk[1]s2 ^= xk[2]s3 ^= xk[3]--nr为中间重复轮数--例如128位密钥,44字子密钥,此处为9轮---2位去除开头和结尾轮nr := len(xk)-4 - 2--4表示已使用了4个字子密钥for r := 0; r nr; r++ {--此处代码包括字节代替、行移位、列混淆、轮密钥加t0 = xk[k+0] ^ te0[uint8(s024)] ^ te1[uint8(s116)] ^ te2[uint8(s28)] ^ te3[uint8(s3)]t1 = xk[k+1] ^ te0[uint8(s124)] ^ te1[uint8(s216)] ^ te2[uint8(s38)] ^ te3[uint8(s0)]t2 = xk[k+2] ^ te0[uint8(s224)] ^ te1[uint8(s316)] ^ te2[uint8(s08)] ^ te3[uint8(s1)]t3 = xk[k+3] ^ te0[uint8(s324)] ^ te1[uint8(s016)] ^ te2[uint8(s18)] ^ te3[uint8(s2)]s0, s1, s2, s3 = t0, t1, t2, t3--最后一轮仅包括字节代替、行移位、轮密钥加--此处为字节代替和行移位s0 = uint32(sbox0[t024])24 | uint32(sbox0[t1160xff])16 | uint32(sbox0[t280xff])8 | uint32(sbox0[t30xff])s1 = uint32(sbox0[t124])24 | uint32(sbox0[t2160xff])16 | uint32(sbox0[t380xff])8 | uint32(sbox0[t00xff])s2 = uint32(sbox0[t224])24 | uint32(sbox0[t3160xff])16 | uint32(sbox0[t080xff])8 | uint32(sbox0[t10xff])s3 = uint32(sbox0[t324])24 | uint32(sbox0[t0160xff])16 | uint32(sbox0[t180xff])8 | uint32(sbox0[t20xff])--轮密钥加s0 ^= xk[k+0]s1 ^= xk[k+1]s2 ^= xk[k+2]s3 ^= xk[k+3]dst[0], dst[1], dst[2], dst[3] = byte(s024), byte(s016), byte(s08), byte(s0)dst[4], dst[5], dst[6], dst[7] = byte(s124), byte(s116), byte(s18), byte(s1)dst[8], dst[9], dst[10], dst[11] = byte(s224), byte(s216), byte(s28), byte(s2)dst[12], dst[13], dst[14], dst[15] = byte(s324), byte(s316), byte(s38), byte(s3)密钥扩展Nk表示初始密钥的字数,一个字为4个字节,以16字节初始密钥为例,初始密钥共计4个字。
Android数据加密之Aes加密前⾔:项⽬中除了登陆,⽀付等接⼝采⽤rsa⾮对称加密,之外的采⽤aes对称加密,今天我们来认识⼀下aes加密。
其他⼏种加密⽅式:•Android数据加密之Rsa加密•Android数据加密之Aes加密•Android数据加密之Des加密•Android数据加密之MD5加密•Android数据加密之Base64编码算法•Android数据加密之SHA安全散列算法什么是aes加密?⾼级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中⼜称Rijndael加密法,是美国联邦政府采⽤的⼀种区块加密标准。
这个标准⽤来替代原先的DES,已经被多⽅分析且⼴为全世界所使⽤。
接下来我们来实际看下具体怎么实现:对于AesUtils类常量简介:private final static String HEX = "0123456789ABCDEF";private static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";//AES是加密⽅式 CBC是⼯作模式 PKCS5Padding是填充模式private static final String AES = "AES";//AES 加密private static final String SHA1PRNG="SHA1PRNG";//// SHA1PRNG 强随机种⼦算法, 要区别4.2以上版本的调⽤⽅法如何⽣成⼀个随机Key?/** ⽣成随机数,可以当做动态的密钥加密和解密的密钥必须⼀致,不然将不能解密*/public static String generateKey() {try {SecureRandom localSecureRandom = SecureRandom.getInstance(SHA1PRNG);byte[] bytes_key = new byte[20];localSecureRandom.nextBytes(bytes_key);String str_key = toHex(bytes_key);return str_key;} catch (Exception e) {e.printStackTrace();}return null;}Aes密钥处理// 对密钥进⾏处理private static byte[] getRawKey(byte[] seed) throws Exception {KeyGenerator kgen = KeyGenerator.getInstance(AES);//for androidSecureRandom sr = null;// 在4.2以上版本中,SecureRandom获取⽅式发⽣了改变if (android.os.Build.VERSION.SDK_INT >= 17) {sr = SecureRandom.getInstance(SHA1PRNG, "Crypto");} else {sr = SecureRandom.getInstance(SHA1PRNG);}// for Java// secureRandom = SecureRandom.getInstance(SHA1PRNG);sr.setSeed(seed);kgen.init(128, sr); //256 bits or 128 bits,192bits//AES中128位密钥版本有10个加密循环,192⽐特密钥版本有12个加密循环,256⽐特密钥版本则有14个加密循环。
AES128_CBC模式加密 ⾼级加密标准(英语:Advanced Encryption Standard,缩写:AES),在中⼜称Rijndael加密法,是采⽤的⼀种区块加密标准。
这个标准⽤来替代原先的,已经被多⽅分析且⼴为全世界所使⽤。
经过五年的甄选流程,⾼级加密标准由(NIST)于2001年11⽉26⽇发布于FIPS PUB 197,并在2002年5⽉26⽇成为有效的标准。
2006年,⾼级加密标准已然成为对称密钥加密中最流⾏的算法之⼀。
原始字符串:SuperDo.Team 加密后字符串:f3de96947b786e45fe338f06e2baeb2a2.字符串解密(iOS) [1].对NSData进⾏拓展 NSData+AES128.h1 2 3 4@interface NSData(AES128)- (NSData*)AES128_encrypt:(NSString*)key padding:(NSString*)pad;; - (NSData*)AES128_decrypt:(NSString*)key padding:(NSString*)pad;; @end NSData+AES128.m 123 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46#import "NSData+AES128.h"@implementation NSData(AES128)- (NSData*)AES128_encrypt:(NSString*)key padding:(NSString*)pad; //加密{char keyPtr[kCCKeySizeAES128+1];bzero(keyPtr, sizeof(keyPtr));[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length];size_t bufferSize = dataLength + kCCBlockSizeAES128;void*buffer = malloc(bufferSize);size_t numBytesEncrypted = 0;CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,kCCOptionPKCS7Padding ,keyPtr, kCCBlockSizeAES128,[pad UTF8String],[self bytes], dataLength,buffer, bufferSize,&numBytesEncrypted);if(cryptStatus == kCCSuccess) {return[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];}free(buffer);return nil;}- (NSData*)AES128_decrypt:(NSString*)key padding:(NSString*)pad; //解密{char keyPtr[kCCKeySizeAES128+1];bzero(keyPtr, sizeof(keyPtr));[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length];size_t bufferSize = dataLength + kCCBlockSizeAES128;void*buffer = malloc(bufferSize);size_t numBytesDecrypted = 0;CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,kCCOptionPKCS7Padding ,keyPtr, kCCBlockSizeAES128,[pad UTF8String],[self bytes], dataLength,buffer, bufferSize,&numBytesDecrypted);if(cryptStatus == kCCSuccess) {return[NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];}free(buffer);return nil;}46 47 48 49 50 51}@end [2].对NSString进⾏拓展 NSString+AES128.h1 2 3 4 5 6 7 8#import <Foundation/Foundation.h>#import <CommonCrypto/CommonCryptor.h>@interface NSString(AES128)-(NSString*) AES128_decrypt:(NSString*)key padding:(NSString*)pad; -(NSString*) AES128_encrypt:(NSString*)key padding:(NSString*)pad;; @end NSString+AES128.m 12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46#import "NSString+AES128.h"#import "NSData+AES128.h"@implementation NSString(AES128)-(NSString*) AES128_encrypt:(NSString*)key padding:(NSString*)pad;{const char*cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];NSData*data = [NSData dataWithBytes:cstr length:self.length];//对数据进⾏加密NSData*result = [data AES128_encrypt:key padding:pad];//转换为2进制字符串if(result && result.length > 0) {Byte *datas = (Byte*)[result bytes];NSMutableString*output = [NSMutableString stringWithCapacity:result.length * 2]; for(int i = 0; i < result.length; i++){[output appendFormat:@"%02x", datas[i]];}return output;}return nil;}-(NSString*) AES128_decrypt:(NSString*)key padding:(NSString*)pad;{//转换为2进制DataNSMutableData*data = [NSMutableData dataWithCapacity:self.length / 2];unsigned char whole_byte;char byte_chars[3] = {'\0','\0','\0'};int i;for(i=0; i < [self length] / 2; i++) {byte_chars[0] = [self characterAtIndex:i*2];byte_chars[1] = [self characterAtIndex:i*2+1];whole_byte = strtol(byte_chars, NULL, 16);[data appendBytes:&whole_byte length:1];}//对数据进⾏解密NSData* result = [data AES128_decrypt:key padding:pad];if(result && result.length > 0) {return[[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];}return nil;}@end3.验证 main.m1 2 3 4 5 6 7 8 9 10 11 12#import <Foundation/Foundation.h>#import "NSString+AES128.h"int main(int argc, const char* argv[]) {@autoreleasepool{// insert code here...NSLog(@"Hello, World!");NSString*str = [@"f3de96947b786e45fe338f06e2baeb2a"AES128_decrypt:@"123456"padding:@"8888888877777777"]; NSLog(@"%@",str);}return0;} 验证结果: 2016-01-18 19:27:48.703 AES_128_CBC[30636:2351517] Hello, World! 2016-01-18 19:27:48.704 AES_128_CBC[30636:2351517] SuperDo.Team Program ended with exit code: 0 完美的搞定AES128_CBC模式加密了!。
AES算法(python)1. 算法介绍⾼级加密标准(Advanced Encryption Standard,AES)⼜称 Rijindael 算法,由⽐利时著名密码学家 Joan Daemen 和 Vincent Rijimen 设计,是美国联邦政府采⽤的⼀种分组加密标准,⽤来替代之前的 DES 算法,已被多⽅分析且使⽤。
⾼级加密标准由美国国家标准与技术研究所在 2001 年 11 ⽉ 26 ⽇发布于 FIPS PUB 197,并在 2002 年 5 ⽉26 ⽇成为有效标准,⽬前为对称密钥加密算法中最流⾏的算法之⼀。
2. 算法结构AES 算法的整体结构为 替代——置换⽹络(Substitution-Permutation Network,SPN)结构,算法的明⽂长度为 128 位,密钥长度为 128,192 或 256 位,分别被称为AES-128,AES-192 和 AES-256。
由于 AES 算法⽹上已经有很多详细的介绍了(⽐如说知乎上),此处就不过多叙述。
这⾥提供⼀个 FIPS PUB 197 的链接,⾥⾯是 AES 的官⽅说明:3. 具体实现(python)3.1 代码SBox = [0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,0xB0, 0x54, 0xBB, 0x16]SBoxIV = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,0x55, 0x21, 0x0c, 0x7d]def _gf2_mul(a: int, b: int, poly: int) -> int:ans = 0digit_1 = poly.bit_length() - 1while b:if b & 1:ans = ans ^ aa, b = a << 1, b >> 1if a >> digit_1:a = a ^ polyreturn ansclass AES:def __init__(self, key: bytes):self.aes_type = len(key) * 8self._key_r = self._generate_key(key)def _generate_key(self, key: bytes) -> list:"""密钥扩展"""Rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36] # 轮常数Nr, Nk = 10 + (self.aes_type - 128) // 32, self.aes_type // 32 # Nr:轮数,Nk:密钥长度 w = [0 for _ in range(4 * (Nr + 1))] # 轮密钥for i in range(Nk):w[i] = int.from_bytes(key[4 * i:4 * i + 4], 'big')for i in range(Nk, 4 * (Nr + 1)):temp = w[i - 1]if i % Nk == 0:temp = self._split_int(temp) # 拆分成 4x8bittemp = [SBox[temp[1]] ^ Rcon[i // Nk - 1], SBox[temp[2]],SBox[temp[3]], SBox[temp[0]]]temp = self._joint_int(temp) # 合并回 32bitelif Nk > 6 and i % Nk == 4:temp = self._split_int(temp) # 拆分成 4x8bittemp = [SBox[temp[0]], SBox[temp[1]],SBox[temp[2]], SBox[temp[3]]]temp = self._joint_int(temp) # 合并回 32bitw[i] = w[i - Nk] ^ temp# 将 w 变成 4x4xNr 形式的矩阵key_r = [[[[0] for _ in range(4)] for _ in range(4)] for _ in range(Nr + 1)]for t in range(Nr + 1):for i in range(4):temp = self._split_int(w[4 * t + i])for j in range(4):key_r[t][j][i] = temp[j]return key_r@staticmethoddef _split_int(n: int) -> list:"""拆分 32bit 成 4x8bit"""return [(n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF]@staticmethoddef _joint_int(b: list) -> int:"""合并 4x8bit 成 32bit"""return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]def encrypt(self, plaintext: bytes) -> bytes:"""加密"""state = [[plaintext[4 * j + i] for j in range(4)] for i in range(4)]Nr = 10 + (self.aes_type - 128) // 32state = self._add_key(state, self._key_r[0])for t in range(1, Nr):state = self._sub_byte(state, iv=False) # 字节代替state = self._shift_row(state, iv=False) # ⾏移位state = self._mix_col(state, iv=False) # 列混淆state = self._add_key(state, self._key_r[t]) # 轮密钥加state = self._sub_byte(state, iv=False)state = self._shift_row(state, iv=False)state = self._add_key(state, self._key_r[Nr])# 将 state 重新排列成⼀维的形式ciphertext = bytearray(16)for i in range(4):for j in range(4):ciphertext[4 * j + i] = state[i][j]return bytes(ciphertext)def decrypt(self, ciphertext: bytes) -> bytes:state = [[ciphertext[4 * j + i] for j in range(4)] for i in range(4)]Nr = 10 + (self.aes_type - 128) // 32state = self._add_key(state, self._key_r[Nr])for t in range(1, Nr):state = self._shift_row(state, iv=True) # 逆⾏移位state = self._sub_byte(state, iv=True) # 逆字节代替state = self._add_key(state, self._key_r[Nr - t]) # 轮密钥加state = self._mix_col(state, iv=True) # 逆列混淆state = self._shift_row(state, iv=True)state = self._sub_byte(state, iv=True)state = self._add_key(state, self._key_r[0])plaintext = bytearray(16)for i in range(4):for j in range(4):plaintext[4 * j + i] = state[i][j]return bytes(plaintext)@staticmethoddef _add_key(state, k):for i in range(4):for j in range(4):state[i][j] = state[i][j] ^ k[i][j]return state@staticmethoddef _shift_row(state, iv):if not iv:state[1] = [state[1][1], state[1][2], state[1][3], state[1][0]]state[2] = [state[2][2], state[2][3], state[2][0], state[2][1]]state[3] = [state[3][3], state[3][0], state[3][1], state[3][2]]else:state[1] = [state[1][3], state[1][0], state[1][1], state[1][2]]state[2] = [state[2][2], state[2][3], state[2][0], state[2][1]]state[3] = [state[3][1], state[3][2], state[3][3], state[3][0]]return state@staticmethoddef _mix_col(state, iv):if not iv:matrix = [[0x02, 0x03, 0x01, 0x01],[0x01, 0x02, 0x03, 0x01],[0x01, 0x01, 0x02, 0x03],[0x03, 0x01, 0x01, 0x02]]else:matrix = [[0x0E, 0x0B, 0x0D, 0x09],[0x09, 0x0E, 0x0B, 0x0D],[0x0D, 0x09, 0x0E, 0x0B],[0x0B, 0x0D, 0x09, 0x0E]]res = [[0 for _ in range(4)] for _ in range(4)]for i in range(4):for j in range(4):temp = 0for k in range(4):temp = temp ^ _gf2_mul(matrix[i][k], state[k][j], poly=0x11b)res[i][j] = tempreturn res@staticmethoddef _sub_byte(state, iv):for i in range(4):for j in range(4):state[i][j] = SBox[state[i][j]] if not iv else SBoxIV[state[i][j]]return state3.2 测试样例上述代码调⽤⽅式如下key = bytes.fromhex("0f1571c947d9e8590cb7add6af7f6798")plaintext = bytes.fromhex("0123456789abcdeffedcba9876543210")aes = AES(key)ciphertext = aes.encrypt(plaintext)print(ciphertext.hex()) # ff0b844a0853bf7c6934ab4364148fb9print(aes.decrypt(ciphertext).hex()) # 0123456789abcdeffedcba9876543210下⾯给出部分 AES-128,AES-196,AES-256 的测试样例# AES-128key = "0f1571c947d9e8590cb7add6af7f6798"plaintext = "0123456789abcdeffedcba9876543210"ciphertext = "ff0b844a0853bf7c6934ab4364148fb9"# AES-128key = "3475bd76fa040b73f521ffcd9de93f24"plaintext = "1b5e8b0f1bc78d238064826704830cdb"ciphertext = "f3855216ddf401d4d42c8002e686c6e7"# AES-128key = "2b24424b9fed596659842a4d0b007c61"plaintext = "41b267bc5905f0a3cd691b3ddaee149d"ciphertext = "fba4ec67020f1573ed28b47d7286d298"# AES-192key = "1234567890123456789012345678901234567890abcdef01"plaintext = "123456789012345678901234567890ab"ciphertext = "7ac22fc4ff307d71f551e7371ced99a9"# AES-256key = "123456789012345678901234567890123456789012345678901234567890abcd"plaintext = "123456789012345678901234567890ab"ciphertext = "d0faf1cff5c57ea32a075f99e8cb81eb"上⽂提供的⽂档末尾有详细的测试样例和中间数据,可供⽐对更多测试样例可以到在线的加解密⽹站上⾃⾏构造,或者通过 python 的 Crypto 库进⾏构造参考资料:《密码学实验教程》。
AES256位加密⽬录1. 算法简介2. 算法流程2.1 扩展密钥2.2 轮密钥加2.3 字节代替2.4 ⾏位移2.5 列混淆3. 总结附录A 运算⽰例1.算法简介⾼级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中⼜称Rijndael加密法,是美国联邦政府采⽤的⼀种区块加密标准。
这个标准⽤来替代原先的DES,已经被多⽅分析且⼴为全世界所使⽤。
经过五年的甄选流程,⾼级加密标准由美国国家标准与技术研究院(NIST)于2001年11⽉26⽇发布于FIPS PUB 197,并在2002年5⽉26⽇成为有效的标准。
2006年,⾼级加密标准已然成为对称密钥加密中最流⾏的算法之⼀。
AES算法属于对称加密算法,是⼀个分组密码。
AES加密算法分为3种,分别是AES-128,AES-192,AES-256。
它们之间区别如表1-1所⽰。
表1-1 3种AES加密算法区别AES密钥长度(bit)分组长度(bit)加密轮数AES-12812812810AES-19219212812AES-25625612814本⽂以最常见的AES-128为例,详细介绍AES加密算法的加密流程。
2.算法流程AES加密算法主要由4中操作组成:字节代替、⾏位移、列混淆、轮密钥加。
另外还需要对原始密钥进⾏扩展。
主流程图如图2-1所⽰。
图2-1 AES-128加密算法流程图加密过程:⾸先明⽂进⾏1次轮密钥加;然后循环9轮字节代替、⾏位移、列混淆、轮密钥加;注意第10轮没有列混淆。
解密过程:解密过程与加密过程相反,这也是对称加密算法的特点。
⾸先密⽂进⾏1次轮密钥加;然后循环9轮逆向⾏位移、逆向字节代替、轮密钥加、逆向列混淆;注意第10轮没有逆向列混淆。
接下来对每⼀个流程进⾏详细介绍。
2.1 扩展密钥⾸先对16字节的原始密钥进⾏扩展,扩展密钥原理图如图2-2所⽰。
图2-2 扩展密钥原理图⾸先需要将16字节原始密钥按列转换成4个32bit的字,即W[0],W[1],W[2],W[3]。
Rijndael加密算法的介绍作者:林祝兴叶义雄杨国鸿本文针对Rijndael加密算法的数学理论背景,算法的架构,回合的转换,金钥的产生,以及各种攻击破密法等等,做了一些简单的介绍。
一、简介在AES ( Advanced Encryption Standard ) 的选拔中,从最初的十五个算法,到十个、五个,逐步筛选出适合用来作为下一代加密算法的标准。
Rijndael在经过了一番时日的考验之后,也一直名列前矛。
直至十月二日,Rijndael才脱颖而出,这篇文章便是针对Rijndael作简要的介绍。
Rijndael是一个反复运算的加密算法,它允许可变动的数据区块及金钥的长度。
数据区块与金钥长度的变动是各自独立的。
在Rijndael算法中定义了几个名词,分述如下:State:在运算过程中所产生的中间值,是一个4×Nb的矩阵,Nb可由数据长度除以32位求得,也就是把数据分割成Nb个区块。
Cipher Key:用来做加密运算的金钥,形式是一个4×Nk的矩阵,Nk可由金钥长度除以32位求得,也就是把金钥分割成Nk个32位的子金钥。
在Rijndael算法中,运算的回合数(Nr)是由Nb及Nk所决定的,回合数的变动定义如下表。
Nr Nb=4 Nb=6 Nb=8Nk=4 10 12 14Nk=6 12 12 14Nk=8 14 14 14二、Rijndael的数学背景在Rijndael中使用了许多字节层级的运算,而这些运算是以GF(28)为基础架构。
也有一些采用了4-byte的字组运算。
在这部分,我们将介绍这些基本的数学原理。
(1) GF(28)的定义假设一个字节b由b7b6b5b4b3b2b1b0组成,我们可以把这些b i想象成一个7次多项式的系数,而这些系数不是0就是1:b7x7+ b6x6+ b5x5+ b4x4+ b3x3+ b2x2+ b1x + b0,例如,(57)16的二进制表示法为(0101,0111)2表示成多项式,则为:x6+ x4+ x2+ x + 1 .(2) 加法两个多项式的加法,则是定义为相同指数项的系数和再模余2,简单的说就是作EXOR运算(i.e., 1+1=0)。
AES基本原理AES(Advanced Encryption Standard)是一种对称加密算法,用于保护敏感数据的机密性。
它是目前最常用的加密算法之一,被广泛应用于各种领域,包括网络通信、金融交易和数据存储等。
1. 对称加密算法简介对称加密算法是一种使用相同的密钥进行加密和解密的算法。
在加密过程中,明文通过一个数学函数(即加密算法)和一个秘钥进行变换,生成密文。
而在解密过程中,通过相同的数学函数和相同的秘钥对密文进行变换,得到原始明文。
对称加密算法具有高效性能和较低的计算成本,因此被广泛应用。
然而,由于加解密使用相同的秘钥,秘钥管理成为一个重要问题。
2. AES历史背景在1997年之前,美国政府一直采用DES(Data Encryption Standard)作为标准对称加密算法。
然而,在计算能力不断提升的情况下,DES逐渐暴露出安全性不足的问题。
为了替代DES,并提供更高级别的安全性能,美国国家标准技术研究所(NIST)在1997年发起了一个公开的竞赛,邀请全球加密专家参与设计新的加密算法。
由比利时密码学家Joan Daemen和Vincent Rijmen设计的Rijndael算法被选为AES。
2001年,AES正式成为美国政府采用的标准对称加密算法,并逐渐在全球范围内得到广泛应用。
3. AES基本原理AES是一种分组密码(block cipher),它将明文和密钥都划分为固定长度的块,并通过多轮迭代来实现加密和解密过程。
AES算法支持128位、192位和256位三种不同长度的秘钥。
3.1 初始轮AES算法开始时会对输入的明文进行一次初始处理。
将明文划分为若干个固定长度(128位)的块。
将每个块与一个固定长度(128位)的秘钥进行异或运算。
3.2 轮函数在每一轮中,AES算法使用一个称为”轮函数”(round function)的操作来处理上一轮输出或初始输入。
该操作包括四个步骤:字节代换、行移位、列混淆和轮秘钥加。