内容纲要

base64

IMG_0798

代码实现

/*base64.c*/  
#include "base64.h"  

unsigned char *base64_encode(unsigned char *str)  
{  
    long len;  
    long str_len;  
    unsigned char *res;  
    int i,j;  
//定义base64编码表  
    unsigned char *base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  

//计算经过base64编码后的字符串长度  
    str_len=strlen(str);  
    if(str_len % 3 == 0)  
        len=str_len/3*4;  
    else  
        len=(str_len/3+1)*4;  

    res=malloc(sizeof(unsigned char)*len+1);  
    res[len]='\0';  

//以3个8位字符为一组进行编码  
    for(i=0,j=0;i<len-2;j+=3,i+=4)  
    {  
        res[i]=base64_table[str[j]>>2]; //取出第一个字符的前6位并找出对应的结果字符  
        res[i+1]=base64_table[(str[j]&0x3)<<4 | (str[j+1]>>4)]; //将第一个字符的后位与第二个字符的前4位进行组合并找到对应的结果字符  
        res[i+2]=base64_table[(str[j+1]&0xf)<<2 | (str[j+2]>>6)]; //将第二个字符的后4位与第三个字符的前2位组合并找出对应的结果字符  
        res[i+3]=base64_table[str[j+2]&0x3f]; //取出第三个字符的后6位并找出结果字符  
    }  

    switch(str_len % 3)  
    {  
        case 1:  
            res[i-2]='=';  
            res[i-1]='=';  
            break;  
        case 2:  
            res[i-1]='=';  
            break;  
    }  

    return res;  
}  

unsigned char *base64_decode(unsigned char *code)  
{  
//根据base64表,以字符找到对应的十进制数据  
    int table[]={0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,62,0,0,0,
             63,52,53,54,55,56,57,58,
             59,60,61,0,0,0,0,0,0,0,0,
             1,2,3,4,5,6,7,8,9,10,11,12,
             13,14,15,16,17,18,19,20,21,
             22,23,24,25,0,0,0,0,0,0,26,
             27,28,29,30,31,32,33,34,35,
             36,37,38,39,40,41,42,43,44,
             45,46,47,48,49,50,51
               };  
    long len;  
    long str_len;  
    unsigned char *res;  
    int i,j;  

//计算解码后的字符串长度  
    len=strlen(code);  
//判断编码后的字符串后是否有=  
    if(strstr(code,"=="))  
        str_len=len/4*3-2;  
    else if(strstr(code,"="))  
        str_len=len/4*3-1;  
    else  
        str_len=len/4*3;  

    res=malloc(sizeof(unsigned char)*str_len+1);  
    res[str_len]='\0';  

//以4个字符为一位进行解码  
    for(i=0,j=0;i < len-2;j+=3,i+=4)  
    {  
        res[j]=((unsigned char)table])<<2 | (((unsigned char)table])>>4); //取出第一个字符对应base64表的十进制数的前6位与第二个字符对应base64表的十进制数的后2位进行组合  
        res[j+1]=(((unsigned char)table])<<4) | (((unsigned char)table])>>2); //取出第二个字符对应base64表的十进制数的后4位与第三个字符对应bas464表的十进制数的后4位进行组合  
        res[j+2]=(((unsigned char)table])<<6) | ((unsigned char)table]); //取出第三个字符对应base64表的十进制数的后2位与第4个字符进行组合  
    }  

    return res;  

}  

识别

索引表

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

base58

不使用数字"0",字母大写"O",字母大写"I",和字母小写"i",以及"+"和"/"符号。

base32

识别

字母全是大写且没有1(A-Z,2-7——共32)

feistel

算法原理

明文P被分为等长的左右两部分,右半部分R0与该轮子密钥K经过F函数运算后,再与左半部分L0做异或运算,最终结果作为下一轮的右半部分输入R1;同时右半部分R0直接作为下一轮左半部分输入L1,这样的一次运算称为一轮。

DES

算法原理

DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小(密钥通常表示为64位的数,但每个第8位都用作奇偶校验,可以忽略,但写程序时为了统一,还是采用64为密钥,但经过密钥置换操作后,就会去除掉其中的奇偶校验位)。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。

image-20210521143550293

产生16个密钥的过程

image-20210521143720293

明文加密过程

image-20210521144034926

通俗易懂的讲des文章

代码实现

#include<stdio.h>  
#include<string.h>  
//#define gets_s gets   //出现[Error] 'gets_s' was not declared in this scope的话就加上这句,默认使用的gcc编译器的话会出现此错误,因为gets_s是vs提供的函数
int IP_Table[64] = {                                     //IP置换矩阵  
    58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
    62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
    57, 49, 41, 33, 25, 17,  9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
    61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 };
int E_Table[48] = {                                    //扩展矩阵  
    32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,
    8,  9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
    16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
    24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32,  1 };
int P_Table[32] = {                                             //  P 盒  
    16, 7, 20, 21, 29, 12, 28, 17, 1,  15, 23, 26, 5,  18, 31, 10,
    2,  8, 24, 14, 32, 27, 3,  9,  19, 13, 30, 6,  22, 11, 4,  25 };
int IPR_Table[64] = {                                    //逆IP置换矩阵  
    40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
    38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
    36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
    34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41,  9, 49, 17, 57, 25 };
int PC1_Table[56] = {                               //密钥第一次置换矩阵  
    57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
    10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
    63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
    14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4 };
int PC2_Table[48] = {                          // 密钥第二次置换矩阵  
    14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
    23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
    41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
    44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 };
int S_Box[8][4][16] = {                     //8个S盒   三维数组  
                                            // S1   
    14, 4,  13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
    0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
    4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
    15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
    // S2   
    15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
    3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
    0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
    13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
    // S3   
    10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
    13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
    13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
    1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
    // S4   
    7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
    13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
    10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
    3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
    // S5   
    2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
    14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
    4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
    11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
    // S6   
    12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
    10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
    9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
    4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
    // S7   
    4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
    13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
    1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
    6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
    // S8   
    13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
    1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
    7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
    2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
};
static void CharToBit(const char input[], int output[], int bits)//把CHAR转换为INT  
{
    int i, j;
    for (j = 0; j<8; j++)
    {
        for (i = 0; i<8; i++)
        {
            output[7 * (j + 1) - i + j] = (input[j] >> i) & 1;
        }
    }
};
static void BitToChar(const int intput[], char output[], int bits)//把INT转换为CHAR  
{
    int i, j;
    for (j = 0; j<8; j++)
    {
        for (i = 0; i<8; i++)
        {
            output[j] = output[j] * 2 + intput[i + 8 * j];
        }
    }
};
static void Xor(int *INA, int *INB, int len)//异或操作  
{
    int i;
    for (i = 0; i<len; i++)
    {
        *(INA + i) = *(INA + i) ^ *(INB + i);
    }
};
static  void IP(const int input[64], int output[64], int table[64])//初始IP置换  
{
    int i;
    for (i = 0; i<64; i++)
    {
        output[i] = input[table[i] - 1];//减1操作不可少!!  
    }
};
static  void E(const int input[32], int output[48], int table[48])//E扩展  
{
    int i;
    for (i = 0; i<48; i++)
    {
        output[i] = input[table[i] - 1];
    }
};
static  void P(const int input[32], int output[32], int table[32])//P置换  
{
    int i;
    for (i = 0; i<32; i++)
    {
        output[i] = input[table[i] - 1];
    }
};
static  void IP_In(const int input[64], int output[64], int table[64])//逆IP  
{
    int i;
    for (i = 0; i<64; i++)
    {
        output[i] = input[table[i] - 1];
    }
};
static  void PC_1(const int input[64], int output[56], int table[56])//PC_1  
{
    int i;
    for (i = 0; i<56; i++)
    {
        output[i] = input[table[i] - 1];
    }
};
static  void PC_2(const int input[56], int output[48], int table[48])//PC_2  
{
    int i;
    for (i = 0; i<48; i++)
    {
        output[i] = input[table[i] - 1];
    }
};
static  void S(const int input[48], int output[32], int table[8][4][16])//S盒压缩  
{
    int i = 0;
    int j = 0;
    int INT[8];
    for (; i<48; i = i + 6)
    {
        INT[j] = table[j][(input[i] << 1) + (input[i + 5])][(input[i + 1] << 3) + (input[i + 2] << 2) + (input[i + 3] << 1) + (input[i + 4])];
        j++;
    }
    for (j = 0; j<8; j++)
    {
        for (i = 0; i<4; i++)
        {
            output[3 * (j + 1) - i + j] = (INT[j] >> i) & 1;
        }
    }
};
static void F_func(int input[32], int output[32], int subkey[48])//完成DES算法轮变换  
{
    int len = 48;
    int temp[48] = { 0 };
    int temp_1[32] = { 0 };
    E(input, temp, E_Table);
    Xor(temp, subkey, len);
    S(temp, temp_1, S_Box);
    P(temp_1, output, P_Table);
};
static void RotateL(const int input[28], int output[28], int leftCount)//秘钥循环左移  
{
    int i;
    int len = 28;
    for (i = 0; i<len; i++)
    {
        output[i] = input[(i + leftCount) % len];
    }
};
static void  subKey_fun(const int input[64], int Subkey[16][48])//子密钥生成  
{
    int loop = 1, loop_2 = 2;
    int i, j;
    int c[28], d[28];
    int pc_1[56] = { 0 };
    int pc_2[16][56] = { 0 };
    int rotatel_c[16][28] = { 0 };
    int rotatel_d[16][28] = { 0 };
    PC_1(input, pc_1, PC1_Table);
    for (i = 0; i<28; i++)
    {
        c[i] = pc_1[i];
        d[i] = pc_1[i + 28];
    }
    int leftCount = 0;
    for (i = 1; i<17; i++)
    {
        if (i == 1 || i == 2 || i == 9 || i == 16)
        {
            leftCount += loop;
            RotateL(c, rotatel_c[i - 1], leftCount);
            RotateL(d, rotatel_d[i - 1], leftCount);
        }
        else
        {
            leftCount += loop_2;
            RotateL(c, rotatel_c[i - 1], leftCount);
            RotateL(d, rotatel_d[i - 1], leftCount);
        }
    }
    for (i = 0; i<16; i++)
    {
        for (j = 0; j<28; j++)
        {
            pc_2[i][j] = rotatel_c[i][j];
            pc_2[i][j + 28] = rotatel_d[i][j];
        }
    }
    for (i = 0; i<16; i++)
    {
        PC_2(pc_2[i], Subkey[i], PC2_Table);
    }
};
static void  DES_Efun(char input[8], char key_in[8], int output[64])
{
    int Ip[64] = { 0 };//存储初始置换后的矩阵  
    int output_1[64] = { 0 };
    int subkeys[16][48];
    int chartobit[64] = { 0 };
    int key[64];
    int l[17][32], r[17][32];
    CharToBit(input, chartobit, 8);//正确,转换为64个二进制数的操作正确!  
    IP(chartobit, Ip, IP_Table);//正确,IP初始置换!  
    CharToBit(key_in, key, 8);//正确!  
    subKey_fun(key, subkeys);//正确!  
    for (int i = 0; i<32; i++)
    {
        l[0][i] = Ip[i];
        r[0][i] = Ip[32 + i];
    }
    for (int j = 1; j<16; j++)//前15轮的操作  
    {
        for (int k = 0; k<32; k++)
        {
            l[j][k] = r[j - 1][k];
        }
        F_func(r[j - 1], r[j], subkeys[j - 1]);
        Xor(r[j], l[j - 1], 32);
    }
    int t = 0;
    for (t = 0; t<32; t++)//最后一轮的操作  
    {
        r[16][t] = r[15][t];
    }
    F_func(r[15], l[16], subkeys[15]);
    Xor(l[16], l[15], 32);
    for (t = 0; t<32; t++)
    {
        output_1[t] = l[16][t];
        output_1[32 + t] = r[16][t];
    }
    IP_In(output_1, output, IPR_Table);
};
static void  DES_Dfun(int input[64], char key_in[8], char output[8])
{
    int Ip[64] = { 0 };//存储初始置换后的矩阵  
    int output_1[64] = { 0 };
    int output_2[64] = { 0 };
    int subkeys[16][48];
    int chartobit[64] = { 0 };
    int key[64];
    int l[17][32], r[17][32];
    IP(input, Ip, IP_Table);//正确,IP初始置换!  
    CharToBit(key_in, key, 8);//正确!  
    subKey_fun(key, subkeys);//正确!  
    for (int i = 0; i<32; i++)
    {
        l[0][i] = Ip[i];
        r[0][i] = Ip[32 + i];
    }
    for (int j = 1; j<16; j++)//前15轮的操作  
    {
        for (int k = 0; k<32; k++)
        {
            l[j][k] = r[j - 1][k];
        }
        F_func(r[j - 1], r[j], subkeys[16 - j]);
        Xor(r[j], l[j - 1], 32);
    }
    int t = 0;
    for (t = 0; t<32; t++)//最后一轮的操作  
    {
        r[16][t] = r[15][t];
    }
    F_func(r[15], l[16], subkeys[0]);
    Xor(l[16], l[15], 32);
    for (t = 0; t<32; t++)
    {
        output_1[t] = l[16][t];
        output_1[32 + t] = r[16][t];
    }
    IP_In(output_1, output_2, IPR_Table);
    BitToChar(output_2, output, 8);
};
int main()
{
    int output[64] = { 0 };
    char MIN[9] = { 0 };
    char MI[9] = { 0 };
    printf("请输入明文(8字节)\n");
    gets_s(MIN);
    printf("请输入秘钥(8字节)\n");
    gets_s(MI);
    DES_Efun(MIN, MI, output);
    printf("密文如下:\n");
    for (int i = 0; i<64; i++)
    {
        printf("%d", output[i]);
        if ((i + 1) % 4 == 0)
            printf("\n");
    }
    printf("\n");

        for(int i=0;i<8;i++) MIN[i]='0';//评论区见到有人不服,没看懂函数就说删掉解密部分输出明文没变,那就在解密前加上个赋值,你再试试?

    printf("解密功能\n");
    DES_Dfun(output, MI, MIN);
    printf("明文如下:\n");
    for (int i = 0; i<8; i++)
    {
        printf("%c", MIN[i]);
    }
    printf("\n\n");
    return 0;
}

总结

主要还是xor和一些位置置换,看到14, 4, 13, 1, 2, 15, 11, 8, 3, 10……这样sbox的一长串数字可以猜测是不是des

3DES

算法原理

3DES为DES向AES过渡的加密算法,它使用3条56位的密钥对数据进行三次加密。
采用了 加密->解密->加密 的方式。

实例

RC4

流加密:明文数据每次与密钥数据流顺次对应加密,得到密文数据流。
对称密钥算法:在加密和解密时使用相同的密钥,或是使用两个可以简单地相互推算的密钥。

算法原理

RC4(Rivest Cipher 4):是流加密算法,对称加密算法(加解密使用相同的密钥)
RC4由伪随机数生成器和异或运算组成。RC4的密钥长度可变,范围是[1,255]。RC4一个字节一个字节地加解密。

加密算法

/*初始化函数*/
void rc4_init(unsigned char*s,unsigned char*key, unsigned long Len)
{
    int i=0,j=0;
    //char k[256]={0};
    unsigned char k[256]={0};
    unsigned char tmp=0;
    for(i=0;i<256;i++) {
        s[i]=i;
        k[i]=key[i%Len];
    }
    for(i=0;i<256;i++) {
        j=(j+s[i]+k[i])%256;
        tmp=s[i];
        s[i]=s[j];//交换s[i]和s[j]
        s[j]=tmp;
    }
}

参数1是一个256长度的char型数组,定义为: unsigned char sBox[256];
参数2是密钥,其内容可以随便定义:char key[256];
参数3是密钥的长度,Len = strlen(key);
在初始化的过程中,密钥的主要功能是将S-box搅乱,i确保S-box的每个元素都得到处理,j保证S-box的搅乱是随机的。而不同的S-box在经过伪随机子密码生成算法的处理后可以得到不同的子密钥序列,将S-box和明文进行xor运算,得到密文,解密过程也完全相同。

/*加解密*/
void rc4_crypt(unsigned char*s,unsigned char*Data,unsigned long Len)
{
    int i=0,j=0,t=0;
    unsigned long k=0;
    unsigned char tmp;
    for(k=0;k<Len;k++)
    {
        i=(i+1)%256;
        j=(j+s[i])%256;
        tmp=s[i];
        s[i]=s[j];//交换s[x]和s[y]
        s[j]=tmp;
        t=(s[i]+s[j])%256;
        Data[k]^=s[t];
    }
}

参数1是上边rc4_init函数中,被搅乱的S-box;
参数2是需要加密的数据data;
参数3是data的长度

//程序开始
#include<stdio.h>
#include<string.h>
typedef unsigned longULONG;

/*初始化函数*/
void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
    int i = 0, j = 0;
    char k[256] = { 0 };
    unsigned char tmp = 0;
    for (i = 0; i<256; i++)
    {
        s[i] = i;
        k[i] = key[i%Len];
    }
    for (i = 0; i<256; i++)
    {
        j = (j + s[i] + k[i]) % 256;
        tmp = s[i];
        s[i] = s[j];//交换s[i]和s[j]
        s[j] = tmp;
    }
}

/*加解密*/
void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
{
    int i = 0, j = 0, t = 0;
    unsigned long k = 0;
    unsigned char tmp;
    for (k = 0; k<Len; k++)
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        tmp = s[i];
        s[i] = s[j];//交换s[x]和s[y]
        s[j] = tmp;
        t = (s[i] + s[j]) % 256;
        Data[k] ^= s[t];
    }
}

int main()
{
    unsigned char s[256] = { 0 }, s2[256] = { 0 };//S-box
    char key[256] = { "justfortest" };
    char pData[512] = "这是一个用来加密的数据Data";
    unsigned long len = strlen(pData);
    int i;

    printf("pData=%s\n", pData);
    printf("key=%s,length=%d\n\n", key, strlen(key));
    rc4_init(s, (unsigned char*)key, strlen(key));//已经完成了初始化
    printf("完成对S[i]的初始化,如下:\n\n");
    for (i = 0; i<256; i++)
    {
        printf("%02X", s[i]);
        if (i && (i + 1) % 16 == 0)putchar('\n');
    }
    printf("\n\n");
    for (i = 0; i<256; i++)//用s2[i]暂时保留经过初始化的s[i],很重要的!!!
    {
        s2[i] = s[i];
    }
    printf("已经初始化,现在加密:\n\n");
    rc4_crypt(s, (unsigned char*)pData, len);//加密
    printf("pData=%s\n\n", pData);
    printf("已经加密,现在解密:\n\n");
    //rc4_init(s,(unsignedchar*)key,strlen(key));//初始化密钥
    rc4_crypt(s2, (unsigned char*)pData, len);//解密
    printf("pData=%s\n\n", pData);
    return 0;
}
//程序完

加密解密都是通过crypt,而第一个参数是相同的

总结

存在 3 个循环,前两次循环的次数为 256 次,最后一次循环的次数以某个变量的值为限,实质是需要加密(解密)的内容长度,每次循环的最后有一个异或的操作代表加密该内容。

实例

超详细+ida实例+od实例

TEA

算法原理

TEA加密和解密时都使用一个常量值,这个常量值为0x9e3779b,这个值是近似黄金分割率,注意,有些编程人员为了避免在程序中直接出现"mov变量,0x9e3779b",以免被破解者直接搜索0x9e3779b这个常数得知使用TEA算法,所以有时会使用"sub变量,0x61C88647"代替"mov变量,0x9e3779b",0x61C88647=-(0x9e3779b)。
  TEA算法每一次可以操作64bit(8byte),采用128bit(16byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。

原始算法

void encrypt(uint32_t*v,uint32_t*k){
  uint32_t v0=v[0],v1=v[1],sum=0,i;/*setup*/
  uint32_t delta=0x9e3779b9;/*akeyscheduleconstant*/
  uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];/*cachekey*/
  for(i=0;i<32;i++){
    /*basiccyclestart*/
    sum+=delta;
    v0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
    v1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
    }/*endcycle*/
  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;/*setup*/
uint32_t delta=0x9e3779b9;/*akeyscheduleconstant*/
uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];/*cachekey*/
for(i=0;i<32;i++){
/*basiccyclestart*/
  v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
  v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
  sum-=delta;
}/*endcycle*/
v[0]=v0;
v[1]=v1;
}

具体:https://blog.csdn.net/makercloud/article/details/107454777

总结

看到0x61C88647或者0x9e3779b可以猜测是tea加密

实例

image-20210626195710687

XTEA

代码实现

#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;
}

总结

有一个key[(sum>>11)&3]的特征

XXTEA

#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)            /* n>0,加密部分*/
    {
        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)      /*n<0, 解密部分*/
    {
        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;
}

AES

原理

可爱易懂的原理解析,i了i了

aes知识

详细代码解释

总结

对称加密。
发现有S盒也就是一大堆字节,可以猜测为AES。

代码

//不含加密模式#include <iostream>#include <bitset>#include <string>using namespace std;typedef bitset<8> byte;typedef bitset<32> word;const int Nr = 10;  // AES-128需要 10 轮加密const int Nk = 4;   // Nk 表示输入密钥的 word 个数byte S_Box[16][16] = {    {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}};byte Inv_S_Box[16][16] = {    {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}};// 轮常数,密钥扩展中用到。(AES-128只需要10轮)word Rcon[10] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,                0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000 };/**********************************************************************//*                                                                    *//*                              AES算法实现                           *//*                                                                    *//**********************************************************************//******************************下面是加密的变换函数**********************//** *  S盒变换 - 前4位为行号,后4位为列号 */void SubBytes(byte mtx[4 * 4]){ for (int i = 0; i < 16; ++i) {       int row = mtx[i][7] * 8 + mtx[i][6] * 4 + mtx[i][5] * 2 + mtx[i][4];        int col = mtx[i][3] * 8 + mtx[i][2] * 4 + mtx[i][1] * 2 + mtx[i][0];        mtx[i] = S_Box[row][col];   }}/** *  行变换 - 按字节循环移位 */void ShiftRows(byte mtx[4 * 4]){   // 第二行循环左移一位    byte temp = mtx[4]; for (int i = 0; i < 3; ++i)      mtx[i + 4] = mtx[i + 5];    mtx[7] = temp;  // 第三行循环左移两位    for (int i = 0; i < 2; ++i)  {       temp = mtx[i + 8];      mtx[i + 8] = mtx[i + 10];       mtx[i + 10] = temp; }   // 第四行循环左移三位    temp = mtx[15]; for (int i = 3; i > 0; --i)      mtx[i + 12] = mtx[i + 11];  mtx[12] = temp;}/** *  有限域上的乘法 GF(2^8) */byte GFMul(byte a, byte b) {   byte p = 0; byte hi_bit_set;    for (int counter = 0; counter < 8; counter++) {      if ((b & byte(1)) != 0) {           p ^= a;     }       hi_bit_set = (byte)(a & byte(0x80));        a <<= 1;      if (hi_bit_set != 0) {          a ^= 0x1b; /* x^8 + x^4 + x^3 + x + 1 */        }       b >>= 1;  }   return p;}/** *  列变换 */void MixColumns(byte mtx[4 * 4]){    byte arr[4];    for (int i = 0; i < 4; ++i)  {       for (int j = 0; j < 4; ++j)          arr[j] = mtx[i + j * 4];        mtx[i] = GFMul(0x02, arr[0]) ^ GFMul(0x03, arr[1]) ^ arr[2] ^ arr[3];       mtx[i + 4] = arr[0] ^ GFMul(0x02, arr[1]) ^ GFMul(0x03, arr[2]) ^ arr[3];       mtx[i + 8] = arr[0] ^ arr[1] ^ GFMul(0x02, arr[2]) ^ GFMul(0x03, arr[3]);       mtx[i + 12] = GFMul(0x03, arr[0]) ^ arr[1] ^ arr[2] ^ GFMul(0x02, arr[3]);  }}/** *  轮密钥加变换 - 将每一列与扩展密钥进行异或 */void AddRoundKey(byte mtx[4 * 4], word k[4]){ for (int i = 0; i < 4; ++i)  {       word k1 = k[i] >> 24;     word k2 = (k[i] << 8) >> 24;        word k3 = (k[i] << 16) >> 24;       word k4 = (k[i] << 24) >> 24;       mtx[i] = mtx[i] ^ byte(k1.to_ulong());      mtx[i + 4] = mtx[i + 4] ^ byte(k2.to_ulong());      mtx[i + 8] = mtx[i + 8] ^ byte(k3.to_ulong());      mtx[i + 12] = mtx[i + 12] ^ byte(k4.to_ulong());    }}/**************************下面是解密的逆变换函数***********************//** *  逆S盒变换 */void InvSubBytes(byte mtx[4 * 4]){   for (int i = 0; i < 16; ++i) {       int row = mtx[i][7] * 8 + mtx[i][6] * 4 + mtx[i][5] * 2 + mtx[i][4];        int col = mtx[i][3] * 8 + mtx[i][2] * 4 + mtx[i][1] * 2 + mtx[i][0];        mtx[i] = Inv_S_Box[row][col];   }}/** *  逆行变换 - 以字节为单位循环右移 */void InvShiftRows(byte mtx[4 * 4]){    // 第二行循环右移一位    byte temp = mtx[7]; for (int i = 3; i > 0; --i)      mtx[i + 4] = mtx[i + 3];    mtx[4] = temp;  // 第三行循环右移两位    for (int i = 0; i < 2; ++i)  {       temp = mtx[i + 8];      mtx[i + 8] = mtx[i + 10];       mtx[i + 10] = temp; }   // 第四行循环右移三位    temp = mtx[12]; for (int i = 0; i < 3; ++i)      mtx[i + 12] = mtx[i + 13];  mtx[15] = temp;}void InvMixColumns(byte mtx[4 * 4]){    byte arr[4];    for (int i = 0; i < 4; ++i)  {       for (int j = 0; j < 4; ++j)          arr[j] = mtx[i + j * 4];        mtx[i] = GFMul(0x0e, arr[0]) ^ GFMul(0x0b, arr[1])          ^ GFMul(0x0d, arr[2]) ^ GFMul(0x09, arr[3]);        mtx[i + 4] = GFMul(0x09, arr[0]) ^ GFMul(0x0e, arr[1])          ^ GFMul(0x0b, arr[2]) ^ GFMul(0x0d, arr[3]);        mtx[i + 8] = GFMul(0x0d, arr[0]) ^ GFMul(0x09, arr[1])          ^ GFMul(0x0e, arr[2]) ^ GFMul(0x0b, arr[3]);        mtx[i + 12] = GFMul(0x0b, arr[0]) ^ GFMul(0x0d, arr[1])         ^ GFMul(0x09, arr[2]) ^ GFMul(0x0e, arr[3]);    }}/******************************下面是密钥扩展部分***********************//** * 将4个 byte 转换为一个 word. */word Word(byte& k1, byte& k2, byte& k3, byte& k4){   word result(0x00000000);    word temp;  temp = k1.to_ulong();  // K1    temp <<= 24;  result |= temp; temp = k2.to_ulong();  // K2    temp <<= 16;  result |= temp; temp = k3.to_ulong();  // K3    temp <<= 8;   result |= temp; temp = k4.to_ulong();  // K4    result |= temp; return result;}/** *  按字节 循环左移一位 *  即把[a0, a1, a2, a3]变成[a1, a2, a3, a0] */word RotWord(word rw){   word high = rw << 8;  word low = rw >> 24;  return high | low;}/** *  对输入word中的每一个字节进行S-盒变换 */word SubWord(word sw){    word temp;  for (int i = 0; i < 32; i += 8)  {       int row = sw[i + 7] * 8 + sw[i + 6] * 4 + sw[i + 5] * 2 + sw[i + 4];        int col = sw[i + 3] * 8 + sw[i + 2] * 4 + sw[i + 1] * 2 + sw[i];        byte val = S_Box[row][col];     for (int j = 0; j < 8; ++j)          temp[i + j] = val[j];   }   return temp;}/** *  密钥扩展函数 - 对128位密钥进行扩展得到 w[4*(Nr+1)] */void KeyExpansion(byte key[4 * Nk], word w[4 * (Nr + 1)]){ word temp;  int i = 0;  // w[]的前4个就是输入的key  while (i < Nk)   {       w[i] = Word(key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3]);        ++i;    }   i = Nk; while (i < 4 * (Nr + 1)) {       temp = w[i - 1]; // 记录前一个word       if (i % Nk == 0)            w[i] = w[i - Nk] ^ SubWord(RotWord(temp)) ^ Rcon[i / Nk - 1];       else            w[i] = w[i - Nk] ^ temp;        ++i;    }}/******************************下面是加密和解密函数**************************//** *  加密 */void encrypt(byte in[4 * 4], word w[4 * (Nr + 1)]){   word key[4];    for (int i = 0; i < 4; ++i)      key[i] = w[i];  AddRoundKey(in, key);   for (int round = 1; round < Nr; ++round) {       SubBytes(in);       ShiftRows(in);      MixColumns(in);     for (int i = 0; i < 4; ++i)          key[i] = w[4 * round + i];      AddRoundKey(in, key);   }   SubBytes(in);   ShiftRows(in);  for (int i = 0; i < 4; ++i)      key[i] = w[4 * Nr + i]; AddRoundKey(in, key);}/** *  解密 */void decrypt(byte in[4 * 4], word w[4 * (Nr + 1)]){   word key[4];    for (int i = 0; i < 4; ++i)      key[i] = w[4 * Nr + i]; AddRoundKey(in, key);   for (int round = Nr - 1; round > 0; --round) {       InvShiftRows(in);       InvSubBytes(in);        for (int i = 0; i < 4; ++i)          key[i] = w[4 * round + i];      AddRoundKey(in, key);       InvMixColumns(in);  }   InvShiftRows(in);   InvSubBytes(in);    for (int i = 0; i < 4; ++i)      key[i] = w[i];  AddRoundKey(in, key);}/**********************************************************************//*                                                                    *//*                              测试                                  *//*                                                                    *//**********************************************************************/int main(){ byte key[] = { 0x31,0x32, 0x33 ,0x34 ,0x35, 0x36, 0x37 ,0x38,0x31,0x32, 0x33 ,0x34 ,0x35, 0x36, 0x37 ,0x38 };   byte plain[16] = { 0x31,0x32, 0x33 ,0x34 ,0x35, 0x36, 0x37 ,0x38 ,0x31,0x32, 0x33 ,0x34 ,0x35, 0x36, 0x37 ,0x38 };  // 输出密钥 cout << "密钥是:"; for (int i = 0; i < 16; ++i)     cout << hex << key[i].to_ulong() << " ";    cout << endl; word w[4 * (Nr + 1)];   KeyExpansion(key, w);   // 输出待加密的明文 cout << endl << "待加密的明文:" << endl;  for (int i = 0; i < 16; ++i) {       cout << hex << plain[i].to_ulong() << " ";      if ((i + 1) % 4 == 0)           cout << endl; }   cout << endl; // 加密,输出密文  encrypt(plain, w);  cout << "加密后的密文:" << endl;    for (int i = 0; i < 16; ++i) {       cout << hex << plain[i].to_ulong() << " ";      if ((i + 1) % 4 == 0)           cout << endl; }   cout << endl; // 解密,输出明文  decrypt(plain, w);  cout << "解密后的明文:" << endl;    for (int i = 0; i < 16; ++i) {       cout << hex << plain[i].to_ulong() << " ";      if ((i + 1) % 4 == 0)           cout << endl; }   cout << endl; return 0;}

实例

C#——来自oj_crackme2

image-20210426191514913

RijndaelManaged

MD5

密码散列函数:极其难以由散列函数输出的结果,回推输入的数据。

原理

MD5是密码散列函数。
MD5码以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

#include<iostream>#include<string>using namespace std;#define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))//右移的时候,高位一定要补零,而不是补充符号位#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))    #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))#define H(x, y, z) ((x) ^ (y) ^ (z))#define I(x, y, z) ((y) ^ ((x) | (~z)))#define A 0x67452301#define B 0xefcdab89#define C 0x98badcfe#define D 0x10325476//strBaye的长度unsigned int strlength;//A,B,C,D的临时变量unsigned int atemp;unsigned int btemp;unsigned int ctemp;unsigned int dtemp;//常量ti unsigned int(abs(sin(i+1))*(2pow32))const unsigned int k[]={        0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,        0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,        0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,        0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,        0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,        0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,        0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,        0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,        0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,        0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,        0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,        0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,        0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391};//向左位移数const unsigned int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,        12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,        4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,        15,21,6,10,15,21,6,10,15,21,6,10,15,21};const char str16[]="0123456789abcdef";void mainLoop(unsigned int M[]){    unsigned int f,g;    unsigned int a=atemp;    unsigned int b=btemp;    unsigned int c=ctemp;    unsigned int d=dtemp;    for (unsigned int i = 0; i < 64; i++)    {        if(i<16){            f=F(b,c,d);            g=i;        }else if (i<32)        {            f=G(b,c,d);            g=(5*i+1)%16;        }else if(i<48){            f=H(b,c,d);            g=(3*i+5)%16;        }else{            f=I(b,c,d);            g=(7*i)%16;        }        unsigned int tmp=d;        d=c;        c=b;        b=b+shift((a+f+k[i]+M[g]),s[i]);        a=tmp;    }    atemp=a+atemp;    btemp=b+btemp;    ctemp=c+ctemp;    dtemp=d+dtemp;}/**填充函数*处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)*填充方式为先加一个1,其它位补零*最后加上64位的原来长度*/unsigned int* add(string str){    unsigned int num=((str.length()+8)/64)+1;//以512位,64个字节为一组    unsigned int *strByte=new unsigned int[num*16];    //64/4=16,所以有16个整数    strlength=num*16;    for (unsigned int i = 0; i < num*16; i++)        strByte[i]=0;    for (unsigned int i=0; i <str.length(); i++)    {        strByte[i>>2]|=(str[i])<<((i%4)*8);//一个整数存储四个字节,i>>2表示i/4 一个unsigned int对应4个字节,保存4个字符信息    }    strByte[str.length()>>2]|=0x80<<(((str.length()%4))*8);//尾部添加1 一个unsigned int保存4个字符信息,所以用128左移    /*    *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位    */    strByte[num*16-2]=str.length()*8;    return strByte;}string changeHex(int a){    int b;    string str1;    string str="";    for(int i=0;i<4;i++)    {        str1="";        b=((a>>i*8)%(1<<8))&0xff;   //逆序处理每个字节        for (int j = 0; j < 2; j++)        {            str1.insert(0,1,str16[b%16]);            b=b/16;        }        str+=str1;    }    return str;}string getMD5(string source){    atemp=A;    //初始化    btemp=B;    ctemp=C;    dtemp=D;    unsigned int *strByte=add(source);    for(unsigned int i=0;i<strlength/16;i++)    {        unsigned int num[16];        for(unsigned int j=0;j<16;j++)            num[j]=strByte[i*16+j];        mainLoop(num);    }    return changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp));}unsigned int main(){    string ss;//    cin>>ss;    string s=getMD5("abc");    cout<<s;    return 0;}

总结

看到0x67452301、0xefcdab89、0x98badcfe、0x10325476,可以猜测是MD5。

实例

一道pwn的md5加密

image-20210626195406162

image-20210626195251250

v3初始化为md5的特征值

下面的两个函数:

md5_1

image-20210626195427062

sub400BB4

image-20210626195457881

md_2

image-20210626195524285

sub400A38

image-20210626195559649

blowfish

原理

对称加密块算法。

用来加密64Bit长度的字符串。

使用两个“盒”——unsignedlongpbox[18]unsignedlongsbox[4,256]

BlowFish算法中,有一个核心加密函数:BF_En。该函数输入64位信息,运算后,以64位密文的形式输出。用BlowFish算法加密信息,需要两个过程:密钥预处理和信息加密。

密钥预处理:

BlowFish算法的源密钥——pbox和sbox是固定的。我们要加密一个信息,需要自己选择一个key,用这个key对pbox和sbox进行变换,得到下一步信息加密所要用的key_pbox和key_sbox。具体的变化算法如下:

1)用sbox填充key_sbox

2)用自己选择的key8个一组地去异或pbox,用异或的结果填充key_pbox。key可以循环使用。

比如说:选的key是"abcdefghijklmn"。则异或过程为:

key_pbox[0]=pbox[0]abcdefgh;

key_pbox[1]=pbox[1]ijklmnab;

…………

…………

如此循环,直到key_pbox填充完毕。

3)用BF_En加密一个全0的64位信息,用输出的结果替换key_pbox[0]和key_pbox[1],i=0;

4)用BF_En加密替换后的key_pbox,key_pbox[i+1],用输出替代key_pbox[i+2]和key_pbox[i+3];

5)i+2,继续第4步,直到key_pbox全部被替换;

6)用key_pbox[16]和key_pbox[17]做首次输入(相当于上面的全0的输入),用类似的方法,替换key_sbox信息加密。

信息加密就是用函数把待加密信息x分成32位的两部分:xL,xRBF_En对输入信息进行变换。

解密

用BlowFish算法解密,同样也需要两个过程。

1.密钥预处理

2.信息解密

密钥预处理的过程与加密时完全相同,信息解密的过程就是把信息加密过程的key_pbox逆序使用即可。可以看出,选择不同的key,用BlowFish算法加密同样的信息,可以得出不同的结果。要破解BlowFish算法,就是要得到BlowFish算法的key。所以,使用BlowFish算法进行加密,最重要的也就是key的选择以及key的保密。其中key的选择可以使用bf_sdk中的_WeakKey函数进行检验。以下是该函数的说明:

_WeakKey

功能:测试产生的box是否安全

参数:无

返回:AX=1不安全;AX=0安全

影响:AX,BX,CX,DX,SI,DI,方向标志

描述:使用"_InitCrypt"函数产生用于加密的Boxes后,你应该用这个函数测试产生的Boxes是否安全,如果该key产生的Boxes不安全——可以被密码分析者通过分析Boxes得到key,那么,你应该采用另外一个key产生一个安全的Boxes用来加密。

代码

//blowfish.hunsigned long p_box[18] = { 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, 0x9216D5D9L, 0x8979FB1BL};unsigned long s_box[4][256] = {   { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,   0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL },   { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,   0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L },   { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,   0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L },   { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,   0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L }};//blowfish.cpp#include <Windows.h>#include <stdio.h>#include "blowfish.h"#define unsigned char byteULONG SearchTable(ULONG leftPart){   ULONG value;    //查表操作 每一个字节查一次表 然后进行加和异或操作 value = s_box[0][leftPart >> 24] + s_box[1][(leftPart >> 16) & 0xff];   value ^= s_box[2][(leftPart >> 8) & 0xff];    value += s_box[3][leftPart & 0xff]; return value;}//BlowFish的主加密函数 它对明文的加密和对密钥的变换都是利用这个 迭代变换16轮inline void BF_Fn(ULONG& leftPart, ULONG& rightPart){    int i;  for (i = 0; i < 16; i += 2) {        leftPart ^= p_box[i];       rightPart ^= SearchTable(leftPart);     rightPart ^= p_box[i + 1];      leftPart ^= SearchTable(rightPart); }   leftPart ^= p_box[16];  rightPart ^= p_box[17]; //最后交换一下    ULONG temp = leftPart;  leftPart = rightPart;   rightPart = temp;}//对pBox和sBox进行变换void ExchangeBox(byte* key){  int i, j;   int keyLen = strlen((const char*)key);//获取key长度 ULONG* keyLong = NULL;  ULONG leftPart = 0, rightPart = 0;//得到共计64bit的左右两部分 keyLong = (ULONG*)malloc(keyLen * sizeof(byte));//获取应得的空间   ZeroMemory(keyLong, keyLen * sizeof(byte)); keyLen = keyLen / sizeof(ULONG);    printf("KeyLen : %d\n", keyLen);  printf("Key : "); for (i = 0; i < keyLen; i++) {       keyLong[i] = _byteswap_ulong(*((ULONG*)key + i));       printf("0x%x\t", keyLong[i]); }   printf("\n"); for (i = 0; i < 18; i++) {//进行异或     p_box[i] ^= keyLong[i % keyLen];    }   leftPart = rightPart = 0;//产生一个64位全0数据  for (i = 0; i < 18; i += 2) {//变换pBox        BF_Fn(leftPart, rightPart);     p_box[i] = leftPart;        p_box[i + 1] = rightPart;   }   for (i = 0; i < 4; i++) {//变换sBox        for (j = 0; j < 256; j += 2) {//256 / 2 == 128           BF_Fn(leftPart, rightPart);         s_box[i][j] = leftPart;         s_box[i][j + 1] = rightPart;        }   }}//p_box s_boxvoid BlowFish(byte* key, byte* data){    int i;  int dataLen = strlen((const char*)data) / (sizeof(ULONG) * 2);//获取data长度    byte* dataCopy = data;//建立一个data副本 方便进行指针偏移 ULONG leftPart, rightPart;  ExchangeBox(key);   //至此就可以加密明文了 一次加密2 * 4字节大小  for (i = 0; i < dataLen; i++) {      leftPart = _byteswap_ulong(*((ULONG*)dataCopy));        rightPart = _byteswap_ulong(*((ULONG*)dataCopy + 1));       BF_Fn(leftPart, rightPart);     *((ULONG*)dataCopy) = _byteswap_ulong(leftPart);        *((ULONG*)dataCopy + 1) = _byteswap_ulong(rightPart);       dataCopy += sizeof(ULONG) * 2;//指向下一个数据块    }   for (i = 0; i < strlen((const char*)data); i++) {        printf("%x ", data[i]);   }}int main(){   byte data[] = "1234567812345678"; byte key[] = "12345678";  BlowFish(key, data);    return 0;}

实例

image-20210507195333759

image-20210507195344850

看sbox和pbox的数值,一般有6A267E96……

salsa20