❶ 初學者,求高手給一個完整的AES加密解密演算法的程序(C/C++) 希望能滿足如下要求
/*128bits密鑰長度及分組長度AES加解密代碼
*作者:Jeffrey.zhu
*/
❷ c#的AES加密解密問題
不是初學,而是對.net中所有的加解密方式都沒有弄清楚。不過別灰心——很多自以為會的人也沒有弄清。
首先,.net中類庫中支持各類摘要加解密方式。一般情況下我們將安全分為兩類,一類是摘要,一類是加解密。加密解又分為對稱與非對稱加解密。
在.net體系中,不管是摘要還是加解密,為了統一演算法方式,一律都是流方式進行的。不管是MD5摘要還是ADE/DES/TDES/RSA等等。一定要記住的第一條,是流方式進行的!
流——這個概念很多人也不清楚,因為stream的范圍還是非常的大的,有網路流responseStream等,基本文本流,IO流等等,在加密時我們使用了一個流叫「加解密流」CryptStream,該流用來實現加解密及摘要演算法等等。
那麼CryptoStream是個什麼流呢?它算是轉換流,把一種形式轉換成另一種形式,比如把密文轉換成明文或把明文換成密文。正常的情況下,我們可以用流寫流的方式來實現,比如MemoryStream來換流。當然,也可以把byte[]數組直接寫到流中。
流這部分說完了,那麼,其實我們如何區別CryptoStream是加密還是解密呢,除了說明之外,還是一個方式,就是看流的方式是讀還是寫!所以當我看到你的解密流中使用的方式竟然是Write,而不是Read,所以你對加解密方式並沒有真正理解。
比如,我們可以轉換後的流直接進行ReadToLine即可。
老實說,你這種寫法有很大問題——有關stream大部分都是非託管,所以一定要記著Dispose,或Close(Close時會自動調用Dispose)。防止出現錯誤等內存泄露。
有於加解密流,我們經常一句話,加密方式是Write,解密方式是Read!
❸ 誰知道哪裡有AES演算法加密,解密c++/C語言代碼
我有寫好的,腫么給你?貼上來吧。
#ifndef aes_h_
#define aes_h_
#include <iostream>
#include <string>
using namespace std;
typedef unsigned char uint8;
class aes
{
public:
/// 構造函數
aes();
/// 析構函數
~aes();
/// 加密,默認256位密碼
///
/// @param input 要加密的字元串
/// @param output 加密後字元串
/// @return 無
/// @see
/// @note (note描述需要注意的問題)
void encrypt(const string& input, string& output);
/// 解密 默認密碼
///
/// @param input 要解密字元串
/// @param output 解密後字元串
/// @return 無
/// @see
/// @note (note描述需要注意的問題)
void decrypt(const string& input, string& output);
/// 加密 256位
///
/// @param key 密碼
/// @param input 要加密的字元串
/// @param output 加密後字元串
/// @return 無
/// @see
/// @note (note描述需要注意的問題)
void encrypt(uint8 key[32], const string& input, string& output);
/// 解密 256位
///
/// @param key 密碼
/// @param input 要解密字元串
/// @param output 解密後字元串
/// @return 無
/// @see
/// @note (note描述需要注意的問題)
void decrypt(uint8 key[32],const string& input, string& output);
private:
typedef struct
{
uint32 erk[64]; /* encryption round keys */
uint32 drk[64]; /* decryption round keys */
int nr; /* number of rounds */
}aes_context;
int aes_set_key( aes_context* ctx, uint8* key, int nbits );
void aes_encrypt( aes_context* ctx, uint8 input[16], uint8 output[16] );
void aes_decrypt( aes_context* ctx, uint8 input[16], uint8 output[16] );
};
#endif // aes_h_
我暈,太長貼不上來啊?
❹ 用C語言編寫AES加密演算法,遇到問題。
一行行列印語句,問題的核心沒有講出來,大家怎麼幫你呢,我們只能保證這個列印過程是正確的。
❺ 【密碼學】C語言實現AES核心步驟
按照AES演算法,完成AES演算法S盒、行移位、列混合、輪密鑰加操作
高級加密標准(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標准。這個標准用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,高級加密標准由美國國家標准與技術研究院(NIST)於2001年11月26日發布於FIPS PUB 197,並在2002年5月26日成為有效的標准。2006年,高級加密標准已然成為對稱密鑰加密中最流行的演算法之一。
AES採用對稱分組密碼體制,密鑰的長度最少支持為128、192、256,分組長度128位,演算法應易於各種硬體和軟體實現。
AES加密數據塊分組長度必須為128比特,密鑰長度可以是128比特、192比特、256比特中的任意一個(如果數據塊及密鑰長度不足時,會補齊)。AES加密有很多輪的重復和變換。大致步驟如下:1、密鑰擴展(KeyExpansion),2、初始輪(Initial Round),3、重復輪(Rounds),每一輪又包括:位元組替代(SubBytes)、行移位(ShiftRows)、列混合(MixColumns)、輪密鑰加(AddRoundKey),4、最終輪(Final Round),最終輪沒有MixColumns。
AES演算法的加密整體結構
位元組替代(SubBytes):使用一個S盒進行非線性置換,S盒是一個16×16的矩陣,如表4-9所示。位元組替代將輸入的狀態矩陣的每一個位元組通過一個簡單查表操作,映射為另外一個位元組。
輸入位元組的前4bits指定S盒的行值,後4bits指定S盒的列值,行和列所確定S盒位置的元素作為輸出,例如輸入位元組「03」,行值為0,列值為3,根據表4-9可知第0行第3列對應的值為 「7B」,因此輸出位元組為「7B」。
舉例
在上面的示例中,第1個基本元素為」F5」,它將被S盒行為第」F行」、列為第」5」列的元素「E6「代替,其餘的輸出也用相同的方法確定。
狀態陣列的4個行循環以位元組為基本單位進行左移,而每行循環做移的偏移量是由明文分組的大小和所在行數共同確定,即列數Nb和行號確定。
舉例
舉例
輪密鑰加操作是將密鑰與明文按比特異或,輪密鑰通過密鑰擴展得到
和fips-192(AES)的標准一樣
由於有一個重要的Rar文件,極需解開,首先試用了ARPC,但是解壓的速度極慢,每秒只有30個左右,所以斷了窮舉破解的念頭,卻仍不死心,因為我從不崇尚窮舉破解的方法,除非每秒可以跑幾千萬次的,我或許可以一試,所以決定研究一下Winrar3.x密碼演算法,以期是否可以破解該密碼。查看了網路上的資料,包括看雪FAQ里的回答,都聲稱只能用窮舉法破解,起先並不理解,但通過研究,我理解了看雪前輩們在FAQ里所說的原因,不禁讓我佩服
Winrar加密思路的成熟。雖然研究的結果沒有什麼新意,但我還是決定把我的研究結果與大家一起分享,為那些仍然以為winrar密碼可以象破解注冊碼一樣的,通過修改winrar彈出框之類的更改文件流程指向可以達到跳過密碼檢驗的朋友,做一個簡要的說明。
一、Rar文件生成的流程。
Winrar加密文件時,總的分兩個步驟:
1:先把源文件壓縮,壓成一段數據段。
2:再將壓縮完的數據段加密。
對於同一個源文件來說,不進行加密,壓縮完,其rar文件中的數據段是一模一樣的。但是如果對同一個源文件來說,即使使用同一個密碼,加密完rar文件中的數據段是不一樣的,這是由於加密的密鑰是依賴於一個Salt(8個位元組的密鑰,用來加密時使用,存放在rar文件頭中里)
所以要解密rar加密文件關鍵在於數據解密這一步,那我們接下來研究一下如何加密的。
二、加密「壓縮完的數據段」的流程
1、獲取密鑰:
將明文的密碼與Salt一起,通過HASH演算法,生成兩個16位元組的密鑰。(一個是KEY(AES演算法的參數),一個是initVector)
2、以Key和initVector來加密壓縮數據:
這里,是一個循環加密的結構,每16位元組作為一個塊,進行加密(這可能正是為什麼加密完的文件長度總為16倍數的原因)。加密採用AES演算法(RAR採用的是AES的rijndael的標准應用)。這里注意:AES加密前,有一個異或運算,是先將每16位元組塊與上一個16位元組塊加密結果進行異或,然後再進行AES演算法的。我用一個簡單的示意代碼看說明:
;===============================================
packblock[0]=packblock[i]^initVector
encryptBlock[0]=AES(packblock[0]) ;(KEY為AES的密鑰)
for i=1to 塊數量-1
packblock[i]=packblock[i]^encryptBlock[i-1]
encryptBlock[i]=AES(packblock[i]);(KEY為AES的密鑰)
next
;packblock[i]表示壓縮完的每16位元組數據
;encryptBlock[i]表示加密完的每16位元組數據
;===============================================
三、解密的過程
由於AES演算法是對稱的,所以解密的過程,是加密過程的逆運算。但解密時AES演算法過程與加密所用的不一樣(是因為解密過程中由KEY生成的子密鑰表不一樣)。仍然需要我們將密碼輸入,與salt一起生成兩個16位元組密鑰,KEY和initVector。
;===============================================
packblock[0]=AES1(encryptBlock[0]) ;(KEY為AES的密鑰)
packblock[0]=packblock[i]^initVector
for i=1to 塊數量-1
packblock[i]=AES1(encryptBlock[i]) ;(KEY為AES的密鑰)
packblock[i]=packblock[i]^encryptBlock[i-1]
next
;===============================================
那判斷密碼是否正確的在什麼地方呢?
解密的過程是解密後的數據塊進行解壓縮,然後解成源文件,對該文件進行CRC校驗,存在RAR文件中的源文件CRC校驗碼比較,相同則密碼正確,不相同則密碼錯誤。
四、無法秒破的原因
從上面,我們了解了RAR文件的整體思路。地球人都知道,解密時,肯定有個步驟是來判斷密碼的正確與否。而且,依據以往的經驗,我們也許可以將某些判斷的點移動,那樣可以縮減破解的流程思路。那RAR的這一步在哪裡?它把校驗放在了最後的一步。如果要秒破,我們該怎麼做泥?至少我認為目前是不可能的。
我們從解密過程逆反過來看看:
1、CRC檢驗這一塊修改跳轉?根本毫無意義,因為它已經是最後一步了。你可以修改RAR文件頭的CRC值,你可以將它改得和你用任意密碼解壓出來的文件CRC值一樣,但你的文件根本就不是原來的文件了。可能已經完全面目全非了。所以,對這一過程不可行。CRC校驗本身是不可逆的
2、那麼把判斷提前到壓縮完的數據?
解壓的時候,有沒有什麼來判斷壓縮數據是否正確?壓縮完的數據,有沒有固定的特徵,是否可以做為解壓的判斷,在這一步里,我們也無法找到有效的可用的固定特徵。因為這一步涉及到RAR的壓縮演算法。即使一個源文件,即使你的文件前一部分是完全相同的,只對後面的部分進行改過,那麼壓縮完,數據也是完全一樣的。因為壓縮完的數據首先是一個壓縮表,後面是編碼。文件不一樣,掃描完的壓縮表也不一樣,編碼又是依賴於壓縮表,所以,這里頭找不到壓縮完的數據有任何的固定特徵可以用來判斷的。
不管壓縮數據是什麼樣的,Winrar都一如既往地進行解壓,沒有進行壓縮數據是否有效的判斷。
3、那假如我們破解了AES了泥?
由於AES只依賴於KEY,如果AES演算法被破解了,我們知道了KEY,我們可以解出壓縮完的數據,但是這里有一個問題,還有一個initVector密鑰,用來第一個16位元組塊的異或,你沒有initVector參數,你第一個16位元組塊的數據便無法解得出來。
4、那就只能從第一步Hash的演算法入手
即使你能破解hash,但hash後的結果泥?沒有結果,你怎麼返推密碼。
所以綜上,我發現rar的加密是由hash和AES兩種演算法互相牽制,而兩種演算法當前都無法破解,至少目前還沒有辦法秒破,也理解了看雪高手講的道理。
五、對窮舉提高演算法效率的一些設想。
我用匯編寫完了RAR窮舉解密的演算法模塊,但是如何提高效率,優化窮舉的速度泥?我有如下的想法:
1、從壓縮數據里找尋特徵,省掉解壓縮、CRC檢驗代碼和生成initVector生成代碼。目前,通過多次實驗,我找到的一個特徵(不知道這個是否正確),即解密完的最後一個16位元組塊的最後一個位元組必須為0。因為經過多次的試驗,我發現有加密的數據段長度都會比未加密前的數據長,那麼,最後一個
16個位元組的數據塊解密完,多出的部分就都為0,但多出幾個位元組泥?多次實驗,長度不一,我試想著從加密數據段最後一個16個位元組塊著手,只解這一塊,看是否一個位元組為0,這樣,只解密16個位元組的數據,來大大提高效率?如果能進行到這一步了,再通過解全部數據,進行CRC校驗的判斷。
2、如果第一個特徵不成立的話,針對特定格式的壓縮文件,比如doc、jpg等,部分數據固定,壓縮完的數據是否存在相互牽制的數據?從而把判斷提前,這一步,我不知道如何找到壓縮完的數據是否存在相互牽制的數據。
❼ 求AES演算法加密C語言完整程序
恰好我有。能運行的,C語言的。
#include <string.h>
#include "aes.h"
#include "commonage.h"
#define byte unsigned char
#define BPOLY 0x1b //!< Lower 8 bits of (x^8+x^4+x^3+x+1), ie. (x^4+x^3+x+1).
#define BLOCKSIZE 16 //!< Block size in number of bytes.
#define KEYBITS 128 //!< Use AES128.
#define ROUNDS 10 //!< Number of rounds.
#define KEYLENGTH 16 //!< Key length in number of bytes.
byte xdata block1[ 256 ]; //!< Workspace 1.
byte xdata block2[ 256 ]; //!< Worksapce 2.
byte xdata * powTbl; //!< Final location of exponentiation lookup table.
byte xdata * logTbl; //!< Final location of logarithm lookup table.
byte xdata * sBox; //!< Final location of s-box.
byte xdata * sBoxInv; //!< Final location of inverse s-box.
byte xdata * expandedKey; //!< Final location of expanded key.
void CalcPowLog( byte * powTbl, byte * logTbl )
{
byte xdata i = 0;
byte xdata t = 1;
do {
// Use 0x03 as root for exponentiation and logarithms.
powTbl[i] = t;
logTbl[t] = i;
i++;
// Muliply t by 3 in GF(2^8).
t ^= (t << 1) ^ (t & 0x80 ? BPOLY : 0);
} while( t != 1 ); // Cyclic properties ensure that i < 255.
powTbl[255] = powTbl[0]; // 255 = '-0', 254 = -1, etc.
}
void CalcSBox( byte * sBox )
{
byte xdata i, rot;
byte xdata temp;
byte xdata result;
// Fill all entries of sBox[].
i = 0;
do {
// Inverse in GF(2^8).
if( i > 0 ) {
temp = powTbl[ 255 - logTbl[i] ];
} else {
temp = 0;
}
// Affine transformation in GF(2).
result = temp ^ 0x63; // Start with adding a vector in GF(2).
for( rot = 0; rot < 4; rot++ ) {
// Rotate left.
temp = (temp<<1) | (temp>>7);
// Add rotated byte in GF(2).
result ^= temp;
}
// Put result in table.
sBox[i] = result;
} while( ++i != 0 );
}
void CalcSBoxInv( byte * sBox, byte * sBoxInv )
{
byte xdata i = 0;
byte xdata j = 0;
// Iterate through all elements in sBoxInv using i.
do {
// Search through sBox using j.
cleardog();
do {
// Check if current j is the inverse of current i.
if( sBox[ j ] == i ) {
// If so, set sBoxInc and indicate search finished.
sBoxInv[ i ] = j;
j = 255;
}
} while( ++j != 0 );
} while( ++i != 0 );
}
void CycleLeft( byte * row )
{
// Cycle 4 bytes in an array left once.
byte xdata temp = row[0];
row[0] = row[1];
row[1] = row[2];
row[2] = row[3];
row[3] = temp;
}
void InvMixColumn( byte * column )
{
byte xdata r0, r1, r2, r3;
r0 = column[1] ^ column[2] ^ column[3];
r1 = column[0] ^ column[2] ^ column[3];
r2 = column[0] ^ column[1] ^ column[3];
r3 = column[0] ^ column[1] ^ column[2];
column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
r0 ^= column[0] ^ column[1];
r1 ^= column[1] ^ column[2];
r2 ^= column[2] ^ column[3];
r3 ^= column[0] ^ column[3];
column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
r0 ^= column[0] ^ column[2];
r1 ^= column[1] ^ column[3];
r2 ^= column[0] ^ column[2];
r3 ^= column[1] ^ column[3];
column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
column[0] ^= column[1] ^ column[2] ^ column[3];
r0 ^= column[0];
r1 ^= column[0];
r2 ^= column[0];
r3 ^= column[0];
column[0] = r0;
column[1] = r1;
column[2] = r2;
column[3] = r3;
}
byte Multiply( unsigned char num, unsigned char factor )
{
byte mask = 1;
byte result = 0;
while( mask != 0 ) {
// Check bit of factor given by mask.
if( mask & factor ) {
// Add current multiple of num in GF(2).
result ^= num;
}
// Shift mask to indicate next bit.
mask <<= 1;
// Double num.
num = (num << 1) ^ (num & 0x80 ? BPOLY : 0);
}
return result;
}
byte DotProct( unsigned char * vector1, unsigned char * vector2 )
{
byte result = 0;
result ^= Multiply( *vector1++, *vector2++ );
result ^= Multiply( *vector1++, *vector2++ );
result ^= Multiply( *vector1++, *vector2++ );
result ^= Multiply( *vector1 , *vector2 );
return result;
}
void MixColumn( byte * column )
{
byte xdata row[8] = {
0x02, 0x03, 0x01, 0x01,
0x02, 0x03, 0x01, 0x01
}; // Prepare first row of matrix twice, to eliminate need for cycling.
byte xdata result[4];
// Take dot procts of each matrix row and the column vector.
result[0] = DotProct( row+0, column );
result[1] = DotProct( row+3, column );
result[2] = DotProct( row+2, column );
result[3] = DotProct( row+1, column );
// Copy temporary result to original column.
column[0] = result[0];
column[1] = result[1];
column[2] = result[2];
column[3] = result[3];
}
void SubBytes( byte * bytes, byte count )
{
do {
*bytes = sBox[ *bytes ]; // Substitute every byte in state.
bytes++;
} while( --count );
}
void InvSubBytesAndXOR( byte * bytes, byte * key, byte count )
{
do {
// *bytes = sBoxInv[ *bytes ] ^ *key; // Inverse substitute every byte in state and add key.
*bytes = block2[ *bytes ] ^ *key; // Use block2 directly. Increases speed.
bytes++;
key++;
} while( --count );
}
void InvShiftRows( byte * state )
{
byte temp;
// Note: State is arranged column by column.
// Cycle second row right one time.
temp = state[ 1 + 3*4 ];
state[ 1 + 3*4 ] = state[ 1 + 2*4 ];
state[ 1 + 2*4 ] = state[ 1 + 1*4 ];
state[ 1 + 1*4 ] = state[ 1 + 0*4 ];
state[ 1 + 0*4 ] = temp;
// Cycle third row right two times.
temp = state[ 2 + 0*4 ];
state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
state[ 2 + 2*4 ] = temp;
temp = state[ 2 + 1*4 ];
state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
state[ 2 + 3*4 ] = temp;
// Cycle fourth row right three times, ie. left once.
temp = state[ 3 + 0*4 ];
state[ 3 + 0*4 ] = state[ 3 + 1*4 ];
state[ 3 + 1*4 ] = state[ 3 + 2*4 ];
state[ 3 + 2*4 ] = state[ 3 + 3*4 ];
state[ 3 + 3*4 ] = temp;
}
void ShiftRows( byte * state )
{
byte temp;
// Note: State is arranged column by column.
// Cycle second row left one time.
temp = state[ 1 + 0*4 ];
state[ 1 + 0*4 ] = state[ 1 + 1*4 ];
state[ 1 + 1*4 ] = state[ 1 + 2*4 ];
state[ 1 + 2*4 ] = state[ 1 + 3*4 ];
state[ 1 + 3*4 ] = temp;
// Cycle third row left two times.
temp = state[ 2 + 0*4 ];
state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
state[ 2 + 2*4 ] = temp;
temp = state[ 2 + 1*4 ];
state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
state[ 2 + 3*4 ] = temp;
// Cycle fourth row left three times, ie. right once.
temp = state[ 3 + 3*4 ];
state[ 3 + 3*4 ] = state[ 3 + 2*4 ];
state[ 3 + 2*4 ] = state[ 3 + 1*4 ];
state[ 3 + 1*4 ] = state[ 3 + 0*4 ];
state[ 3 + 0*4 ] = temp;
}
void InvMixColumns( byte * state )
{
InvMixColumn( state + 0*4 );
InvMixColumn( state + 1*4 );
InvMixColumn( state + 2*4 );
InvMixColumn( state + 3*4 );
}
void MixColumns( byte * state )
{
MixColumn( state + 0*4 );
MixColumn( state + 1*4 );
MixColumn( state + 2*4 );
MixColumn( state + 3*4 );
}
void XORBytes( byte * bytes1, byte * bytes2, byte count )
{
do {
*bytes1 ^= *bytes2; // Add in GF(2), ie. XOR.
bytes1++;
bytes2++;
} while( --count );
}
void CopyBytes( byte * to, byte * from, byte count )
{
do {
*to = *from;
to++;
from++;
} while( --count );
}
void KeyExpansion( byte * expandedKey )
{
byte xdata temp[4];
byte i;
byte xdata Rcon[4] = { 0x01, 0x00, 0x00, 0x00 }; // Round constant.
unsigned char xdata *key;
unsigned char xdata a[16];
key=a;
//以下為加解密密碼,共16位元組。可以選擇任意值
key[0]=0x30;
key[1]=0x30;
key[2]=0x30;
key[3]=0x30;
key[4]=0x30;
key[5]=0x30;
key[6]=0x30;
key[7]=0x30;
key[8]=0x30;
key[9]=0x30;
key[10]=0x30;
key[11]=0x30;
key[12]=0x30;
key[13]=0x30;
key[14]=0x30;
key[15]=0x30;
////////////////////////////////////////////
// Copy key to start of expanded key.
i = KEYLENGTH;
do {
*expandedKey = *key;
expandedKey++;
key++;
} while( --i );
// Prepare last 4 bytes of key in temp.
expandedKey -= 4;
temp[0] = *(expandedKey++);
temp[1] = *(expandedKey++);
temp[2] = *(expandedKey++);
temp[3] = *(expandedKey++);
// Expand key.
i = KEYLENGTH;
while( i < BLOCKSIZE*(ROUNDS+1) ) {
// Are we at the start of a multiple of the key size?
if( (i % KEYLENGTH) == 0 ) {
CycleLeft( temp ); // Cycle left once.
SubBytes( temp, 4 ); // Substitute each byte.
XORBytes( temp, Rcon, 4 ); // Add constant in GF(2).
*Rcon = (*Rcon << 1) ^ (*Rcon & 0x80 ? BPOLY : 0);
}
// Keysize larger than 24 bytes, ie. larger that 192 bits?
#if KEYLENGTH > 24
// Are we right past a block size?
else if( (i % KEYLENGTH) == BLOCKSIZE ) {
SubBytes( temp, 4 ); // Substitute each byte.
}
#endif
// Add bytes in GF(2) one KEYLENGTH away.
XORBytes( temp, expandedKey - KEYLENGTH, 4 );
// Copy result to current 4 bytes.
*(expandedKey++) = temp[ 0 ];
*(expandedKey++) = temp[ 1 ];
*(expandedKey++) = temp[ 2 ];
*(expandedKey++) = temp[ 3 ];
i += 4; // Next 4 bytes.
}
}
void InvCipher( byte * block, byte * expandedKey )
{
byte round = ROUNDS-1;
expandedKey += BLOCKSIZE * ROUNDS;
XORBytes( block, expandedKey, 16 );
expandedKey -= BLOCKSIZE;
do {
InvShiftRows( block );
InvSubBytesAndXOR( block, expandedKey, 16 );
expandedKey -= BLOCKSIZE;
InvMixColumns( block );
} while( --round );
InvShiftRows( block );
InvSubBytesAndXOR( block, expandedKey, 16 );
}
void Cipher( byte * block, byte * expandedKey ) //完成一個塊(16位元組,128bit)的加密
{
byte round = ROUNDS-1;
XORBytes( block, expandedKey, 16 );
expandedKey += BLOCKSIZE;
do {
SubBytes( block, 16 );
ShiftRows( block );
MixColumns( block );
XORBytes( block, expandedKey, 16 );
expandedKey += BLOCKSIZE;
} while( --round );
SubBytes( block, 16 );
ShiftRows( block );
XORBytes( block, expandedKey, 16 );
}
void aesInit( unsigned char * tempbuf )
{
powTbl = block1;
logTbl = block2;
CalcPowLog( powTbl, logTbl );
sBox = tempbuf;
CalcSBox( sBox );
expandedKey = block1; //至此block1用來存貯密碼表
KeyExpansion( expandedKey );
sBoxInv = block2; // Must be block2. block2至此開始只用來存貯SBOXINV
CalcSBoxInv( sBox, sBoxInv );
}
//對一個16位元組塊解密,參數buffer是解密密緩存,chainBlock是要解密的塊
void aesDecrypt( unsigned char * buffer, unsigned char * chainBlock )
{
//byte xdata temp[ BLOCKSIZE ];
//CopyBytes( temp, buffer, BLOCKSIZE );
CopyBytes(buffer,chainBlock,BLOCKSIZE);
InvCipher( buffer, expandedKey );
//XORBytes( buffer, chainBlock, BLOCKSIZE );
CopyBytes( chainBlock, buffer, BLOCKSIZE );
}
//對一個16位元組塊完成加密,參數buffer是加密緩存,chainBlock是要加密的塊
void aesEncrypt( unsigned char * buffer, unsigned char * chainBlock )
{
CopyBytes( buffer, chainBlock, BLOCKSIZE );
//XORBytes( buffer, chainBlock, BLOCKSIZE );
Cipher( buffer, expandedKey );
CopyBytes( chainBlock, buffer, BLOCKSIZE );
}
//加解密函數,參數為加解密標志,要加解密的數據緩存起始指針,要加解密的數據長度(如果解密運算,必須是16的整數倍。)
unsigned char aesBlockDecrypt(bit Direct,unsigned char *ChiperDataBuf,unsigned char DataLen)
{
unsigned char xdata i;
unsigned char xdata Blocks;
unsigned char xdata sBoxbuf[256];
unsigned char xdata tempbuf[16];
unsigned long int xdata OrignLen=0; //未加密數據的原始長度
if(Direct==0)
{
*((unsigned char *)&OrignLen+3)=ChiperDataBuf[0];
*((unsigned char *)&OrignLen+2)=ChiperDataBuf[1];
*((unsigned char *)&OrignLen+1)=ChiperDataBuf[2];
*((unsigned char *)&OrignLen)=ChiperDataBuf[3];
DataLen=DataLen-4;
}
else
{
memmove(ChiperDataBuf+4,ChiperDataBuf,DataLen);
OrignLen=DataLen;
ChiperDataBuf[0]=OrignLen;
ChiperDataBuf[1]=OrignLen>>8;
ChiperDataBuf[2]=OrignLen>>16;
ChiperDataBuf[3]=OrignLen>>24;
}
cleardog();
aesInit(sBoxbuf); //初始化
if(Direct==0) //解密
{
Blocks=DataLen/16;
for(i=0;i<Blocks;i++)
{
cleardog();
aesDecrypt(tempbuf,ChiperDataBuf+4+16*i);
}
memmove(ChiperDataBuf,ChiperDataBuf+4,OrignLen);
cleardog();
return(OrignLen);
}
else //加密
{
if(DataLen%16!=0)
{
Blocks=DataLen/16+1;
//memset(ChiperDataBuf+4+Blocks*16-(DataLen%16),0x00,DataLen%16); //不足16位元組的塊補零處理
}
else
{
Blocks=DataLen/16;
}
for(i=0;i<Blocks;i++)
{
cleardog();
aesEncrypt(tempbuf,ChiperDataBuf+4+16*i);
}
cleardog();
return(Blocks*16+4);
}
}
//#endif
以上是C文件。以下是頭文件
#ifndef AES_H
#define AES_H
extern void aesInit( unsigned char * tempbuf );
extern void aesDecrypt(unsigned char *buffer, unsigned char *chainBlock);
extern void aesEncrypt( unsigned char * buffer, unsigned char * chainBlock );
extern void aesInit( unsigned char * tempbuf );
extern void aesDecrypt( unsigned char * buffer, unsigned char * chainBlock );
extern void aesEncrypt( unsigned char * buffer, unsigned char * chainBlock );
extern unsigned char aesBlockDecrypt(bit Direct,unsigned char *ChiperDataBuf,unsigned char DataLen);
#endif // AES_H
這是我根據網上程序改寫的。只支持128位加解密。沒有使用占內存很多的查表法。故運算速度會稍慢。
❽ [高分]C語言對字元串的加密和解密
char
ch,name[30],over;
FILE
*fp;
printf("請輸入要加密的文件名(正確的做法是:先把解密的數不知道,你想要什麼樣的加密演算法。
AES不錯。不過AES是對16個位元組長度加密,要是不是16的倍數,處理有點麻煩據保存到字元串里,全部結束之後,一次性把解密