凯撒算法
加密
for(i=0; i<strlen(passwd); i++)
{
if(passwd[i] >= 'A' && passwd[i] <= 'Z')
{
passwd[i] = ((passwd[i]-'A')+move)%26+'A';
}
else if(passwd[i] >= 'a' && passwd[i] <= 'z')
{
passwd[i] = ((passwd[i]-'a')+move)%26+'a';
}
}
解密
for(i=0; i<strlen(passwd); i++)
{
if(passwd[i] >= 'A' && passwd[i] <= 'Z')
{
passwd[i] = ((passwd[i]-'A')+26-move)%26+'A';
}
else if(passwd[i] >= 'a' && passwd[i] <= 'z')
{
passwd[i] = ((passwd[i]-'a')+26-move)%26+'a';
}
}
SM4算法
加密
-
生成s盒
- 特征是传入128位密钥(v2)
- 19行异或的数也是sm4的一个特征值
-
明文加密
- input划分为4个4字节的值,赋给v5,v5数组按照往后递推的方式,由前4个单元生成后1个单元的值,最后逐个字节取v5[32]到v5[35]的值赋给out
- sub_411700长这样,第一个v5单元的值和sub_41170函数异或,函数的参数为v5后三个单元和key的异或,最后计算的值再赋给第5个v5单元
解密
import sm4
key = sm4.SM4Key(b"where_are_u_now?")
print key.decrypt(sm4_encoded)
查表算法
加密
a="?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z"
index='PQHRSIDTUJVWKEBXYLZ[MF\]N^_OGCA'
b=[0]*31
for i in range(31):
b[i]=a[ord(index[i])]
解密
b="?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z"
index='PQHRSIDTUJVWKEBXYLZ[MF\]N^_OGCA'
a=[0]*31
for i in range(31):
a[ord(index[i])]=b[i]
二叉树算法
加密
typedef struct Node{
DataType Data;
struct Node *lchild, *rchild;
}BinTNode, *BiTree;
void Create_BinTree(BiTree *T)
{
char ch;
scanf("%c",&ch);
if(ch=='#')
{
*T==NULL;
// return;
}
else
{
*T=(BinTNode*)malloc(sizeof(BinTNode));
(*T)->Data=ch;
printf("\n建立左子树\n");
(*T)->lchild=NULL;
(*T)->rchild=NULL;
Create_BinTree( &((*T)->lchild ) );//建立左子树
printf("\n建立右子树\n");
Create_BinTree( &((*T)->rchild ) );//建立右子树
}
return ;
}
void PostOrder_Traverase(BiTree T)//后序遍历
{
if(T==NULL)
return ;
else
{
PostOrder_Traverase(T->lchild);
PostOrder_Traverase(T->rchild);
printf(" %c " , T->Data);
}
}
解密
# 二叉树的遍历本质上是一个位置映射,当做一个黑盒处理
# 输入'ABCDEFGHIJKLMNOPQRSTUVWXYZ',程序输出index字符串
# 利用index的位置映射关系来恢复待解密的字符串a
a="?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z"
index='PQHRSIDTUJVWKEBXYLZ[MF\]N^_OGCA'
b=[0]*31
for i in range(31):
b[ord(index[i])-ord('A')]=a[i]
已知中序和后序,求先序
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char post[] = "20f0Th{2tsIS_icArE}e7__w"; //后序遍历结果
char mid[] = "2f0t02T{hcsiI_SwA__r7Ee}"; //中序遍历结果
void f(int root,int start,int end)
{
if(start > end)
return ;
int i = start;
while(i < end && mid[i] != post[root])
i++; //定位根在中序的位置
printf("%c",mid[i]);
f(root - 1-(end - i),start,i - 1); //递归处理左子树
f(root-1,i + 1,end); //递归处理右子树
}
int main()
{
f(24,0,24);
return 0;
}
满二叉树已知任一序,可以求任一序
循环左移/右移算法
正运算
for ( i = 0; i < strlen(input); ++i )
{
if ( (i & 1) != 0 ) // 奇数循环右移
v1 = (input[i] >> 2) | (input[i] << 6);
else // 偶数循环左移
v1 = (4 * input[i]) | (input[i] >> 6);
input[i] = v1;
}
逆运算
for i in range(0,len(result)):
t = result[i]
if i&1==0: //偶数循环右移
input[i]=(t&0x3)<<6|(t&0xfc)>>2 #低2位左移6位,高6位右移2位 相当于循环右移2位
else: //奇数循环左移
input[i]=(t&0x3f)<<2|(t&0xc0)>>6 #低6位左移2位,高2位右移6位 相当于循环左移2位
base64
加密
- 识别
-
脚本
import base64 str='admin' bs64=base64.b64encode(str.encode('utf-8'))
解密
-
识别
void *__fastcall RxEncode(const char *input, int len) { void *result; // rax int sz; // [rsp+18h] [rbp-38h] signed int paddingSz; // [rsp+1Ch] [rbp-34h] int idx; // [rsp+20h] [rbp-30h] signed int v6; // [rsp+24h] [rbp-2Ch] int v7; // [rsp+28h] [rbp-28h] int v8; // [rsp+28h] [rbp-28h] signed int i; // [rsp+2Ch] [rbp-24h] _BYTE *v10; // [rsp+30h] [rbp-20h] void *s; // [rsp+38h] [rbp-18h] sz = 3 * (len / 4); paddingSz = 0; idx = 0; if ( input[len - 1] == '=' ) paddingSz = 1; if ( input[len - 2] == '=' ) ++paddingSz; if ( input[len - 3] == '=' ) ++paddingSz; if ( paddingSz == 3 ) { sz += 2; } else if ( paddingSz <= 3 ) { if ( paddingSz == 2 ) { sz += 3; } else if ( paddingSz <= 2 ) { if ( paddingSz ) { if ( paddingSz == 1 ) sz += 4; } else { sz += 4; } } } s = malloc(sz); if ( s ) { memset(s, 0, sz); v10 = s; while ( idx < len - paddingSz ) { v6 = 0; v7 = 0; while ( v6 <= 3 && idx < len - paddingSz ) { v7 = (v7 << 6) | (char)find_pos(input[idx]); ++v6; ++idx; } v8 = v7 << 6 * (4 - v6); for ( i = 0; i <= 2 && i != v6; ++i ) *v10++ = v8 >> 8 * (2 - i); } *v10 = 0; result = s; } else { puts("No enough memory."); result = 0LL; } return result; }
-
脚本
import base64 debs64=base64.b64decode(bs64)
换表的base64解密脚本
import base64
import string
str1 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q"
string1 = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))
base58
strcpy(v23, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
v21 = 138 * strlen(v19) / 0x64;
v14 = v21 + 1;
v1 = 0;
v22 = (_BYTE *)MEMORY[0x8114](v21 + 1);
v2 = v22;
sub_402C08(v22, 0, v14);
v3 = v19;
v20 = (int)(v19 + 1);
if ( strlen(v19) )
{
v4 = &v2[v21];
v18 = v4;
while ( 1 )
{
v20 = ((char)*v4 << 8) + v3[v1];
v5 = v20 / 58;
*v4 = v20 % 58;
if ( v5 )
{
do
{
v6 = (char)*--v4;
v7 = (v6 << 8) + v5;
v20 = v7 / 58;
*v4 = v7 % 58;
v5 = v20;
}
while ( v20 );
v4 = v18;
}
if ( ++v1 >= strlen(v19) )
break;
v3 = v19;
}
v2 = v22;
}
v8 = 0;
if ( !*v2 )
{
do
++v8;
while ( !v2[v8] );
}
v9 = v21;
if ( v8 <= v21 )
{
v10 = v2 - (_BYTE *)v24;
do
{
v11 = (char *)v24 + v8++;
*v11 = v23[(char)v11[v10]];
}
while ( v8 <= v9 );
}
if ( !MEMORY[0x7C1A](v24, "56fkoP8KhwCf3v7CEz") )
tea系列算法
tea
-
TEA加密解密是以原文以8字节(64位bit)为一组,密钥16字节(128位bit)为一组,该算法加密轮次可变,作者建议为32轮,因为被加密的明文为64位,所以最终加密的结果也是64位
-
实现
#include <stdio.h> #include <stdint.h> //加密函数 void encrypt (uint32_t* v, uint32_t* k) { uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */ uint32_t delta=0x9e3779b9; /* a key schedule constant */ uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ for (i=0; i < 32; i++) { /* basic cycle start */ sum += delta; v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); } /* end cycle */ v[0]=v0; v[1]=v1; } //解密函数 void decrypt (uint32_t* v, uint32_t* k) { uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */ uint32_t delta=0x9e3779b9; /* a key schedule constant */ uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ for (i=0; i<32; i++) { /* basic cycle start */ v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); sum -= delta; } /* end cycle */ v[0]=v0; v[1]=v1; }
xtea
-
XTEA是TEA的升级版,增加了更多的密钥表,移位和异或操作
-
实现
#include <stdio.h> #include <stdint.h> /* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */ void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9; for (i=0; i < num_rounds; i++) { v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); sum += delta; v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); } v[0]=v0; v[1]=v1; } void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds; for (i=0; i < num_rounds; i++) { v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); sum -= delta; v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); } v[0]=v0; v[1]=v1; } int main() { uint32_t v[2]={1,2}; uint32_t const k[4]={2,2,3,4}; unsigned int r=32;//num_rounds建议取值为32 // v为要加密的数据是两个32位无符号整数 // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位 printf("加密前原始数据:%u %u\n",v[0],v[1]); encipher(r, v, k); printf("加密后的数据:%u %u\n",v[0],v[1]); decipher(r, v, k); printf("解密后的数据:%u %u\n",v[0],v[1]); return 0; }
xxtea
-
特点:原字符串长度可以不是4的倍数了
-
实现
#include <stdio.h> #include <stdint.h> #define DELTA 0x9e3779b9 #define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z))) void btea(uint32_t *v, int n, uint32_t const key[4]) { uint32_t y, z, sum; unsigned p, rounds, e; if (n > 1) /* Coding Part */ { rounds = 6 + 52/n; sum = 0; z = v[n-1]; do { sum += DELTA; e = (sum >> 2) & 3; for (p=0; p<n-1; p++) { y = v[p+1]; z = v[p] += MX; } y = v[0]; z = v[n-1] += MX; } while (--rounds); } else if (n < -1) /* Decoding Part */ { n = -n; rounds = 6 + 52/n; sum = rounds*DELTA; y = v[0]; do { e = (sum >> 2) & 3; for (p=n-1; p>0; p--) { z = v[p-1]; y = v[p] -= MX; } z = v[n-1]; y = v[0] -= MX; sum -= DELTA; } while (--rounds); } } int main() { uint32_t v[2]= {1,2}; uint32_t const k[4]= {2,2,3,4}; int n= 2; //n的绝对值表示v的长度,取正表示加密,取负表示解密 // v为要加密的数据是两个32位无符号整数 // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位 printf("加密前原始数据:%u %u\n",v[0],v[1]); btea(v, n, k); printf("加密后的数据:%u %u\n",v[0],v[1]); btea(v, -n, k); printf("解密后的数据:%u %u\n",v[0],v[1]); return 0; }
-
(链接)vs中导入头文件编译,可直接使用decode函数
RC4算法
- RC4加密原理很简单,只需要一个KeyStream与明文进行异或即可,密钥流的长度和明文的长度是对应的。RC4算法的的主要代码还是在于如何生成秘钥流
- 密钥流的生成由两部分组成:
- KSA(the Key-Scheduling Algorithm)
- PRGA(the Pseudo-Random Generation Algorithm)
- 实现
#include<stdio.h>
#include<string.h>
#define SBOX_LEN 256
#define rc4_encrypt rc4_crypt
#define rc4_decrypt rc4_crypt
static inline void swap_uchar(unsigned char *puc_x, unsigned char *puc_y)
{
*puc_x = *puc_x ^ *puc_y;
*puc_y = *puc_x ^ *puc_y;
*puc_x = *puc_x ^ *puc_y;
}
void hexdump(unsigned char *puc_data, int length)
{
int i = 0;
for (i = 0; i < length; i++) {
printf("%02X", puc_data[i]);
if (i && (i + 1) % 16 == 0) {
putchar('\n');
}
}
printf("\n");
}
/**
* 利用Key生成S盒,伪随机数生成器
* the Key-Scheduling Algorithm
*/
static void rc4_ksa(unsigned char *puc_sbox, unsigned char *puc_key, int key_length)
{
int i = 0;
int j = 0;
char tmp[SBOX_LEN] = {0};
for (i = 0; i < SBOX_LEN; i++) {
puc_sbox[i] = i;
tmp[i] = puc_key[i % key_length];
}
for (i = 0; i < SBOX_LEN; i++) {
j = (j + puc_sbox[i] + tmp[i]) % SBOX_LEN;
swap_uchar(&puc_sbox[i], &puc_sbox[j]); //交换puc_sbox[i]和puc_sbox[j]
}
}
/**
* 利用S盒生成密钥流
* The pseudo-random generation algorithm(PRGA)
*/
static void rc4_prga(unsigned char *puc_sbox, unsigned char *puc_key_stream, unsigned long ul_data_length)
{
int i = 0;
int j = 0;
int t = 0;
unsigned long k = 0;
for (k = 0; k < ul_data_length; k++) {
i = (i + 1) % SBOX_LEN;
j = (j + puc_sbox[i]) % SBOX_LEN;
swap_uchar(&puc_sbox[i], &puc_sbox[j]);
t = (puc_sbox[i] + puc_sbox[j]) % SBOX_LEN;
/* 为了更清晰理解rc4算法流程,此处保存keystream,不直接进行XOR运算 */
puc_key_stream[k] = puc_sbox[t];
}
}
/* 加解密 */
void rc4_crypt(unsigned char *puc_data, unsigned char *puc_key_stream, unsigned long ul_data_length)
{
unsigned long i = 0;
/* 把PRGA算法放在加解密函数中可以不需要保存keystream */
for (i = 0; i < ul_data_length; i++) {
puc_data[i] ^= puc_key_stream[i];
}
}
int main(int argc, char *argv[])
{
unsigned char sbox[SBOX_LEN] = {0};
char key[SBOX_LEN] = {"abcdefghijklmnopqrstuvwxyz"}; //秘钥内容随便定义
char data[512] = "[email protected] lvfvr#9527";
unsigned char puc_keystream[512] = {0};
unsigned long ul_data_length = strlen(data);
printf("key=%s, length=%d\n\n", key, strlen(key));
printf("Raw data string:%s\n", data);
printf("Raw data hex:\n");
hexdump(data, ul_data_length);
/* 生成S-box */
rc4_ksa(sbox, (unsigned char *)key, strlen(key));
/* 生成keystream并保存,S-box也会被更改 */
rc4_prga(sbox, puc_keystream, ul_data_length);
printf("S-box final status:\n");
hexdump(sbox, sizeof(sbox));
printf("key stream:\n");
hexdump(puc_keystream, ul_data_length);
/* 加密 */
rc4_encrypt((unsigned char*)data, puc_keystream, ul_data_length);
printf("cipher hexdump:\n");
hexdump(data, ul_data_length);
/* 解密 */
rc4_decrypt((unsigned char*)data, puc_keystream, ul_data_length);
printf("decypt data:%s\n", data);
return 0;
}
- 脚本
from Crypto.Cipher import ARC4
rc4 = ARC4.new(key)
print rc4.decrypt(encoded)
CRC算法
/*
**初始化crc表,生成32位大小的crc表
**也可以直接定义出crc表,直接查表,
**但总共有256个,看着眼花,用生成的比较方便,
**对0-255进行模2除法生成crc表.
*/
static void init_crc_table(void)
{
unsigned int c;
unsigned int i, j;
for (i = 0; i < 256; i++) {
c = (unsigned int)i;
for (j = 0; j < 8; j++) {
if (c & 1)
c = 0xedb88320L ^ (c >> 1);
else
c = c >> 1;
}
crc_table[i] = c;
}
}
/*计算buffer的crc校验码*/
static unsigned int crc32(unsigned int crc,unsigned char *buffer, unsigned int size)
{
unsigned int i;
for (i = 0; i < size; i++) {
crc = crc_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
}
return crc ;
}
MD5算法
特征值
void MD5Init (MD5_CTX *context)
{
/*将当前的有效信息的长度设成0,这个很简单,还没有有效信息,长度当然是0了*/
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.*/
/*初始化变量,算法要求这样 */
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
RSA算法
加密
-
选取两个大素数p和q,为了获得最高安全性,设两数长度一样
-
计算n=p*q,n称为模
-
选取加密密钥e,其与φ(n)互素。如果选择的e值合适,RSA加解密的速度会加快。e的常用值为3、17、和65537(2^16+1)
-
公钥为e和n,加密消息m时,将其看成一个大整数,并把它分成比n小的数据分组
c[i] = m[i]^e mod n
解密
-
计算欧拉函数:
φ(n)=(p-1)(q-1)
-
使用扩展欧几里德算法求出e模φ(n)的逆元d
e*d mod φ(n) = 1
-
密钥为d和n,解密密文c时,取每个加密后的分组c[i]
m[i] = c[i]^d mod n
还原
import gmpy2
import rsa
e = 65537
n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463
phin = (q-1)*(p-1)
d = gmpy2.invert(e, phin)
key = rsa.PrivateKey(n, e, int(d), p, q)
with open("G:\\output\\flag.txt", "rb+") as f:
f = f.read()
print(rsa.decrypt(f, key))
AES算法
原理
特征
-
密文的长度必须是0x10字节的倍数
-
秘钥的长度是 0x10 或0x18或0x20字节
-
T1-T4 静态数组数据用于加密数据,T5-T8 静态数组数据用于解密数据,其他静态数组用于初始化
模式
- ECB
- CBC
代码实现
#include <stdio.h>
#include <windows.h>
/*s盒矩阵:The AES Substitution Table*/// 256 位的密匙256 位支持长度为32 个字符
static const unsigned char sbox[256] = {
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,
};
//逆向S 盒矩阵
static const unsigned char contrary_sbox[256] = {
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,
};
/*轮常量表 The key schedule rcon table*/
static const unsigned char Rcon[10] = {
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36 };
//辅助函数
/*有限域*2乘法 The x2time() function */
static unsigned char x2time(unsigned char x)
{
if (x & 0x80)
{
return (((x << 1) ^ 0x1B) & 0xFF);
}
return x << 1;
}
/*有限域*3乘法 The x2time() function */
static unsigned char x3time(unsigned char x)
{
return (x2time(x) ^ x);
}
/*有限域*4乘法 The x4time() function */
static unsigned char x4time(unsigned char x)
{
return (x2time(x2time(x)));
}
/*有限域*8乘法 The x8time() function */
static unsigned char x8time(unsigned char x)
{
return (x2time(x2time(x2time(x))));
}
/*有限域9乘法 The x9time() function */
static unsigned char x9time(unsigned char x) //9:1001
{
return (x8time(x) ^ x);
}
/*有限域*B乘法 The xBtime() function */
static unsigned char xBtime(unsigned char x) //B:1011
{
return (x8time(x) ^ x2time(x) ^ x);
}
/*有限域*D乘法 The xDtime() function */
static unsigned char xDtime(unsigned char x) //D:1101
{
return (x8time(x) ^ x4time(x) ^ x);
}
/*有限域*E乘法 The xEtime() function */
static unsigned char xEtime(unsigned char x) //E:1110
{
return (x8time(x) ^ x4time(x) ^ x2time(x));
}
/*第三类操作:列混合操作 MixColumns: Process the entire block*/
static void MixColumns(unsigned char *col)//列混合
{
unsigned char tmp[4], xt[4];
int i;
for (i = 0; i<4; i++, col += 4) //col代表一列的基地址,col+4:下一列的基地址
{
tmp[0] = x2time(col[0]) ^ x3time(col[1]) ^ col[2] ^ col[3]; //2 3 1 1
tmp[1] = col[0] ^ x2time(col[1]) ^ x3time(col[2]) ^ col[3]; //1 2 3 1
tmp[2] = col[0] ^ col[1] ^ x2time(col[2]) ^ x3time(col[3]); //1 1 2 3
tmp[3] = x3time(col[0]) ^ col[1] ^ col[2] ^ x2time(col[3]); //3 1 1 2
//修改后的值 直接在原矩阵上修改
col[0] = tmp[0];
col[1] = tmp[1];
col[2] = tmp[2];
col[3] = tmp[3];
}
}
//逆向列混淆
static void Contrary_MixColumns(unsigned char *col)
{
unsigned char tmp[4];
unsigned char xt2[4];//colx2
unsigned char xt4[4];//colx4
unsigned char xt8[4];//colx8
int x;
for (x = 0; x<4; x++, col += 4)
{
tmp[0] = xEtime(col[0]) ^ xBtime(col[1]) ^ xDtime(col[2]) ^ x9time(col[3]);
tmp[1] = x9time(col[0]) ^ xEtime(col[1]) ^ xBtime(col[2]) ^ xDtime(col[3]);
tmp[2] = xDtime(col[0]) ^ x9time(col[1]) ^ xEtime(col[2]) ^ xBtime(col[3]);
tmp[3] = xBtime(col[0]) ^ xDtime(col[1]) ^ x9time(col[2]) ^ xEtime(col[3]);
col[0] = tmp[0];
col[1] = tmp[1];
col[2] = tmp[2];
col[3] = tmp[3];
}
}
/*第二类操作:行移位:行左循环移位 ShiftRows:Shifts the entire block*/
static void ShiftRows(unsigned char *col)//正向行移位
{
unsigned char t;
t = col[1]; col[1] = col[5]; col[5] = col[9]; col[9] = col[13]; col[13] = t;
t = col[2]; col[2] = col[10]; col[10] = t;
t = col[6]; col[6] = col[14]; col[14] = t;
t = col[15]; col[15] = col[11]; col[11] = col[7]; col[7] = col[3]; col[3] = t;
}
//逆向行移位
static void Contrary_ShiftRows(unsigned char *col)
{
unsigned char t;
t = col[13]; col[13] = col[9]; col[9] = col[5]; col[5] = col[1]; col[1] = t;
t = col[2]; col[2] = col[10]; col[10] = t;
t = col[6]; col[6] = col[14]; col[14] = t;
t = col[3]; col[3] = col[7]; col[7] = col[11]; col[11] = col[15]; col[15] = t;
}
/*第一类操作:s盒字节代换替换 SubBytes*/
static void SubBytes(unsigned char *col)//字节代换
{
int x;
for (x = 0; x<16; x++)
{
col[x] = sbox[col[x]];
}
}
//逆向字节代换
static void Contrary_SubBytes(unsigned char *col)
{
int x;
for (x = 0; x<16; x++)
{
col[x] = contrary_sbox[col[x]];
}
}
/*第四类操作:轮密钥加 AddRoundKey*/
static void AddRoundKey(unsigned char *col, unsigned char *expansionkey, int round)//密匙加
{
//扩展密钥:44*32bit =11*4* 4*8 = 16字节*11轮,每轮用16字节密钥
//第0轮,只进行一次轮密钥加
//第1-10轮,轮密钥加
int x;
for (x = 0; x<16; x++) //每1轮操作:4*32bit密钥 = 16个字节密钥
{
col[x] ^= expansionkey[(round << 4) + x];
}
}
/* AES加密总函数 10轮4类操作 Encrypt a single block with Nr Rounds(10,12,14)*/
void AesEncrypt(unsigned char *blk, unsigned char *expansionkey, int Nr)//加密一个区块
{
//输入blk原文,直接在上面修改,输出blk密文
//输入skey:
//输入Nr = 10轮
int round;
//第1轮之前:轮密钥加
AddRoundKey(blk, expansionkey, 0);
//第1-9轮:4类操作:字节代换、行移位、列混合、轮密钥加
for (round = 1; round <= (Nr - 1); round++)
{
SubBytes(blk); //输入16字节数组,直接在原数组上修改
ShiftRows(blk); //输入16字节数组,直接在原数组上修改
MixColumns(blk); //输入16字节数组,直接在原数组上修改
AddRoundKey(blk, expansionkey, round);
}
//第10轮:不进行列混合
SubBytes(blk);
ShiftRows(blk);
AddRoundKey(blk, expansionkey, Nr);
}
//AES 解密总函数
void Contrary_AesEncrypt(unsigned char *blk, unsigned char *expansionkey, int Nr)
{
int x;
/* unsigned char *contrary_key=key;
for(x=0;x<11;x++,key+=16)
Contrary_MixColumns(key);*/
AddRoundKey(blk, expansionkey, Nr);
Contrary_ShiftRows(blk);
Contrary_SubBytes(blk);
for (x = (Nr - 1); x >= 1; x--)
{
AddRoundKey(blk, expansionkey, x);
Contrary_MixColumns(blk);
Contrary_ShiftRows(blk);
Contrary_SubBytes(blk);
}
AddRoundKey(blk, expansionkey, 0);
}
/*//密钥编排,16字节--->44列32bit密钥生成--> 11组16字节:分别用于11轮 轮密钥加运算
Schedule a secret key for use.
*outkey[] must be 16*15 bytes in size
*Nk==number of 32 bit words in the key,e.g.,4,6,8
*Nr==number of rounds,e.g.,10,12,14
*/
void ScheduleKey(unsigned char *inkey, unsigned char *outkey, int Nk, int Nr)//安排一个保密密钥使用
{
//inkey:初始16字节密钥key
//outkey:11组*16字节扩展密钥expansionkey
//Nk:4列
//Nr:10轮round
unsigned char temp[4], t;
int x, i;
/*copy the key*/
//第0组:[0-3]直接拷贝
for (i = 0; i<(4 * Nk); i++)
{
outkey[i] = inkey[i];
}
//第1-10组:[4-43]
i = Nk;
while (i<(4 * (Nr + 1))) //i=4~43 WORD 32bit的首字节地址,每一个4字节
{//1次循环生成1个字节扩展密钥,4次循环生成一个WORD
//temp:4字节数组:代表一个WORD密钥
/*temp=w[i-1]*/
//i不是4的倍数的时候
//每个temp = 每个outkey32bit = 4字节
for (x = 0; x<4; x++)
temp[x] = outkey[(4 * (i - 1)) + x]; //i:32bit的首字节地址
//i是4的倍数的时候
if (i%Nk == 0)
{
/*字循环:循环左移1字节 RotWord()*/
t = temp[0]; temp[0] = temp[1]; temp[1] = temp[2]; temp[2] = temp[3]; temp[3] = t;
/*字节代换:SubWord()*/
for (x = 0; x<4; x++)
{
temp[x] = sbox[temp[x]];
}
/*轮常量异或:Rcon[j]*/
temp[0] ^= Rcon[(i / Nk) - 1];
}
/*w[i] = w[i-4]^w[i-1]*/
for (x = 0; x<4; x++)
{
outkey[(4 * i) + x] = outkey[(4 * (i - Nk)) + x] ^ temp[x];
}
++i;
}
}
int main(void) {
/*
pt:原文16字节-->密文
key:原密钥16字节
skey:密钥扩展44long
sbox:s盒
*/
unsigned char pt[17], key[17];
unsigned char expansionkey[15 * 16];
int i;
int j;
printf("输入需要加密字符串: \n");//输入无格式的字符串字符个数不得少于六个!
scanf("%s", pt);
printf("输入加密密钥: \n");//输入加密钥匙密匙个数不得低于六个!
scanf("%s", key);
/*加密*/
ScheduleKey(key, expansionkey, 4, 10); //1、密钥扩展生成
AesEncrypt(pt, expansionkey, 10); //2、AES 加密
printf("加密后的数据: "); //输出密码文件
for (i = 0; i < 16; i++)
printf("%02x ", pt[i]);
printf("\n");
/*解密*/
Contrary_AesEncrypt(pt, expansionkey, 10);//AES 解密
printf("解密后的数据: ");//将解密文件输出
for (i = 0; i < 16; i++)
printf("%c ", pt[i]);
system("pause");
return 0;
}
脚本还原
- ECB
from Crypto.Cipher import AES
password = b'1234567812345678' #秘钥,b就是表示为bytes类型
text = b'abcdefghijklmnhi' #需要加密的内容,bytes类型
aes = AES.new(password,AES.MODE_ECB) #创建一个aes对象
# AES.MODE_ECB 表示模式是ECB模式
en_text = aes.encrypt(text) #加密明文
print("密文:",en_text) #加密明文,bytes类型
den_text = aes.decrypt(en_text) # 解密密文
print("明文:",den_text)
- CBC
from Crypto.Cipher import AES
password = b'1234567812345678' #秘钥,b就是表示为bytes类型
iv = b'1234567812345678' # iv偏移量,bytes类型
text = b'abcdefghijklmnhi' #需要加密的内容,bytes类型
aes = AES.new(password,AES.MODE_CBC,iv) #创建一个aes对象
# AES.MODE_CBC 表示模式是CBC模式
en_text = aes.encrypt(text)
print("密文:",en_text) #加密明文,bytes类型
aes = AES.new(password,AES.MODE_CBC,iv) #CBC模式下解密需要重新创建一个aes对象
den_text = aes.decrypt(en_text)
print("明文:",den_text)
DES算法
原理
特征
-
密文的长度必须是0x08字节的倍数
-
秘钥的长度必须是 0x08字节
脚本还原
import base64
from Crypto.Cipher import DES
encryptData = "xZWDZaKEhWNMCbiGYPBIlY3+arozO9zonwrYLiVL4njSez2RYM2WwsGnsnjCDnHs7N43aFvNE54noSadP9F8eEpvTs5QPG+KL0TDE/40nbU="
e = base64.b64decode(encryptData)
# 在C#中,字符串默认是Unicode字符串,所以转成字节数组,在每个字符字节后都要加一个"\x00"
keyiv = b"t\x00e\x00s\x00t\x00"
d = DES.new(keyiv, DES.MODE_CBC, keyiv)
print(d.decrypt(e).decode("utf-16"))
标签:逆向,加密,int,unsigned,puc,char,re,算法,key
From: https://www.cnblogs.com/z5onk0/p/17508358.html