AES加密演算法 C

2021-06-08 09:20:09 字數 4260 閱讀 8402

**:

先搞定aes演算法,基本變換包括subbytes(位元組替代)、shiftrows(行移位)、mixcolumns(列混淆)、addroundkey(輪金鑰加)

其演算法一般描述為

明文及金鑰的組織排列方式

bytesubstitution(位元組替代)

非線性的位元組替代,單獨處理每個位元組:

求該位元組在有限域gf(28)上的乘法逆,"0"被對映為自身,即對於α∈gf(28),求β∈gf(28),

使得α·β=β·α=1mod(x8+x4+x2+x+1)。

對上一步求得的乘法逆作仿射變換

yi=xi + x(i+4)mod8 + x(i+6)mod8 + x(i+7)mod8 + ci

(其中ci是6310即011000112的第i位),用矩陣表示為

本來打算把求乘法逆和仿射變換演算法敲上去,最後還是放棄了...直接打置換表

unsigned char sbox = 

;

下面是逆置換表,解密時使用

unsigned char invsbox[256] =  

;

這裡遇到問題了,本來用純c初始化陣列很正常,封裝成類以後發現不能初始化,不管是宣告、建構函式都無法初始化,百歌谷度了一通後沒有任何答案,無奈只能在建構函式中宣告乙個區域性變數陣列並初始化,然後用memcpy,(成員變數名為sbox/invsbox,區域性變數名sbox/invsbox)

void aes::subbytes(unsigned char state[4]) } }

shiftrows(行移位變換)

行移位變換完成基於行的迴圈位移操作,變換方法:

即行移位變換作用於行上,第0行不變,第1行迴圈左移1個位元組,第2行迴圈左移2個位元組,第3行迴圈左移3個位元組。

void aes::shiftrows(unsigned char state[4]) 

for(c=0; c<4; c++) } }

mixcolumns(列混淆變換)

逐列混合,方法:

矩陣表示形式:

}其中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]) } }

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]) 

; for(r=0; r<4; r++)

} for(i=1; i<=10; i++)

if(j == 0)

t[3] = sbox[temp];

t[0] ^= rc[i-1];

} for(r=0; r<4; r++)

} }

}

解密的基本運算aes解密演算法與加密不同,基本運算中除了addroundkey(輪金鑰加)不變外,其餘的都需要進行逆變換,即

invsubbytes(逆位元組替代)、invshiftrows(逆行移位)、invmixcolumns(逆列混淆)

void aes::invsubbytes(unsigned char state[4]) 

} }

void aes::invshiftrows(unsigned char state[4])

for(c=0; c<4; c++)

} }

void aes::invmixcolumns(unsigned char state[4])

for(r=0; r<4; r++) } }

加密過程先將輸入的明文按列序組合成4*4的矩陣,直接與第0組金鑰(即輸入的金鑰)相加(異或),作為輪加密的輸入

然後迴圈10次進行subbytes、shiftrows、mixcolumns、addroundkey運算,最後恢復原序列

需要注意的是最後一輪並不進行mixcolumns(列混淆變換)

unsigned char* aes::cipher(unsigned char* input) 

} addroundkey(state,w[0]);

for(i=1; i<=10; i++)

for(r=0; r<4; r++)

} return input;

解密過程

unsigned char* aes::invcipher(unsigned char* input) 

} addroundkey(state, w[10]);

for(i=9; i>=0; i--)

for(r=0; r<4; r++)

} return input;

}

對外部資料的加密/解密至此已經實現了aes加密與解密的原型,在使用的時候一般處理的是字串等,而不是直接傳入128位的資料,所以要封裝一下對外部資料的加解密處理

void* aes::cipher(void* input, int length) 

for(i=0; i

加密時預設引數length=0,為要加密的資料長度,如果使用預設值,則作為字串處理,以'\0'為結尾計算長度

加密時傳進的指標要預留夠16整數倍位元組的空間,因為加密操作直接修改原資料,不足128位可能造成記憶體溢位

AES加密演算法

aes加密演算法 加密模式 ecb模式 優點 1.簡單 2.有利於平行計算 3.誤差不會被傳送 缺點 1.不能隱藏明文的模式 2.可能對明文進行主動攻擊 cbc模式 優點 1.不容易主動攻擊,安全性好於ecb,適合傳輸長度長的報文,是ssl ipsec的標準。缺點 1.不利於平行計算 2.誤差傳遞 ...

AES加密演算法

aes對稱加密演算法下有好多種演算法,往往很難做到垮語言的加密解密,本文提供一套c 和node.js可以相互加密解密通用的 之aes 256 cbc演算法 1 aes所有的鑰匙必須 128位 16位元組 192位 24位元組 或256位 32位元組 長 2 有幾種操作模式,每個都有不同的優點和缺點。...

AES加密演算法

aes的基本要求是 比三重des快 至少與三重des一樣安全 資料分組長度為128 bit 金鑰長度為128 192 256 bit,對應於金鑰的不同長度,加密輪的次數也不盡相同。選定rijndael演算法為新的aes演算法。演算法的原型是square演算法,其設計策略為寬軌跡策略 針對差分分析和線...