ctf常见编码与加密:https://blog.csdn.net/ruoli_s/article/details/109767829
在线解密网站:
xssee:http://web2hack.org/xssee
xssee:http://evilcos.me/lab/xssee
程默的博客(DES,3DES,AES,RC,Blowfish,Twofish,Serpent,Gost,Rijndael,Cast,Xtea,RSA):http://tool.chacuo.net/cryptdes
在线编码解码(多种并排):http://bianma.911cha.com
在线加密解密(多种):http://encode.chahuo.com
Unicode转中文:http://www.bejson.com/convert/unicode_chinese
栅栏密码 && 凯撒密码 && 摩斯电码:http://heartsnote.com/tools/cipher.htm
Caesar cipher(凯撒密码):http://planetcalc.com/1434/
Quoted-Printable && ROT13:http://www.mxcz.net/tools/QuotedPrintable.aspx
ROT5/13/18/47编码转换:http://www.qqxiuzi.cn/bianma/ROT5-13-18-47.php
Base32/16:http://pbaseconverter.com/
Base32:https://tools.deamwork.com/crypt/decrypt/base32decode.html
quipqiup古典密码自动化爆破(词频分析):http://quipqiup.com/index.php
词频分析/替换:http://cryptoclub.org/tools/cracksub_topframe.php
'+.<>[]' && '!.?'(Brainfuck/Ook!):https://www.splitbrain.org/services/ook
'+-.<>[]'(Brainfuck):https://www.nayuki.io/page/brainfuck-interpreter-javascript
'+-.<>[]'(Brainfuck):http://esoteric.sange.fi/brainfuck/impl/interp/i.html
'()[]!+'JavaScript编码(JSfuck):http://discogscounter.getfreehosting.co.uk/js-noalnum.php
用 6 个字符'()[]!+'来编写 JavaScript 程序(JSfuck同上):http://www.jsfuck.com/
http://patriciopalladino.com/files/hieroglyphy/
摩斯密码翻译器:http://www.jb51.net/tools/morse.htm
Morse Code摩尔斯电码:http://rumkin.com/tools/cipher/morse.php
摩尔斯电码转换器:http://www.zhongguosou.com/zonghe/moErSiCodeConverter.aspx
字符串编码,解码,转换(长度,反转,进制转换):http://www.5ixuexiwang.com/str/
Cisco Type 7 Reverser:http://packetlife.net/toolbox/type7
Cisco:http://www.ifm.net.nz/cookbooks/passwordcracker.html
cmd5 && NTLM && mysql…:http://www.cmd5.com
spammimic(字符2一段话):http://www.spammimic.com/
js代码在线加密解密:https://tool.lu/js/
JScript/VBscript脚本解密(#@~^….^#~@):http://www.dheart.net/decode/index.php
VBScript.Encode解密(tip:Asp encode):http://adophper.com/encode.html
JScript.Encode脚本加密与解密:http://www.haokuwang.com/jsendecode.htm
'+/v+'UTF-7加密:http://web2hack.org/xssee
各种无知密码解密:http://www.tools88.com
uuencode解码 && xxencode解码(古老的邮件密码):http://web.chacuo.net/charsetuuencode
MIME标准(邮件编码的一种):http://dogmamix.com/MimeHeadersDecoder/
Binhex编码(邮件编码的一种,常见于MAC机):http://encoders-decoders.online-domain-tools.com/
%u8001%u9525非/u的hex,%u编码,只能编码汉字(xssee):http://web.chacuo.net/charsetescape
猪圈密码:http://www.simonsingh.net/The_Black_Chamber/pigpen.html
ppencode(把Perl代码转换成只有英文字母的字符串):http://namazu.org/~takesako/ppencode/demo.html
rrencode(把ruby代码全部转换成符号):挂了
aaencode(JS代码转换成常用的网络表情,也就是我们说的颜文字js加密):http://utf-8.jp/public/aaencode.html
'()[]!+' && '$=~[]+"_.\();'jother编码jjencode(JS代码转换成只有符号的字符串):http://web2hack.org/xssee
jother(是一种运用于javascript语言中利用少量字符构造精简的匿名函数方法对于字符串进行的编码方式。其中8个少量字符包括:! + ( ) [ ] { }。只用这些字符就能完成对任意字符串的编码):http://tmxk.org/jother/
jjencode/aaencode可用xssee && Chrome的Console模式来直接输出解密。
Manchester曼彻斯特解密:http://eleif.net/manchester.html
Vigenère维多利亚解密:https://www.guballa.de/vigenere-solver
Vigenère cipher:http://planetcalc.com/2468/
Hill cipher(希尔密码):http://planetcalc.com/3327/
Atbash cipher(埃特巴什码):http://planetcalc.com/4647/
snow(html隐写):http://fog.misty.com/perry/ccs/snow/snow/snow.html
Serpent加密解密:http://serpent.online-domain-tools.com/
十六进制Hex转文本字符串:http://www.bejson.com/convert/ox2str/
Hex2text:http://www.convertstring.com/EncodeDecode/HexDecode
Binary(二进制),ACSII,Hex(十六进制),Decimal(十进制):http://www.binaryhexconverter.com/
集合:http://www.qqxiuzi.cn/daohang.htm
集合(各种古典密码):http://rumkin.com/tools/cipher/
文本加密为汉字("盲文",音符,各种语言,花朵,箭头…):http://www.qqxiuzi.cn/bianma/wenbenjiami.php
在线繁体字转换器:http://www.aies.cn
在线工具集合:http://tomeko.net/online_tools/
二维码/条形码:https://online-barcode-reader.inliteresearch.com/
生成二维码:http://www.wwei.cn/
在线二维码解密:http://jiema.wwei.cn/
Image2Base64:http://www.vgot.net/test/image2base64.php
与佛论禅:http://www.keyfc.net/bbs/tools/tudoucode.aspx
在线分解GIF帧图:http://zh.bloggif.com/gif-extract
bejson(杂乱):http://www.bejson.com
atool(杂乱):http://www.atool.org
Punch Card:http://www.kloth.net/services/cardpunch.php
分解素数(ESA):http://www.factordb.com/index.php
文件在线Hash:http://www.atool.org/file_hash.php
base系列
base16
参考文章,某大佬博客:https://blog.csdn.net/securitit/article/details/106934357
简介:
Base16编码使用16个ASCII字符对任何数据进行编码,Base16与Base64的实现原理类似,同样是将原数据二进制形式取指定位数转换为ASCII码。首先获取数据的二进制形式,将其串联起来,每4个比特为一组进行切分,每一组内的4个比特可转换到指定的16个ASCII字符中的一个,将转换后的ASCII字符连接起来,就是编码后的数据。
编码表
base16编码
#include<stdio.h>
#include<string.h>
int main(void)
{
char date[100]="bacde";
char code[100];
unsigned char table[17]="0123456789ABCDEF";
int len_date,len_code,i,j,num;
len_date=strlen(date);
printf("明文长度为len_date=%d\n",len_date);
printf("明文为:%s\n",date);
len_code=len_date*2;
for(i=0,j=0;i<len_date;i++,j+=2)
{
code[j]=table[date[i]>>4];
code[j+1]=table[date[i]&15];
}
printf("密文长度len_code=%d\n",len_code);
printf("密文为:");
for(i=0;i<len_code;i++)
{
printf("%c",code[i]);
}
}
base16解码
#include<stdio.h>
#include<string.h>
int main(void)
{
char code[100]="6261636465";
char date[100];
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,0,1,2,3,4,5,6,
7,8,9,0,0,0,0,0,0,0,10,
11,12,13,14,15
};
// printf("%d",table['A']);
int len_date,len_code,i,j,num;
len_code=strlen(code);
printf("密文长度为len_code=%d\n",len_code);
printf("密文为:%s\n",code);
len_date=len_code/2;
for(i=0,j=0;i<len_code;i+=2,j++)
{
date[j]=table[code[i]]<<4|table[code[i+1]];
}
printf("明文长度为len_date=%d\n",len_date);
printf("明文为:");
for(i=0;i<len_date;i++)
{
printf("%c",date[i]);
}
}
base32
参考文章,某大佬博客:https://blog.csdn.net/securitit/article/details/106934385
简介:
Base32编码使用32个ASCII字符对任何数据进行编码,Base32与Base64的实现原理类似,同样是将原数据二进制形式取指定位数转换为ASCII码。首先获取数据的二进制形式,将其串联起来,每5个比特为一组进行切分,每一组内的5个比特可转换到指定的32个ASCII字符中的一个,将转换后的ASCII字符连接起来,就是编码后的数据。
编码表
表1(常用)
表2
base32编码
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[])
{
char date[100]="bacde";
char code[100];
unsigned char table[33]="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
int len_date,len_code,i,j,num;
len_date=strlen(date);
printf("明文长度为len_date=%d\n",len_date);
printf("明文为:%s\n",date);
if(len_date%5!=0)
{
len_code=(len_date/5+1)*8;
}
else
{
len_code=(len_date/5)*8;
}
for(i=0,j=0;i<len_code;i+=5,j+=8)
{
code[j]=table[date[i]>>3];
code[j+1]=table[((date[i]&7)<<2)|(date[i+1]>>6)];
code[j+2]=table[(date[i+1]>>1)&31];
code[j+3]=table[(date[i+1]&1)<<4|date[i+2]>>4];
code[j+4]=table[(date[i+2]&15)<<1|date[i+3]>>7];
code[j+5]=table[(date[i+3]>>2)&31];
code[j+6]=table[(date[i+3]&3)<<3|date[i+4]>>5];
code[j+7]=table[date[i+4]&31];
}
num=len_date%5;
switch(num)
{
case 1:
for(i=1;i<8-num;i++)
{
code[len_code-i]='=';
}
break;
case 2:
for(i=1;i<7-num;i++)
{
code[len_code-i]='=';
}
break;
case 3:
for(i=1;i<7-num;i++)
{
code[len_code-i]='=';
}
break;
case 4:
code[len_code-1]='=';
break;
}
printf("密文长度len_code=%d\n",len_code);
printf("密文为:");
for(i=0;i<len_code;i++)
{
printf("%c",code[i]);
}
}
base32解码
#include<stdio.h>
#include<string.h>
int main(void)
{
char code[100]="MJQXG3LTMZZWCZQ=";
char date[100];
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,0,0,0,0,
0,0,0,26,27,28,29,30,
31,0,0,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
};
int len_date,len_code,i,j,num;
len_code=strlen(code);
printf("密文长度为len_code=%d\n",len_code);
printf("密文为:%s\n",code);
if(strstr(code,"======"))
{
len_date=(len_code/8)*5-4;
}
else if(strstr(code,"===="))
{
len_date=(len_code/8)*5-3;
}
else if(strstr(code,"==="))
{
len_date=(len_code/8)*5-2;
}
else if(strstr(code,"="))
{
len_date=(len_code/8)*5-1;
}
else
{
len_date=(len_code/8)*5;
}
for(i=0,j=0;j<len_date;i+=8,j+=5)
{
date[j]=table[code[i]]<<3|table[code[i+1]]>>2;
date[j+1]=table[code[i+1]]<<6|table[code[i+2]]<<1|table[code[i+3]]>>4;
date[j+2]=table[code[i+3]]<<4|table[code[i+4]]>>1;
date[j+3]=table[code[i+4]]<<7|table[code[i+5]]<<2|table[code[i+6]]>>3;
date[j+4]=table[code[i+6]]<<5|table[code[i+7]];
}
printf("明文长度为len_date=%d\n",len_date);
printf("明文为:");
for(i=0;i<len_date;i++)
{
printf("%c",date[i]);
}
}
base64
参考文章:https://blog.csdn.net/qq_26093511/article/details/78836087
简介:
Bse64是一种以64个可打印字符对二进制数据进行编码的编码算法。base64在对数据进行编码时以三个8位字符型数据为一组,取这三个字符型数据的ASCII码,然后以6位为一组组成4个新的数据,这4个新的数据有6位,所以它的最大值为2^6=64。我们以4个6位数据的十进制数从base64表中得到最终编码后的字符。
编码表
表1
表2
base64编码
编码过程图片详解
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
char *str1="Happy birthday!";
unsigned char *str2;
int len1;
int len2;
int i,j;
unsigned char *table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwzyz0123456789+/";
len1=strlen(str1);
if(len1%3!=0)
{
len2=(len1/3+1)*4;
}
else
{
len2=(len1/3)*4;
}
str2=malloc(sizeof(unsigned char)*len2+1);
str2[len2]='\0';
for(i=0,j=0;i<len1;i+=3,j+=4)
{
str2[j]=table[str1[i]>>2];
str2[j+1]=table[(((str1[i]&3)<<4)|(str1[i+1]>>4))];
str2[j+2]=table[((str1[i+1]&15)<<2)|(str1[i+2]>>6)];
str2[j+3]=table[str1[i+2]&63];
}
// printf("%d",len2);
switch(len1%3)
{
case 1:
str2[len2-2]='=';
str2[len2-1]='=';
break;
case 2:
str2[len2-1]='=';
break;
}
for(i=0;i<len2;i++)
{
printf("%c",str2[i]);
}
return 0;
}
编码在IDA中的伪代码
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
_BYTE *v4; // [rsp+20h] [rbp-30h]
int v5; // [rsp+2Ch] [rbp-24h]
int v6; // [rsp+44h] [rbp-Ch]
int v7; // [rsp+48h] [rbp-8h]
int i; // [rsp+48h] [rbp-8h]
int v9; // [rsp+4Ch] [rbp-4h]
_main(*(_QWORD *)&argc, argv, envp);
v5 = strlen("Happy birthday! yangtianci!");
if ( v5 % 3 )
v9 = 4 * (v5 / 3 + 1);
else
v9 = 4 * (v5 / 3);
v4 = malloc(v9 + 1i64);
v4[v9] = 0;
v7 = 0;
v6 = 0;
while ( v7 < v5 )
{
v4[v6] = aAbcdefghijklmn[(char)(aHappyBirthdayY[v7] >> 2)];
v4[v6 + 1] = aAbcdefghijklmn[16 * (aHappyBirthdayY[v7] & 3) | (char)(aHappyBirthdayY[v7 + 1] >> 4)];
v4[v6 + 2] = aAbcdefghijklmn[4 * (aHappyBirthdayY[v7 + 1] & 0xF) | (char)(aHappyBirthdayY[v7 + 2] >> 6)];
v4[v6 + 3] = aAbcdefghijklmn[aHappyBirthdayY[v7 + 2] & 0x3F];
v7 += 3;
v6 += 4;
} //aAbcdefghijklmn...是编码的索引表,4*代表<<2,16*代表<<4。
if ( v5 % 3 == 1 )
{
v4[v9 - 2] = 61;
v4[v9 - 1] = 61;
}
else if ( v5 % 3 == 2 )
{
v4[v9 - 1] = 61;
}//根据数组长度来决定=的个数,61代表=。
for ( i = 0; i < v9; ++i )
putchar((unsigned __int8)v4[i]);
return 0;
}
base64解码
解码所用到的索引表
int main(void)
{
int i;
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
};
char str[]={'A','B','C','D','E','F','G','H',
'I','J','K','L','M','N','O','P','Q','R','S',
'T','U','V','W','X','Y','Z','a','b','c','d','e'
,'f','g','h','i','j','k','l','m','n','o','p','q',
'r','s','t','u','v','w','x','y','z','0','1','2','3','4',
'5','6','7','8','9','+','/'};
for(i=0;i<64;i++)
{
printf("%d ",table[str[i]]);
}
}
解码图片详解
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
char *str1="SGFwcHkgYmlydGh";
unsigned char *str2;
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
};
int len1;
int len2;
int i,j;
len1=strlen(str1);
if(strstr(str1,"=="))
{
len2=(len1/4)*3-2;
}
else if(strstr(str1,"="))
{
len2=(len1/4)*3-1;
}
else
{
len2=(len1/4)*3;
}
str2=malloc(sizeof(unsigned char)*len2+1);
str2[len2]='\0';
for(i=0,j=0;i<len1-2;i+=4,j+=3)
{
str2[j]=((table[str1[i]])<<2)|((table[str1[i+1]])>>4);
str2[j+1]=(table[str1[i+1]]<<4)|((table[str1[i+2]])>>2);
str2[j+2]=((table[str1[i+2]])<<6)|(table[str1[i+3]]);
}
// printf("%d",len2);
for(i=0;i<len2;i++)
{
printf("%c",str2[i]);
}
return 0;
}
解码在IDA中的伪代码
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4[126]; // [rsp+20h] [rbp-60h] //v4是那个索引表
_BYTE *v5; // [rsp+218h] [rbp+198h]
int v6; // [rsp+224h] [rbp+1A4h]
char *Str; // [rsp+228h] [rbp+1A8h]
int v8; // [rsp+234h] [rbp+1B4h]
int i; // [rsp+238h] [rbp+1B8h]
int v10; // [rsp+23Ch] [rbp+1BCh]
_main(*(_QWORD *)&argc, argv, envp);
Str = "SGFwcHkgYmlydGhkYXkhIHlhbmd0aWFuY2kh";
qmemcpy(v4, &unk_403040, 0x1ECui64); //memcpy指的是C和C++使用的内存拷贝函数,函数原型为void *memcpy(void *destin, void *source, unsigned n);函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,即从源source中拷贝n个字节到目标destin中。
v6 = strlen("SGFwcHkgYmlydGhkYXkhIHlhbmd0aWFuY2kh");
if ( strstr(Str, "==") )
{
v10 = 3 * (v6 / 4) - 2;
}
else if ( strchr(Str, 61) )
{
v10 = 3 * (v6 / 4) - 1;
}
else
{
v10 = 3 * (v6 / 4);
}
v5 = malloc(v10 + 1i64);
v5[v10] = 0;
i = 0;
v8 = 0;
while ( v6 - 2 > i )
{
v5[v8] = 4 * v4[Str[i]] | (v4[Str[i + 1]] >> 4); //4*代表<<2
v5[v8 + 1] = 16 * v4[Str[i + 1]] | (v4[Str[i + 2]] >> 2); //16*代表<<4
v5[v8 + 2] = (LOBYTE(v4[Str[i + 2]]) << 6) | LOBYTE(v4[Str[i + 3]]);
i += 4;
v8 += 3;
}
for ( i = 0; i < v10; ++i )
putchar((unsigned __int8)v5[i]);
putchar(10);
for ( i = 0; i < v10; ++i )
{
v5[i] = 16 * (i ^ v5[i]) | ((i ^ (unsigned __int8)v5[i]) >> 4);//输出数组的for循环改变了,可以随便带一个值去算算。
printf("%d ", (unsigned __int8)v5[i]);
}
return 0;
}
base58
参考博客:https://www.pianshen.com/article/9105343279/,https://www.jianshu.com/p/d8af38e091be
前言:个人感觉base58才体现了basexx编码的灵魂,因为其包含了进制转换思想,而base64,base32,base16都可以使用其他算法来实现,而base58就必须用进制转换来实现,但是由于小生不才,没能看懂大佬那个算法,所以现在只对大佬博客里面的算法进行部分讲解。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
char date[] = "AB";
int i,index = 0;
long long sum = 0;
int len_date=strlen(date);
int len_code=strlen(date) *138/100;// len * log(2)256 / log(2)(58)
int len=len_code + 1;//加1是因为用动态数组时结尾那个'\0'
char base58Table[59] = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
char *code = (char *)malloc(len * sizeof(char));
memset(code,0,len * sizeof(char));
len_date=strlen(date);
printf("明文长度为len_date=%d\n",len_date);
printf("明文为:%s\n",date);
//方法一,基本上不可用,明文长一点就没办法了。
// for(i = 0; i < strlen(plainText); i++) {//可以首先获取累加和 但是这样做的风险就是 随着幂的增加 和会急速暴增
// sum += plainText[i] * pow(256,strlen(plainText)-i-1);
// }
//
// cout << sum << endl;
// for(i = len - 1; i >= 0; i--) {
// encryption[i] = base58Table[sum % 58];
// sum /= 58;
// if(0 == sum )
// break;
// }
//方法二 每次都模 这样就不会存在和超出最大范围
while(index < len_date ) //这个while循环实现的是数制转换
{
int each = date[index];
for(i = len_code;1;i--)
{
each = each + code[i] * 256;
code[i] = each % 58;
each /= 58;
if(each==0)
break;
}
i = 0;//输出
while(!code[i])
i++;
printf("第%d轮code[]数组的值",index+1);
for(;i <= len_code; i++)
{
printf("%-3d ",code[i]);
}
printf("\n") ;
index++;
}
i = 0;
while(!code[i])
i++;
printf("密文长度len_code=%d\n",len_code);
printf("密文为:");
for(;i <= len_code; i++)
{
printf("%c",base58Table[code[i]]);
}
return 0;
}
1.len_code:对于加密后的长度问题,实际上关于base系列都是一个道理,就是进制的转换,都是字符串转为大整数,然后转为xx进制。这里放一张图。
2.进制转换部分,就只以AB为例,感觉有一点需要知道
(65*256+66)%58=2 等价于 ((58+7)*256+66)%58=2 等价于 (7*256+66)%58=2
由于没看懂,就只写一些数据。
总而言之,base58是basexx编码的灵魂,如果知道这个理论可以写出任意其他进制的编码。
对称加密
一些是贴的别人的。
rc4
https://baike.baidu.com/item/RC4/3454548?fr=aladdin注意可能也会有魔改的。
//程序开始
#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;//做一道re的题时这里就改为了,s[i]=256-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;
}
//程序完
tea,xtea,xxtea
相关题可以去看nepctf和hgame的week1
tea
一次加密可以加密两个数据,需要4个key,然后常见标志是date=0x9e3779b9。
#include<stdio.h>
void encrypt(unsigned int *flag , unsigned int *key)
{
unsigned int v0,v1,sum=0,i;
unsigned int delta=0x9e3779b9;
v0=flag[0];
v1=flag[1];
for(i=0;i<32;i++)
{
sum+=delta;
v0+=( (v1<<4)+key[0] ) ^ ( v1+sum ) ^((v1>>5)+key[1]);
v1+=( (v0<<4)+key[2] ) ^ ( v0+sum ) ^((v0>>5)+key[3]);
}
flag[0]=v0;
flag[1]=v1;
}
void decrypt(unsigned int *code , unsigned int *key)
{
unsigned int delta=0x9e3779b9;
unsigned int v0,v1,sum=0xC6EF3720,i;// sum=0xC6EF3720
v0=code[0];
v1=code[1];
for(i=0;i<32;i++)
{
v1-=( (v0<<4)+key[2] ) ^ (v0+sum) ^ ( (v0>>5)+key[3] );
v0-=( (v1<<4)+key[0] ) ^ (v1+sum) ^ ( (v1>>5)+key[1] );
sum-=delta;
}
code[0]=v0;
code[1]=v1;
}
int main()
{
unsigned int flag[2]={1,2},key[4]={1,2,3,4};
unsigned int code[2]={0xf99e87a6,0xa5b88bf3};
encrypt(flag,key);
printf("%x %x\n",flag[0],flag[1]);
decrypt(code,key);
printf("%x %x",code[0],code[1]);
}
xtea
算法特征,在tea算法的基础上多了一些异或运算和&运算,sum的值的变化也变成了在中间位置,然后取哪一个key也是由sum的值来决定的,循环加密的次数也可以由自己来确定了。
void encrypt(unsigned int r ,unsigned int *flag ,unsigned int *key)
{
unsigned int v0,v1,sum=0,i;
unsigned int delta=0x9e3779b9;
v0=flag[0];
v1=flag[1];
for(i=0;i<r;i++)
{
v0+=( ((v1<<4) ^ (v1>>5)) +v1 ) ^ ( sum + key[sum&3] );
sum+=delta;
v1+=( ((v0<<4) ^(v0>>5)) +v0 ) ^ ( sum + key[ (sum>>11)&3 ]);
}
flag[0]=v0;
flag[1]=v1;
}
void decrypt(unsigned int r ,unsigned int *code ,unsigned int *key)
{
unsigned int v0,v1,i,delta=0x9e3779b9;
unsigned int sum=delta*r;
v0=code[0];
v1=code[1];
for(i=0;i<r;i++)
{
v1-=( ((v0<<4) ^(v0>>5)) +v0 ) ^ ( sum + key[ (sum>>11)&3 ]);
sum-=delta;
v0-=( ((v1<<4) ^ (v1>>5)) +v1 ) ^ ( sum + key[sum&3] );
}
code[0]=v0;
code[1]=v1;
}
#include<stdio.h>
int main()
{
unsigned int flag[2]={1,2} ,key[4]={1,2,3,4};
unsigned int r=32;
unsigned int code[2]={0xf4420bdd,0xd58bca18};
encrypt(r,flag,key);
printf("%x %x\n",flag[0],flag[1]);
decrypt(r,code,key);
printf("%x %x",code[0],code[1]);
}
xxtea
可以自己定义加密数据的个数,然后添加了更多的异或和位移操作,也添加了循环加密的轮次,每一轮加密的过程中的每一个加密数据都与它的上一个和下一个数据有关,特别的是第一个数据,和最后一个数据。
第一个数据的加密与第二个和最后一个数据有关系,最后一个数据的加密和第一个和倒数第二个数据有关。
#include<stdio.h>
void encrypt(unsigned int *flag ,unsigned int *key ,unsigned int n)
{
unsigned int next,end,sum;
unsigned int rounds,e,delta=0x9e3779b9;
int i;
rounds=6+52/n;//轮回的次数
sum=0;
end=flag[n-1];//先设置end的值为最后一个,因为加密第一个要用
do
{
sum+=delta;
e=(sum>>2)&3;//与key的值关;
for(i=0;i<n-1;i++)//加密第一个到倒数第二个
{
next=flag[i+1];
flag[i]+=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) + (key[(i&3)^e]^end) ));
end=flag[i];//现在用end来保存当前数据的值,为下一个数据的加密做准备。
}
next=flag[0];//将第一个数据给next,为加密最后一个数据做准备,这时候end的值为倒数第二个数据。
flag[n-1]+=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) + (key[(i&3)^e]^end) ));
end=flag[n-1];//继续设置end的值为最后一个数据,为新一轮加密做准备。
}while(--rounds);
}
void decrypt(unsigned int *code ,unsigned int *key ,unsigned int n)
{
unsigned int next,end,sum;
unsigned int rounds,e,delta=0x9e3779b9;
int i;
rounds=6+52/n;
sum=rounds*delta;
next=code[0];//设置next为code的第一个
do
{
e=(sum>>2)&3;
for(i=n-1;i>0;i--)//解密最后一个到第二个
{
end=code[i-1];
code[i]-=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) + (key[(i&3)^e]^end) ));
next=code[i];
}
end=code[n-1];
code[0]-=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) +(key[i&3^e]^end) ));
next=code[0];
sum-=delta;
}while(--rounds);
}
int main()
{
unsigned int flag[2]={1,2},key[4]={1,2,3,4};
unsigned int n=2;
unsigned int code[2]={0x86a5acc6,0x579acf59};
encrypt(flag,key,n);
printf("%x %x\n",flag[0],flag[1]);
decrypt(code,key,n);
printf("%x %x\n",code[0],code[1]);
}
IDEA
密钥128位,转为8个16位的数,然后循环左位移25位得到新的8个数, 扩展到44个数。
加密就是,明文和密钥的9轮运算,前8轮一样,最后一轮单独算
加密算法
#include<stdio.h>
#include<string.h>
#define IDEA_ADD_MODULAR 65536
#define IDEA_MP_MODULAR 65537
unsigned short endkey[52];
void swap(unsigned short *a,unsigned short *b)
{
unsigned short c;
c=*a;
*a=*b;
*b=c;
}
unsigned short add_mod(unsigned short a,unsigned short b)
{
unsigned short tmp=a+b;
return tmp%IDEA_ADD_MODULAR;
}
unsigned short mp_mod(unsigned short a,unsigned short b)
{
unsigned long long tmp, tmp_a, tmp_b;
tmp_a = a == 0 ? (1 << 16) : a;
tmp_b = b == 0 ? (1 << 16) : b;
tmp = (tmp_a * tmp_b) % IDEA_MP_MODULAR;
return (unsigned short)(tmp);
}
void releft(unsigned short temkey[])
{
unsigned high=temkey[0]>>(16-5);
int i;
for(i=0;i<7;i++)
{
temkey[i]=(temkey[i]<<5)|(temkey[i+1]>>(16-5));
}
temkey[7]=temkey[7]<<5|high;
}
void extendkey(unsigned char key[])
{
int i,j,k;
unsigned short temkey[8];
//得到开始的8个endkey
for(i=0;i<8;i++)
{
temkey[i]=(key[i*2]<<8)|(key[i*2+1]);
endkey[i]=(key[i*2]<<8)|(key[i*2+1]);
// printf("%04x ",endkey[i]);
}
//用暂时保存的temkey来扩展
for(i=1;i<=5;i++)
{
for(j=0;j<5;j++)
{
releft(temkey);
}
for(k=0;k<8;k++)
{
endkey[i*8+k]=temkey[k];
}
}
//最后4个密钥
for(j=0;j<5;j++)
{
releft(temkey);
}
for(i=0;i<4;i++)
{
endkey[48+i]=temkey[i];
}
}
void idea_round(unsigned short X[],int group)
{
unsigned short out[4],tmp[4],mid[4],mid_out[2];
int i;
tmp[0]=mp_mod(X[0],endkey[6*group+0]);//1
tmp[1]=add_mod(X[1],endkey[6*group+1]);//2
tmp[2]=add_mod(X[2],endkey[6*group+2]);//3
tmp[3]=mp_mod(X[3],endkey[6*group+3]);//4
mid[0]=tmp[0]^tmp[2];//5
mid[1]=tmp[1]^tmp[3];//6
mid[2]=mp_mod(mid[0],endkey[6*group+4]);//7
mid[3]=add_mod(mid[1],mid[2]);//8
mid_out[0]=mp_mod(mid[3],endkey[6*group+5]);//9
mid_out[1]=add_mod(mid[2],mid_out[0]);//10
out[0]=tmp[0]^mid_out[0];
out[1]=tmp[1]^mid_out[1];
out[2]=tmp[2]^mid_out[0];
out[3]=tmp[3]^mid_out[1];
swap(&out[1],&out[2]);
for(i=0;i<4;i++)
{
X[i]=out[i];
printf("%04x ",X[i]);
}
}
void encrypt(unsigned char key[],unsigned char date[],unsigned short out[])
{
int i,j,rounds,count;
unsigned char *key1;
unsigned char *date1;
unsigned short X[4];
key1=key;
date1=date;
extendkey(key1);
for(i=0;i<52;i++)
{
// printf("%04x ",endkey[i]);
}
rounds=strlen((const char*)date)/8;
for(count=0;count<rounds;count++)
{
for(i=0;i<4;i++)
{
X[i]=(date1[i*2]<<8)|(date1[i*2+1]);
}
for(i=0;i<8;i++)
{
idea_round(X,i);
printf("\n");
}
//最后一轮
swap(&X[1],&X[2]);
X[0]=mp_mod(X[0],endkey[48]);
X[1]=add_mod(X[1],endkey[49]);
X[2]=add_mod(X[2],endkey[50]);
X[3]=mp_mod(X[3],endkey[51]);
for(i=0;i<4;i++)
{
out[i+count*4]=X[i];
}
}
}
int main()
{
unsigned char key[]="1234567812345678";
unsigned char date[]="1234567812345678";
unsigned short out[8];
unsigned char buffer[256];
int i;
encrypt(key,date,out);
printf("\n");
// for(i=0;i<8;i++)
// {
// printf("%02x %02x ",*((char*)&out[i])&0xff,*((char*)&out[i] + 1)&0xff);
// }
// printf("\n");
for(i=0;i<8;i++)
{
printf("%04x ",out[i]);
}
}
解密算法好像就是密钥的问题,还没看懂。
AES
基本介绍:https://blog.csdn.net/qq_28205153/article/details/55798628
注意的两个点:
- 然后CBC模式就多一个iv,也就是在每一轮加密前,先和iv异或,然后一轮加密后的密文,又作为下一轮的iv
- 128,192,256加密的轮数和一些细节地方是不一样的。
自己的实现,借用了别人的一些代码,是最简单的Aes的ECB模式
#include<stdio.h>
/****************/
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) );
}
/***********************/
unsigned char S[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 };
unsigned char S2[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 };
unsigned int Rcon[10]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36};
void addRoundKey(unsigned char *ipArray,unsigned char *endkey,int n)
{
int i;
for(i=0;i<4;i++)
{
ipArray[i*4+0]^=endkey[i*4+n*16+0];
ipArray[i*4+1]^=endkey[i*4+n*16+1];
ipArray[i*4+2]^=endkey[i*4+n*16+2];
ipArray[i*4+3]^=endkey[i*4+n*16+3];
}
}
void subBytes(unsigned char *ipArray)
{
int i;
int a,b;
for(i=0;i<16;i++)
{
a=ipArray[i]>>4;
b=ipArray[i]&0xf;
ipArray[i]=S[a][b];
}
}
void shiftRows(unsigned char *ipArray)
{
int i,j,k;
unsigned char tmp,mid[16];
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
mid[j*4+i]=ipArray[i*4+j];
}
}
for(i=1;i<4;i++)
{
for(j=0;j<i;j++)
{
tmp=mid[i*4];
for(k=0;k<3;k++)
{
mid[i*4+k]=mid[i*4+k+1];
}
mid[i*4+k]=tmp;
}
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
ipArray[j*4+i]=mid[i*4+j];
}
}
}
void mixColumns(unsigned char *ipArray)
{
unsigned char a[] = {0x02, 0x03, 0x01, 0x01};
unsigned char tmp[4],mid[16];
int i,j;
for(i=0,j=0;i<4;i++,j+=4)
{
tmp[0]=x2time(ipArray[j]) ^ x3time(ipArray[j+1]) ^ ipArray[j+2] ^ ipArray[j+3];//2 3 1 1
tmp[1]=ipArray[j] ^ x2time(ipArray[j+1]) ^ x3time(ipArray[j+2]) ^ ipArray[j+3];//1 2 3 1
tmp[2]=ipArray[j] ^ ipArray[j+1] ^ x2time(ipArray[j+2]) ^ x3time(ipArray[j+3]);//1 1 2 3
tmp[3]=x3time(ipArray[j]) ^ ipArray[j+1] ^ ipArray[j+2] ^ x2time(ipArray[j+3]);//3 1 1 2
mid[i*4+0]=tmp[0];
mid[i*4+1]=tmp[1];
mid[i*4+2]=tmp[2];
mid[i*4+3]=tmp[3];
}
for(i=0;i<16;i++)
{
ipArray[i]=mid[i];
}
}
//加密
void AesEncrypt(unsigned char *in,unsigned char *endkey,unsigned char *out)
{
unsigned char *ipArray;
int i,j,k;
int rounds=10;
ipArray=in;
addRoundKey(ipArray, endkey,0);
for(i=1;i<10;i++)
{
subBytes(ipArray);
shiftRows(ipArray);
mixColumns(ipArray);
addRoundKey(ipArray,endkey,i);
}
subBytes(ipArray);
shiftRows(ipArray);
addRoundKey(ipArray,endkey,10);
}
void inv_shiftRows(unsigned char *state)
{
int i,j,k;
unsigned char tmp,mid[16];
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
mid[j*4+i]=state[i*4+j];
}
}
for(i=1;i<4;i++)
{
for(j=0;j<i;j++)
{
tmp=mid[i*4+3];
for(k=3;k>0;k--)
{
mid[i*4+k]=mid[i*4+k-1];
}
mid[i*4+k]=tmp;
}
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
state[j*4+i]=mid[i*4+j];
}
}
}
void inv_subBytes(unsigned char *state)
{
int i;
int a,b;
for(i=0;i<16;i++)
{
a=state[i]>>4;
b=state[i]&0xf;
state[i]=S2[a][b];
}
}
void inv_mixColumns(unsigned char *state)
{
unsigned char a[] = {0x0E, 0x0B, 0x0D, 0x09};
unsigned char tmp[4],mid[16];
int i,j;
for(i=0,j=0;i<4;i++,j+=4)
{
tmp[0]=xEtime(state[j]) ^ xBtime(state[j+1]) ^ xDtime(state[j+2]) ^ x9time(state[j+3]);//E B D 9
tmp[1]=x9time(state[j]) ^ xEtime(state[j+1]) ^ xBtime(state[j+2]) ^ xDtime(state[j+3]);//9 E B D
tmp[2]=xDtime(state[j]) ^ x9time(state[j+1]) ^ xEtime(state[j+2]) ^ xBtime(state[j+3]);//D 9 E B
tmp[3]=xBtime(state[j]) ^ xDtime(state[j+1]) ^ x9time(state[j+2]) ^ xEtime(state[j+3]);//B D 9 E
mid[i*4+0]=tmp[0];
mid[i*4+1]=tmp[1];
mid[i*4+2]=tmp[2];
mid[i*4+3]=tmp[3];
}
for(i=0;i<16;i++)
{
state[i]=mid[i];
}
}
//解密
void AesDecrypt(unsigned char *in,unsigned char *endkey,unsigned char *out)
{
unsigned char *state;
int i,j,k;
int rounds=10;
state=in;
addRoundKey(state,endkey,10);
for(i=rounds-1;i>0;i--)
{
inv_shiftRows(state);
inv_subBytes(state);
addRoundKey(state,endkey,i);
inv_mixColumns(state);
}
inv_shiftRows(state);
inv_subBytes(state);
addRoundKey(state,endkey,0);
}
//扩展密钥
void leftLoop(unsigned char mid[])
{
unsigned char t;
t=mid[0]; mid[0]=mid[1]; mid[1]=mid[2]; mid[2]=mid[3]; mid[3]=t;
}
void box_change(unsigned char mid[])
{
int i;
int a,b;
for(i=0;i<4;i++)
{
a=mid[i]>>4;
b=mid[i]&0xf;
mid[i]=S[a][b];
}
}
void extendkey(unsigned char key[],unsigned char endkey[])
{
unsigned char tmp[4];
int i;
for(i=0;i<4;i++)
{
endkey[i*4+0]=key[i*4+0];
endkey[i*4+1]=key[i*4+1];
endkey[i*4+2]=key[i*4+2];
endkey[i*4+3]=key[i*4+3];
}
for(i=4;i<44;i++)
{
tmp[0]=endkey[4*(i-1)+0];
tmp[1]=endkey[4*(i-1)+1];
tmp[2]=endkey[4*(i-1)+2];
tmp[3]=endkey[4*(i-1)+3];
if(i%4==0)
{
leftLoop(tmp);
box_change(tmp);
tmp[0]^=Rcon[i/4-1];
}
endkey[i*4+0]=tmp[0]^endkey[4*(i-4)+0];
endkey[i*4+1]=tmp[1]^endkey[4*(i-4)+1];
endkey[i*4+2]=tmp[2]^endkey[4*(i-4)+2];
endkey[i*4+3]=tmp[3]^endkey[4*(i-4)+3];
}
}
int main(void)
{
unsigned char plain[17]="abcdefghijklmnop",key[17]="1234567812345678";
unsigned char endkey[11*16+1];
unsigned char out[16];
unsigned char code[16]={0xCC,0x96,0xB9,0x6C,0x11,0xBD,0xAD,0x3A,0x7A,0x73,0xDB,0xCD,0x9E,0x5A,0xF2,0x44};
int i;
extendkey(key,endkey);
// for(i=0;i<11*16;i++)
// {
// if(i%4==0)
// {
// printf(" ");
// }
// printf("%02x",endkey[i]);
// }
AesEncrypt(plain,endkey,out);
printf("加密后的数据是:") ;
for (i = 0; i < 16; i++)
{
printf("0x%02x,", plain[i]);
}
printf("\n解密后的数据是:") ;
AesDecrypt(code,endkey,out);
for (i = 0; i < 16; i++)
{
printf("%c", code[i]);
}
}
DES
https://bbs.pediy.com/thread-253558.htm#msg_header_h1_1
占时不打算直接用c写了,整个过程大致了解了,可以说是bit位的加密方式,如果以后有必要在来补充吧。
SM4
https://blog.csdn.net/weixin_46491183/article/details/112686034
https://blog.csdn.net/weixin_42700740/article/details/102667012
https://blog.csdn.net/jiujiederoushan/article/details/100122773
自己用c写的ECB模式。
#include<stdio.h>
unsigned int FK[4] = {
0xa3b1bac6,
0x56aa3350,
0x677d9197,
0xb27022dc
};
/******************************定义固定参数CK的取值****************************************/
unsigned int CK[32] = {
0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
0x10171e25,0x2c333a41,0x484f565d,0x646b7279
};
/******************************SBox参数列表****************************************/
unsigned char SBOX[256] = {
0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,
0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,
0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,
0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,
0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48
};
void long_to_char(unsigned int in ,unsigned char *out)
{
int i;
for(i=0;i<4;i++)
{
out[i]=(unsigned char)(in>>(24-i*8))&0xff;
}
}
void char_to_long(unsigned char *in , unsigned int *out)
{
int i;
*out=0;
for(i=0;i<4;i++)
{
*out = (unsigned int)in[i]<<(24-8*i)|(*out);
}
}
unsigned int left_move(unsigned int a,int lenth)
{
a=(a<<lenth) | a>>(32-lenth);
return a;
}
unsigned int date_round(unsigned int tmp)
{
int i;
unsigned char arr[4]={0};
long_to_char(tmp,arr);
for(i=0;i<4;i++)
{
arr[i]=SBOX[arr[i]];
}
char_to_long(arr,&tmp);
tmp = tmp ^ left_move(tmp, 2) ^ left_move(tmp, 10) ^ left_move(tmp, 18) ^ left_move(tmp, 24);
return tmp;
}
void sm4_encode(unsigned char *plain,unsigned int sub_key[],unsigned char out[])
{
int i;
unsigned int date[36];
for(i=0;i<4;i++)
{
char_to_long(plain+i*4,date+i);
}
for(i=0;i<32;i++)
{
date[i+4]=date[i]^date_round(date[i+1]^date[i+2]^date[i+3]^sub_key[i+4]);
}
for(i=0;i<4;i++)
{
long_to_char(date[35-i],out+i*4);
}
}
void sm4_decode(unsigned char *code,unsigned int sub_key[],unsigned char out[])
{
int i;
unsigned int date[36];
for(i=0;i<4;i++)
{
char_to_long(code+i*4,date+i);
}
for(i=0;i<32;i++)
{
date[i+4]=date[i]^date_round(date[i+1]^date[i+2]^date[i+3]^sub_key[35-i]);
}
for(i=0;i<4;i++)
{
long_to_char(date[35-i],out+i*4);
}
}
unsigned int key_round(unsigned int tmp)
{
int i;
unsigned char arr[4]={0};
long_to_char(tmp,arr);
for(i=0;i<4;i++)
{
arr[i]=SBOX[arr[i]];
}
char_to_long(arr,&tmp);
tmp = tmp ^ left_move(tmp, 13) ^ left_move(tmp, 23);
return tmp;
}
void extendkey(unsigned char key[],unsigned int sub_key[])
{
int i;
for(i=0;i<4;i++)
{
char_to_long(key+i*4,sub_key+i);
sub_key[i]^=FK[i];
}
for(i=0;i<32;i++)
{
sub_key[i+4]=sub_key[i] ^ key_round(sub_key[i+1] ^ sub_key[i+2] ^ sub_key[i+3] ^ CK[i]);
}
}
int main(void)
{
unsigned char key[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
unsigned char code[16]={0x68,0x1e,0xdf,0x34,0xd2,0x06,0x96,0x5e,0x86,0xb3,0xe9,0x4f,0x53,0x6e,0x42,0x46};
unsigned char plain[16]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
unsigned int sub_key[36]={0};
unsigned char out[16];
int i;
extendkey(key,sub_key);
sm4_encode(plain,sub_key,out);
for(i=0;i<16;i++)
{
printf("0x%02x,",out[i]);
}
printf("\n");
sm4_decode(code,sub_key,out);
for(i=0;i<16;i++)
{
printf("0x%02x,",out[i]);
}
}
网上的python版本
SBOX = ['d6', '90', 'e9', 'fe', 'cc', 'e1', '3d', 'b7', '16', 'b6', '14', 'c2', '28', 'fb', '2c', '05',
'2b', '67', '9a', '76', '2a', 'be', '04', 'c3', 'aa', '44', '13', '26', '49', '86', '06', '99',
'9c', '42', '50', 'f4', '91', 'ef', '98', '7a', '33', '54', '0b', '43', 'ed', 'cf', 'ac', '62',
'e4', 'b3', '1c', 'a9', 'c9', '08', 'e8', '95', '80', 'df', '94', 'fa', '75', '8f', '3f', 'a6',
'47', '07', 'a7', 'fc', 'f3', '73', '17', 'ba', '83', '59', '3c', '19', 'e6', '85', '4f', 'a8',
'68', '6b', '81', 'b2', '71', '64', 'da', '8b', 'f8', 'eb', '0f', '4b', '70', '56', '9d', '35',
'1e', '24', '0e', '5e', '63', '58', 'd1', 'a2', '25', '22', '7c', '3b', '01', '21', '78', '87',
'd4', '00', '46', '57', '9f', 'd3', '27', '52', '4c', '36', '02', 'e7', 'a0', 'c4', 'c8', '9e',
'ea', 'bf', '8a', 'd2', '40', 'c7', '38', 'b5', 'a3', 'f7', 'f2', 'ce', 'f9', '61', '15', 'a1',
'e0', 'ae', '5d', 'a4', '9b', '34', '1a', '55', 'ad', '93', '32', '30', 'f5', '8c', 'b1', 'e3',
'1d', 'f6', 'e2', '2e', '82', '66', 'ca', '60', 'c0', '29', '23', 'ab', '0d', '53', '4e', '6f',
'd5', 'db', '37', '45', 'de', 'fd', '8e', '2f', '03', 'ff', '6a', '72', '6d', '6c', '5b', '51',
'8d', '1b', 'af', '92', 'bb', 'dd', 'bc', '7f', '11', 'd9', '5c', '41', '1f', '10', '5a', 'd8',
'0a', 'c1', '31', '88', 'a5', 'cd', '7b', 'bd', '2d', '74', 'd0', '12', 'b8', 'e5', 'b4', 'b0',
'89', '69', '97', '4a', '0c', '96', '77', '7e', '65', 'b9', 'f1', '09', 'c5', '6e', 'c6', '84',
'18', 'f0', '7d', 'ec', '3a', 'dc', '4d', '20', '79', 'ee', '5f', '3e', 'd7', 'cb', '39', '48',]
FK = ['a3b1bac6', '56aa3350', '677d9197', 'b27022dc']
CK = ['00070e15', '1c232a31', '383f464d', '545b6269',
'70777e85', '8c939aa1', 'a8afb6bd', 'c4cbd2d9',
'e0e7eef5', 'fc030a11', '181f262d', '343b4249',
'50575e65', '6c737a81', '888f969d', 'a4abb2b9',
'c0c7ced5', 'dce3eaf1', 'f8ff060d', '141b2229',
'30373e45', '4c535a61', '686f767d', '848b9299',
'a0a7aeb5', 'bcc3cad1', 'd8dfe6ed', 'f4fb0209',
'10171e25', '2c333a41', '484f565d', '646b7279']
def left(list,n):
return list[n:] + list[:n]
def group(list, n):
for i in range(0, len(list), n):
yield list[i:i + n]
def xor(a,b):
a1 = int(a,16)
b1 = int(b,16)
if a == b:
A = '{:032x}'.format(int(a1^b1))
else:
A = '{:08x}'.format(int(a1^b1))
return A
def round_function(k0,k1,k2,k3,rk,mod):
k = xor(xor(xor(k1,k2),k3),rk)
Tr = T(k,mod)
rki = xor(k0,Tr)
return rki
def T(A,mod):
T = linear(S(A),mod)
return T
def S(A):
A1 = []
A2 = [0,0,0,0]
for i in group(A,2):
A1.append(i)
for i in range(4):
l = int(A1[i],16)
A2[i] = '{:02x}'.format(int(SBOX[l],16))
A2 = ''.join(A2)
return A2
def linear(B,mod):
B1 = list(B)
for i in range(8):
B1[i] = '{:04b}'.format(int(B1[i],16))
B1 = ''.join(B1)
B1_2= left(B1,2)
B1_10 = left(B1,10)
B1_18 = left(B1,18)
B1_24 = left(B1,24)
B1_13 = left(B1,13)
B1_23 = left(B1,23)
if mod == 'enc' or mod == 'dec':
BX = xor(xor(xor(xor(B1,B1_2),B1_10),B1_18),B1_24)
elif mod == 'extend':
BX = xor(xor(B1,B1_13),B1_23)
else:
return "模式输入错误"
BX = '%x'%int(BX, 2)
return BX
def get_key(key):
MK = []
for i in group(key,8):
MK.append(i)
key0 = xor(MK[0],FK[0])
key1 = xor(MK[1],FK[1])
key2 = xor(MK[2],FK[2])
key3 = xor(MK[3],FK[3])
keylist = [key0,key1,key2,key3]
rk = []
for i in range(32):
a = round_function(keylist[i],keylist[i+1],keylist[i+2],keylist[i+3],CK[i],mod='extend')
keylist.append(a)
rk.append(a)
return rk
def get_sm4_ecb(key,input_data,mod):
data = []
rk = get_key(key)
for i in group(input_data,8):
data.append(i)
for i in range(32):
if mod == 'enc':
ldata = round_function(data[i],data[i+1],data[i+2],data[i+3],rk[i],mod)
else:
ldata = round_function(data[i],data[i+1],data[i+2],data[i+3],rk[31-i],mod)
data.append(ldata)
out_data = [data[35],data[34],data[33],data[32]]
out_data = ''.join(out_data)
return out_data
def get_sm4_cbc(key,input_data,iv,mod):
rk = get_key(key)
if mod == 'enc':
input_data = xor(input_data,iv)
data = []
for i in group(input_data,8):
data.append(i)
for i in range(32):
ldata = round_function(data[i],data[i+1],data[i+2],data[i+3],rk[i],mod)
data.append(ldata)
out_data = [data[35],data[34],data[33],data[32]]
out_data = ''.join(out_data)
else:
data = []
for i in group(input_data,8):
data.append(i)
for i in range(32):
ldata = round_function(data[i],data[i+1],data[i+2],data[i+3],rk[31-i],mod)
data.append(ldata)
out_data = [data[35],data[34],data[33],data[32]]
out_data = ''.join(out_data)
out_data = xor(out_data,iv)
out_data = '{:032x}'.format(int(out_data, 16))
return out_data
print(get_sm4_ecb(key = '0123456789abcdeffedcba9876543210', input_data = '0123456789abcdeffedcba9876543210', mod = 'enc'))
print(get_sm4_ecb(key = '0123456789abcdeffedcba9876543210', input_data = '681edf34d206965e86b3e94f536e4246', mod = 'dec'))
print(get_sm4_cbc(key = '0123456789abcdeffedcba9876543210', input_data = '681edf34d206965e86b3e94f536e4246',
iv = '0123456789abcdeffedcba9876543210', mod='enc'))
print(get_sm4_cbc(key = '0123456789abcdeffedcba9876543210', input_data = '9ff11dcfd3afaa236c76090babc3bb85',
iv = '0123456789abcdeffedcba9876543210', mod='dec'))
BlowFish
https://www.cnblogs.com/iBinary/p/14883752.html