關於AES加解密演算法 |
答題得分者是:boss.tw
|
typer486
一般會員 發表:9 回覆:16 積分:5 註冊:2008-11-26 發送簡訊給我 |
[code cpp]
/* AES Encryption System*/ #include #include #define Nb 4 /* 明文 32 bits 區段數目 (4, 128 bits) */ int Nr=0; /* 加密運算回合, AES-128(10), 192(12), 256(14) */ int Nk=0; /* 鑰匙 32 bits 區塊數量, AES-128(4), 192(6), 256(8) */ unsigned char in[16]; // 明文區塊輸入陣列 unsigned char out[16]; // 密文區塊輸出陣列 unsigned char state[4][4]; // 加密運算的狀態陣列 4* 4 unsigned char RoundKey[240]; // 回合鑰匙陣列 unsigned char Key[32]; // 主秘密鑰匙 // 擷取 S-box 取代盒轉換表 int getSBoxValue(int num) { int sbox[256] = { //0 1 2 3 4 5 6 7 8 9 A B C D E F 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F return sbox[num]; } // 擷取逆向 S-box 取代盒轉換表 int getSBoxInvert(int num) { int rsbox[256] = { //0 1 2 3 4 5 6 7 8 9 A B C D E F 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, //0 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, //1 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, //2 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, //3 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, //4 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, //5 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, //6 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, //7 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, //8 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, //9 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, //A 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, //B 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, //C 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, //D 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, //E 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; //F return rsbox[num]; } // 回合常數陣列(round constant word array, Rcon[i]) int Rcon[255] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb }; /* 子鑰匙展開函數, 回合鑰匙 Nb(Nr 1), AES-128: 輸入:Nk(鑰匙區塊 AES-128(4), 192(5), 256(8)), Nr(回合), Nb, 主鑰匙 Key[] 輸出: RoundKeyp[]子鑰匙區塊, AES-128(44), 192(52), 256(60)*/ void KeyExpansion() { int i, j; unsigned char temp[4], k; // 第一回合子鑰匙 = 主鑰匙分成四個(Nb=4) 8 位元區塊 (W0=32 bits) // 第一回合需要 Nk 個鑰匙區塊, AES-128:Nk=4, W0 ~ W3 for ( i=0; i RoundKey[i*4] = Key[i*4]; RoundKey[i*4 1] = Key[i*4 1]; RoundKey[i*4 2] = Key[i*4 2]; RoundKey[i*4 3] = Key[i*4 3]; } // 其他回合鑰匙: AES-128: i=4 ~ 43, 共需 44 個鑰匙字元 (W0 ~ W43, 32 bits). while ( i < (Nb * (Nr 1)) ) { for ( j=0; j<4; j ) // Wi 計 4 個 8 位元陣列元素 temp[j] = RoundKey[(i-1) * 4 j]; if ( i % Nk == 0 ) { // RotWord 函數, i 是 4 個整數倍的 Wi // [a0,a1,a2,a3] 移位成 [a1,a2,a3,a0] { k = temp[0]; temp[0] = temp[1]; temp[1] = temp[2]; temp[2] = temp[3]; temp[3] = k; } // SubWord() S-box 字元取代函數 { temp[0] = getSBoxValue(temp[0]); temp[1] = getSBoxValue(temp[1]); temp[2] = getSBoxValue(temp[2]); temp[3] = getSBoxValue(temp[3]); } temp[0] = temp[0] ^ Rcon[i/Nk]; // 字元參數 } else if ( Nk > 6 && i % Nk == 4 ) { //僅 AES-256 適用, SubWord() 函數 temp[0] = getSBoxValue(temp[0]); temp[1] = getSBoxValue(temp[1]); temp[2] = getSBoxValue(temp[2]); temp[3] = getSBoxValue(temp[3]); } RoundKey[i*4 0] = RoundKey[(i-Nk)*4 0] ^ temp[0]; RoundKey[i*4 1] = RoundKey[(i-Nk)*4 1] ^ temp[1]; RoundKey[i*4 2] = RoundKey[(i-Nk)*4 2] ^ temp[2]; RoundKey[i*4 3] = RoundKey[(i-Nk)*4 3] ^ temp[3]; i ; } } // AddRoundKey() 回合鑰匙加法函數, Nb=4 void AddRoundKey(int round) { int i, j; for ( i=0; i<4; i ) { for ( j=0; j<4; j ) state[j][i] ^= RoundKey[round * Nb * 4 i * Nb j]; } } // SubBytes() 位元組取代函數 void SubBytes() { int i, j; for ( i=0; i<4; i ) { for ( j=0; j<4; j ) state[i][j] = getSBoxValue(state[i][j]); } } // InvSubBytes() 逆向位元組取代函數 void InvSubBytes() { int i, j; for ( i=0; i<4; i ) { for ( j=0; j<4; j ) state[i][j] = getSBoxInvert(state[i][j]); } } // ShiftRow() 移位列函數 void ShiftRows() { unsigned char temp; // 第二行向左迴旋 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; // 第三行向左迴旋 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; // 第四行向左迴旋 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; } // InvShiftRow() 逆向移位列函數 void InvShiftRows() { unsigned char temp; // 第二行向左迴旋 1 個位元組 temp=state[1][3]; state[1][3] = state[1][2]; state[1][2] = state[1][1]; state[1][1] = state[1][0]; state[1][0] = temp; // 第三行向左迴旋 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; // 第四行向左迴旋 3 個位元組 temp=state[3][0]; state[3][0] = state[3][1]; state[3][1] = state[3][2]; state[3][2] = state[3][3]; state[3][3] = temp; } // xtime macro: (x*{02}) mod {1b} #define xtime(x) ((x<<1) ^ (((x>>7) & 1) * 0x1b)) // Multiplty macro: (x * y) mod GF(2^8) #define Multiply(x,y) (((y & 1) * x) ^ ((y>>1 & 1) * xtime(x))\ ^ ((y>>2 & 1) * xtime(xtime(x)))\ ^ ((y>>3 & 1) * xtime(xtime(xtime(x))))\ ^ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) // MixColumns() 混合行運算函數 void MixColumns() { int i; unsigned char Tmp,Tm,t; for ( i=0; i<4; i ) { t=state[0][i]; Tmp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i] ; Tm = state[0][i] ^ state[1][i] ; Tm = xtime(Tm); state[0][i] ^= Tm ^ Tmp ; Tm = state[1][i] ^ state[2][i] ; Tm = xtime(Tm); state[1][i] ^= Tm ^ Tmp ; Tm = state[2][i] ^ state[3][i] ; Tm = xtime(Tm); state[2][i] ^= Tm ^ Tmp ; Tm = state[3][i] ^ t ; Tm = xtime(Tm); state[3][i] ^= Tm ^ Tmp ; } } // InvMixColumns() 逆向混合行運算函數 void InvMixColumns() { int i; unsigned char a, b, c, d; for ( i=0; i<4; i ) { a = state[0][i]; b = state[1][i]; c = state[2][i]; d = state[3][i]; state[0][i] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); state[1][i] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); state[2][i] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); state[3][i] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); } } // Cipher() AES 加密演算函數, // 輸入 Nr 回合次數, in[16] 明文區塊, 16*8=128 biys // 輸出 out[16] 密文區塊, 16*8=128 bits void Cipher() { int i, j, round=0; //將明文區塊 in[] 複製於 4 * 4 狀態陣列內 for ( i=0; i<4; i ) { for ( j=0; j<4; j ) state[j][i] = in[i*4 j]; } // 第 0 回合編碼: 僅執行回合鑰匙加法運算 AddRoundKey(0); // 第 1 到 Nr-1 回合編碼 for ( round=1; round SubBytes(); ShiftRows(); MixColumns(); AddRoundKey(round); } // 第 Nr 回合編碼, 缺少混合行運算 SubBytes(); ShiftRows(); AddRoundKey(Nr); // 將狀態陣列複製到密文輸出陣列上 for ( i=0; i<4; i ) { for ( j=0; j<4; j ) { out[i*4 j] = state[j][i]; } } } // InvCipher() AES 解密演算函數 void InvCipher() { int i, j, round=0; //將密文區塊複製於 4 * 4 狀態陣列內 for ( i=0; i<4; i ) { for ( j=0; j<4; j ) state[j][i] = in[i*4 j]; } // 第 Nr 回合編碼: 僅執行回合鑰匙加法運算 . AddRoundKey(Nr); // 第 Nr-1 到 1 回合編碼 for ( round=Nr-1; round>0; round-- ) { InvShiftRows(); InvSubBytes(); AddRoundKey(round); InvMixColumns(); } //第 0 回合編碼, 缺少混合行運算 InvShiftRows(); InvSubBytes(); AddRoundKey(0); // 將狀態陣列複製到明文輸出陣列上 for ( i=0; i<4; i ) { for ( j=0; j<4; j ) out[i*4 j] = state[j][i]; } } void main() { int i, Len=0; unsigned char in_Key[32], in_Plain[16]; char data; // 使用者決定鑰匙長度 printf( "*** AES 加密編碼 ***\n" ); while ( Len!=128 && Len!=192 && Len!=256 ) { printf( "請輸入鑰匙長度(僅 128, 192 或 256): " ); scanf( "%d", &Len ); } Nk = Len / 32; // 計算鑰匙區塊數量 (AES-128: 4) Nr = Nk 6; // 計算編碼運算回合數 (AES-128: 10) if ( Len == 128 ) { printf( "請輸入秘密鑰匙(16個字元) =>" ); scanf( "%s", &in_Key ); for ( i=0; i<16; i ) Key[i] = in_Key[i]; } else if ( Len == 192 ) { printf( "請輸入秘密鑰匙(24個字元) =>" ); scanf( "%s", &in_Key ); for ( i=0; i<24; i ) Key[i] = in_Key[i]; } else { printf( "請輸入秘密鑰匙(32 個字元) =>" ); scanf( "%s", &in_Key ); for ( i=0; i<32; i ) Key[i] = in_Key[i]; } // 呼叫回合鑰匙產生函數 KeyExpansion(); // 輸入key[], Nb(Nr 1) 輸出 RoundKey[] printf( "請輸入明文 =>" ); scanf( "%s", &data ); // 呼叫加密運算函數 Cipher(); // 輸入 in[], Key[], 輸出 out[] // 呼叫解密運算函數 InvCipher(); // 輸入 in[], Key[], 輸出 out[] getch(); } [/code] 請問各位先進小弟因需要用到AES的加解密演算法所以在網路上找到一些演算法的source code我也對照過密碼學書上的演算法code是沒問題可是我在main裡不知道該如何做加解密的運用可否請各位先進指導。謝謝! |
boss.tw
高階會員 發表:15 回覆:109 積分:194 註冊:2005-05-17 發送簡訊給我 |
unsigned char in[16]; // 明文區塊輸入陣列
unsigned char out[16]; // 密文區塊輸出陣列 printf( "請輸入明文 =>" ); scanf( "%s", &data ); // 呼叫加密運算函數 Cipher(); // 輸入 in[], Key[], 輸出 out[] // 呼叫解密運算函數 InvCipher(); // 輸入 in[], Key[], 輸出 out[] 你的註解好條已經說明的很清楚了 IN陣列儲存要加密的資料 OUT陣列儲存解密後的資料 |
typer486
一般會員 發表:9 回覆:16 積分:5 註冊:2008-11-26 發送簡訊給我 |
printf( "請輸入明文 =>" );
scanf( "%s", &in ); /* 呼叫加密運算函數 */ Cipher(); // 輸入 in[], Key[], 輸出 out[] for(i=0; i<16; i ) /* 密文輸出到檔案上 */ printf("%X", out[i]); /* 呼叫解密運算函數 */ InvCipher(); // 輸入 in[], Key[], 輸出 out[] for(i=0; i<16; i ) /* 明文輸出到檔案上 */ printf("%X", out[i]); 請問各位先進我在main裡面加入這幾行可以加密可是解密確解不回來,請各位先進指導...謝謝 |
boss.tw
高階會員 發表:15 回覆:109 積分:194 註冊:2005-05-17 發送簡訊給我 |
以下試過可以,請參考
[code cpp] printf( "請輸入明文 =>" ); scanf( "%s", &in ); // 呼叫加密運算函數 Cipher(); // 輸入 in[], Key[], 輸出 out[] printf("in[] = %s\nout[] = %s\n", in, out); memcpy( in, out, 16); //暫存上面 out[] ,copy 到 in 準備解密 memset( out, 0, 16); //清除 out // 呼叫解密運算函數 InvCipher(); // 輸入 in[], Key[], 輸出 out[] printf("in[] = %s\nout[] = %s\n", in, out); while(1); [/code] |
gn01739439
一般會員 發表:0 回覆:1 積分:0 註冊:2010-01-06 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |