A加密算法

rot13       

对称加密算法

Rot13是一种简易的替换式加密算法,也称为回转13位。它的原理是将明文中的每个字母都向后移动13位,即A变为N,B变为O,以此类推。这样加密后的密文只有字母被替换,其他字符不变。解密时只需要将密文再次进行Rot13加密即可得到原文。

Rot13是一种替换式加密算法,它对字母表中的每个字母进行替换。具体来说,它通过将输入字符串中的每个字母的ASCII值进行变换来实现加密。

具体加密步骤如下:

1.对于输入字符串中的每个字母,将其ASCII值加上13或减去13,具体取决于它是大写字母还是小写字母。

2.然后找到计算后的ASCII值对应的字母。

例如,对于大写字母"A",其ASCII值为65。将其加上13得到78,对应的字母为"N"。对于小写字母"a",其ASCII值为97。将其加上13得到109,对应的字母为"m"。

通过这样的规则将输入字符串中的每个字母替换为另一个字母,从而达到加密的目的。同样的,解密时将密文中的字母的ASCII值进行反向变换即可得到原文。

需要注意的是,由于字母表中共有26个字母,所以Rot13加密算法是一种对称加密算法,加密和解密的过程是相同的。

凯撒密码

 凯撒密码的替换方法是通过排列明文和密文字母表,密文字母表示通过将明文字母表向左或向右移动一个固定数目的位置例如,当偏移量是左移3的时候(解密时的密钥就是3)

base16

Base16编码就是将ASCII字符集中可打印的字符(数字0~9和字母A~F)对应的二进制字节数据进行编码

编码的方式:

1.将数据(根据ASCII编码,UTF-8编码等)转成对应的二进制数,不足8比特位高位补0.然后将所有的二进制全部串起来,4个二进制位为一组,转化成对应十进制数.

2.根据十进制数值找到Base16编码表里面对应的字符.Base16是4个比特位表示一个字符,所以原始是1个字节(8个比特位)刚好可以分成两组,也就是说原先如果使用ASCII编码后的一个字符,现在转化成两个字符.数据量是原先的2倍.

例子

love字符串对应AscII表的二进制为:

01101100    01101111    01110110   01100101

按照Base16编码,没四个字符为一组,可分为:

0110    1100    0110    1111    0111   0110   0110  0101

对应Base16表的字符串为:6C6F7665

Base32

Base32编码是使用32个可打印字符(字母A-Z和数字2-7)对任意字节数据进行编码的方案,编码后的字符串不用区分大小写并排除了容易混淆的字符

Base32将任意字符串按照字节进行切分,并将每个字节对应的二进制值(不足8比特高位补0)串联起来,按照5比特一组进行切分,并将每组二进制值转换成十进制来对应32个可打印字符中的一个。由于数据的二进制传输是按照8比特一组进行(即一个字节),因此Base32按5比特切分的二进制数据必须是40比特的倍数(5和8的最小公倍数)。

例如输入单字节字符“%”,它对应的二进制值是“100101”,前面补两个0变成“00100101”(二进制值不足8比特的都要在高位加0直到8比特),从左侧开始按照5比特切分成两组:“00100”和“101”,后一组不足5比特,则在末尾填充0直到5比特,变成“00100”和“10100”,这两组二进制数分别转换成十进制数,通过上述表格即可找到其对应的可打印字符“E”和“U”,但是这里只用到两组共10比特,还差30比特达到40比特,按照5比特一组还需6组,则在末尾填充6个“=”。填充“=”符号的作用是方便一些程序的标准化运行,大多数情况下不添加也无关紧要,而且,在URL中使用时必须去掉“=”符号

base编码优缺点

与Base64相比,Base32具有许多优点:

适合不区分大小写的文件系统,更利于人类口语交流或记忆。
结果可以用作文件名,因为它不包含路径分隔符 “/”等符号。
排除了视觉上容易混淆的字符,因此可以准确的人工录入。(例如,RFC4648符号集忽略了数字“1”、“8”和“0”,因为它们可能与字母“I”,“B”和“O”混淆)。
排除填充符号“=”的结果可以包含在URL中,而不编码任何字符。
Base32也比Base16有优势:

Base32比Base16占用的空间更小。(1000比特数据Base32需要200个字符,而Base16则为250个字符)
Base32的缺点:

Base32比Base64多占用大约20%的空间。因为Base32使用8个ASCII字符去编码原数据中的5个字节数据,而Base64是使用4个ASCII字符去编码原数据中的3个字节数据

base64

字符选用了"A-Z、a-z、0-9、+、/" 64个可打印字符,这是标准的Base64协议规定。我们还会看到“=”或“==”号出现在Base64的编码结果中,“=”在此是作为填充字符出现,后面会讲到。

第一步,将待转换的字符串每三个字节分为一组,每个字节占8bit,那么共有24个二进制位。
第二步,将上面的24个二进制位每6个一组,共分为4组。
第三步,在每组前面添加两个0,每组由6个变为8个二进制位,总共32个二进制位,即四个字节。
第四步,根据Base64编码对照表获得对应的值。

实例

第一步:“M”、“a”、"n"对应的ASCII码值分别为77,97,110,对应的二进制值是01001101、01100001、01101110。如图第二三行所示,由此组成一个24位的二进制字符串。
第二步:如图红色框,将24位每6位二进制位一组分成四组。
第三步:在上面每一组前面补两个0,扩展成32个二进制位,此时变为四个字节:00010011、00010110、00000101、00101110。分别对应的值(Base64编码索引)为:19、22、5、46。
第四步:用上面的值在Base64编码表中进行查找,分别对应:T、W、F、u。因此“Man”Base64编码之后就变为:TWFu

两个字节:两个字节共16个二进制位,依旧按照规则进行分组。此时总共16个二进制位,每6个一组,则第三组缺少2位,用0补齐,得到三个Base64编码,第四组完全没有数据则用“=”补上。因此,上图中“BC”转换之后为“QKM=”;
一个字节:一个字节共8个二进制位,依旧按照规则进行分组。此时共8个二进制位,每6个一组,则第二组缺少4位,用0补齐,得到两个Base64编码,而后面两组没有对应数据,都用“=”补上。因此,上图中“A”转换之后为“QQ==”;

注意

大多数编码都是由字符串转化成二进制的过程,而Base64的编码则是从二进制转换为字符串。与常规恰恰相反,
Base64编码主要用在传输、存储、表示二进制领域,不能算得上加密,只是无法直接看到明文。也可以通过打乱Base64编码来进行加密。
中文有多种编码(比如:utf-8、gb2312、gbk等),不同编码对应Base64编码结果都不一样

base64换表脚本

py3的

str1是要解密的代码

string1是改过之后的base64表

import base64
import string

str1 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q"

string1 = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

其余参考:http://t.csdnimg.cn/n7jF7

其余参考:http://t.csdnimg.cn/b3eDK

RC4

参考:http://t.csdnimg.cn/J8NO9

参考:http://t.csdnimg.cn/Zu0bA

RC4由伪随机数生成器和异或运算组成。RC4的密钥长度可变,范围是[1,255]。RC4一个字节一个字节地加解密。给定一个密钥,伪随机数生成器接受密钥并产生一个S盒。S盒用来加密数据,而且在加密过程中S盒会变化。

由于异或运算的对合性,RC4加密解密使用同一套算法。

初始化S

初始条件:密钥种子key[],密钥初始化向量S

初始化S: S中元素被置为按升序从0到255(S[0]=0,S[1]=1,.....,S[255]=255)

建立临时矢量K

如果密钥种子Key[]的长度为256字节,则将Key赋值给K

否则将Key[]的值赋给K的前N个元素(N为密钥Key[]的长度)

循环重复用Key[]的值赋给K剩下的元素,直到K的所有元素都被赋值

用K对S进行初始置换

从S[0]到S[255],对每个S[i],根据由K[i]确定的方案,将S[i]置换为S中的其他一个字节

密码流KeyStramByte的生成是从S[]选择一个元素

将Keys和下一个明文字节进行异或运算

解密脚本

void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k) //初始化函数
{
    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_k];
    }
    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;
    }
}

/*
RC4加解密函数
unsigned char* Data     加解密的数据
unsigned long Len_D     加解密数据的长度
unsigned char* key      密钥
unsigned long Len_k     密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
    unsigned char s[256];
    rc4_init(s, key, Len_k);
    int i = 0, j = 0, t = 0;
    unsigned long k = 0;
    unsigned char tmp;
    for (k = 0; k < Len_D; 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];
    }
}

MD5

单向散列函数是指对不同的输入值,通过单向散列函数进行计算,得到固定长度的输出值。这个输入值称为消息(message),输出值称为散列值(hash value)。

单向散列函数有多种实现算法,常见的有:MD5、SHA-1、SHA-2和 SHA-3。

不可逆,相同的数据的MD5值肯定一样,不同数据的MD5值不一样(理论上可能会有相同的)
一个MD5理论上的确是可能对应无数多个原文的,因为MD5是有限多个的而原文是可以有无数多个的。比如主流使用的MD5将任意长度的字符串映射为一个128bit(16 * 8)的大整数。也就是一共有 2的128次方种可能,大概是 3.14*10的38次方,这个数字是有限的,但是世界上可以被用来加密的原文则有无数的可能性

MD5 算法原理

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

原理一

在 MD5 算法中,首先需要对信息进行填充,这个数据按位补充,要求最终的位数对512求模的结果为448。也就是说数据补位后,其位数长度只差64位就是512的整数倍。即便是这个数据的位数对512求模的结果正好是448也必须进行补位。补位的实现过程:首先在数据后补一个1 bit; 接着在后面补上一堆0 bit, 直到整个数据的位数对512求模的结果正好为448。总之,至少补1位,而最多可能补512位。

在完成补位工作后,又将一个表示数据原始长度的 64 bit数补在最后。当完成补位及补充数据的描述后,得到的结果数据长度正好是512的整数倍。也就是说,长度正好是16个(32bit) 字的整数倍。

需要注意,MD5 运算要用到一个128位的 MD5 缓存器,用来保存中间变量和最终结果。该缓存器又可看成是4个32位的寄存器A、B、C、D,初始化如下:

A : 01 23 45 67
B: 89 ab cd ef
C: fe dc ba 98
D: 76 54 32 10
MD5 处理数据段时,首先定义4个非线性函数 F、G、H、I,对输入的报文运算以512位数据段为单位进行处理。对每个数据段都要进行4轮的逻辑处理,在4轮中分别使用4个不同的函数 F、G、H、I。每一轮以 ABCD 和当前的512位的块为输入,处理后送入 ABCD (128位)。

信息摘要最终处理成以 A, B, C, D 的形式输出。也就是开始于 A 的低位在前的顺序字节,结束于 D 的高位在前的顺序字节。

原理二

对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

一、填充:如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit);

二、记录信息长度:用64位来存储填充前信息长度(这样可以处理的数据已经足够大了--)。

这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。

三、装入标准的幻数(四个整数):标准的幻数(物理顺序)是

A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16

如果在程序中定义应该是:
A=0x67452301,B=0xEFCDAB89,C=0x98BADCFE,D=0x10325476

当然你写程序的时候还是直接让A=01234567.......(计算机大小端存储)

验证 MD5 的工具

MD5在线加密/解密/破解—MD5在线 (sojson.com)

SHA

SHA1加密原理

        第一步:首先将China单词转化为ASCII码的十六进制表示方式

China的十六进制为:43 68 69 6E 61

        第二步:对得到的数据  4368696E61 进行填充和附加,使其能够被512整除。

        对于任意长度的明文,SHA1的明文分组过程与MD5相类似,首先需要对明文添加位数,使明文总长度为448(mod512)位。在明文后添加位的方法是第一个添加位是l,其余都是0。然后将真正明文的长度(没有添加位以前的明文长度)以64位表示,附加于前面已添加过位的明文后,此时的明文长度正好是512位的倍数。与MD5不同的是SHA1的原始报文长度不能超过2的64次方,另外SHA1的明文长度从低位开始填充。

        第三步:将得到数据进行拆分,按照512位分块。SHA1有4轮运算,每一轮包括20个步骤(一共80步),最后产生160位摘要。

SHA256(wait)

参考:http://t.csdnimg.cn/JWoDg

STEP1:附加填充比特

在报文末尾进行填充,使报文长度在对512取模以后的余数是448

填充是这样进行的:先补第一个比特为1,然后都补0,直到长度满足对512取模后余数是448。

需要注意的是,信息必须进行填充,也就是说,即使长度已经满足对512取模后余数是448,补位也必须要进行,这时要填充512个比特。

因此,填充是至少补一位,最多补512位。

例:以信息“abc”为例显示补位的过程。

a,b,c对应的ASCII码分别是97,98,99

于是原始信息的二进制编码为:01100001 01100010 01100011

补位第一步,首先补一个“1” : 0110000101100010 01100011 1

补位第二步,补423个“0”:01100001 01100010 01100011 10000000 00000000 … 00000000

补位完成后
为什么是448

因为在第一步的预处理后,第二步会再附加上一个64bit的数据,用来表示原始报文的长度信息。而448+64=512,正好拼成了一个完整的结构。

STEP2:附加长度值

附加长度值就是将原始数据(第一步填充前的消息)的长度信息补到已经进行了填充操作的消息后面。

SHA256用一个64位的数据来表示原始消息的长度。

因此,通过SHA256计算的消息长度必须要小于 2^64 ,当然绝大多数情况这足够大了。

长度信息的编码方式为64-bit big-endian integer(大端)


2.3 逻辑运算
SHA256散列函数中涉及的操作全部是逻辑的位运算

SM4

参考:http://t.csdnimg.cn/uHwhr

2012年3月,国家密码管理局正式公布了包含SM4分组密码算法在内的《祖冲之序列密码算法》等6项密码行业标准。与DES和AES算法类似,SM4算法是一种分组密码算法。其分组长度为128bit,密钥长度也为128bit。加密算法与密钥扩展算法均采用32轮非线性迭代结构,以字(32位)为单位进行加密运算,每一次迭代运算均为一轮变换函数F。SM4算法加/解密算法的结构相同,只是使用轮密钥相反,其中解密轮密钥是加密轮密钥的逆序。

​ SM4有很高的灵活性,所采用的S盒可以灵活地被替换,以应对突发性的安全威胁。算法的32轮迭代采用串行处理,这与AES中每轮使用代换和混淆并行地处理整个分组有很大不同。

TEA

TEA加密

TEA 采用与 DES 算法类似的 Feistel 结构,迭代的每次循环使用加法和移位操作,对明文和密钥进行扩散和混乱,实现明文的非线性变换。TEA 密钥长度和迭代次数都是 DES 的两倍,抗“试错法”攻击的强度不低于 DES 算法。算法以32bits 的字为运算单位,而不是耗费计算能力的逐位运算。算法没有采用 DES 那样的转换矩阵,它安全、高效、占用存储空间少,非常适合在嵌入式系统中应用, 据说 QQ 就是使用 16 轮迭代的 TEA 算法。

#include <stdio.h>
#include <stdint.h>
 
void encrypt (uint32_t *v,uint32_t *k ){
	uint32_t v0=v[0],v1=v[1],sum=0,i;
	uint32_t delta=0x9e3779b9;
	uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];
	for(i=0;i<32;i++){
		sum+=delta;
		v0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
		v1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
	} 
	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;	//这里的sum是0x9e3779b9*32后截取32位的结果,截取很重要。
	uint32_t delta=0x9e3779b9;
	uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];
	for (i=0;i<32;i++){
		v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
		v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
		sum-=delta;
	} 
	v[0]=v0;v[1]=v1;
}
 
int main()
{
	uint32_t v[2]={1,2},k[4]={2,2,3,4};
	printf("加密前的数据:%u %u\n",v[0],v[1]);	//%u 以十进制形式输出无符号整数 
	encrypt(v,k);
	printf("加密后数据:%u %u\n",v[0],v[1]);
	decrypt(v,k);
	printf("解密后数据:%u %u\n",v[0],v[1]);
	return 0;
}

XTEA加密

#include<stdio.h>
#include<stdint.h>
 
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;				//这里是加密轮数,自己设置 
	printf("加密前原始数据:%u %u\n",v[0],v[1]);
	encipher(r,v,k);
	printf("加密后原始数据:%u %u\n",v[0],v[1]);
	decipher(r,v,k);
	printf("解密后原始数据:%u %u\n",v[0],v[1]);
	return 0;
}

XXTEA 加密

XXTEA,又称Corrected Block TEA

XXTEA是一个非平衡Feistel网络分组密码,在可变长度块上运行,这些块是32位大小的任意倍数(最小64位),使用128位密钥, 是目前TEA系列中最安全的算法,但性能较上两种有所降低。

#include<stdio.h>
#include<stdint.h>
#define DELTA 0x933779b9
#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)
	{
		rounds=6+52/n;	//这里可以说是预定义值,n=2是rounds=32
		sum=0;
		z=v[n-1];
		do
		{
			sum+=DELTA;
			e=(sum>>2)&3;
			for(p=0;p<n-1;p++)        //注意这里的p是从0~n-1
			{
				y=v[p+1];
				z=v[p]+=MX;
			}
			y=v[0];
			z=v[n-1]+=MX;        //这里的MX中传入的p=n-1
		}	
		while(--rounds);
	}
	else if(n<-1)
	{
		n=-n;
		rounds=6+52/n;
		sum=rounds*DELTA;
		y=v[0];
		do
		{
			e=(sum>>2)&3;
			for(p=n-1;p>0;p--)    //注意这里的p是从n-1~0,和上面是反过来的
			{
				z=v[p-1];
				y=v[p]-=MX;
			}
			z=v[n-1];
			y=v[0]-=MX;    //这里的MX中传入的 p=0
			sum-=DELTA;
		}
		while(--rounds);
	}
}
 
int main()
{
	uint32_t v[2]={1,2};
	uint32_t const k[4]={2,2,3,4};
	int n=2;
	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; 
	
}

RSA

加密 c ≡ m 的e次方 mod N

RSA的密文是对代表明文的数字 m 的 e 次方对 N 求余的结果

公钥:在已知明文的情况下,只要只要 E 和 N 这两个数,任何人都可以完成对加密的运算。所以说, E 和 N 是RSA加密的密钥,换句话说,E 和 N 的组合就是公钥,表示为公钥是(E,N)

解密 m≡c的d次方mod N

RSA的明文是对代表密文的数字 c 的 d 次方对 N 求余的结果

私钥:在已知密文的情况下,只要只要 D 和 N 这两个数,任何人都可以完成对解密的运算。所以说, D 和 N 是RSA解密的密钥,换句话说,D 和 N 的组合就是私钥,表示为私钥是(D,N)

生成密钥对
由上述分析可知,加解密的过程需要三个参数 E、D、N,那么这三个参数该怎么生成呢?

由于 E 和 N 是公钥,D 和 N 是私钥,求这三个数的过程就是生成密钥对

求N
首先准备两个很大的质数 P、Q。上述所说的算法安全性与大数分解有关,就体现在这了,我们反过来想,如果 p 和 q 选的很小,那对于 N 的求解将会变得非常简单,密码就容易被破译;但是物极必反,也不能选的太大,太大会使得计算时间大大延长。

准备好之后,N 由以下公式求得

P*Q=N

求φ
φ这个数在加密解密的过程中都不曾出现,它只出现在生成密钥对的过程中。由下列公式求得

φ=(P-1)*(Q-1)

求E
e 的求取基于上述的 φ 值。首先明确 e 的取值范围 1<e<φ,并且 gcd(φ,e)=1(φ 与 e 的最大公约数为1,即两者互质)。之所以要加上1这个条件,是为了保证一定存在解密时需要使用的参数 D

至此,我们生成了密钥对中的公钥

求D
d 的求取基于上述的 e 值和 φ 值。首先明确 d 的取值范围 1<d<φ,并且 gcd(φ,d)=1。d 的求解方式如下

e*d mod φ=1

由网站解密指数E = 65537

 模数N =(转为10进制) 86934482296048119190666062003494800588905656017203025617216654058378322103517

借用网址http://www.factordb.com/index.php?query=86934482296048119190666062003494800588905656017203025617216654058378322103517计算p和q

指路:http://t.csdnimg.cn/UCCMp

AES

http://t.csdnimg.cn/wyqbs

AES解密过程,解密过程仍为10轮,每一轮的操作是加密操作的逆操作。由于AES的4个轮操作都是可逆的,因此,解密操作的一轮就是顺序执行逆行移位、逆字节代换、轮密钥加和逆列混合。同加密操作类似,最后一轮不执行逆列混合,在第1轮解密之前,要执行1次密钥加操作。

1.字节代换操作

AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒。

2.行移位

1.行移位变换

行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节

2.行移位的逆变换

行移位的逆变换是将状态矩阵中的每一行执行相反的移位操作,例如AES-128中,状态矩阵的第0行右移0字节,第1行右移1字节,第2行右移2字节,第3行右移3字节

3.列混合操作

列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵

逆变换矩阵同正变换矩阵的乘积恰好为单位矩阵。

4.轮密钥加

轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作,如下图所示。其中,密钥Ki中每个字W[4i],W[4i+1],W[4i+2],W[4i+3]为32位比特字,包含4个字节,他们的生成算法下面在下面介绍。轮密钥加过程可以看成是字逐位异或的结果,也可以看成字节级别或者位级别的操作。也就是说,可以看成S0 S1 S2 S3 组成的32位字与W[4i]的异或运算。

/**
 * 参数 c: 密文的字符串数组。
 * 参数 clen: 密文的长度。
 * 参数 key: 密钥的字符串数组。
 */
void deAes(char *c, int clen, char *key) {

    int keylen = strlen(key);
    if(clen == 0 || clen % 16 != 0) {
        printf("密文字符长度必须为16的倍数!现在的长度为%d\n",clen);
        exit(0);
    }

    if(!checkKeyLen(keylen)) {
        printf("密钥字符长度错误!长度必须为16、24和32。当前长度为%d\n",keylen);
        exit(0);
    }

    extendKey(key);//扩展密钥
    int cArray[4][4];
    for(int k = 0; k < clen; k += 16) {
        convertToIntArray(c + k, cArray);


        addRoundKey(cArray, 10);

        int wArray[4][4];
        for(int i = 9; i >= 1; i--) {
            deSubBytes(cArray);

            deShiftRows(cArray);

            deMixColumns(cArray);
            getArrayFrom4W(i, wArray);
            deMixColumns(wArray);

            addRoundTowArray(cArray, wArray);
        }

        deSubBytes(cArray);

        deShiftRows(cArray);

        addRoundKey(cArray, 0);

        convertArrayToStr(cArray, c + k);

    }
}

学习

burp爆破

不太懂,感觉不太像逆向的内容

思路

有一个通过交叉引用发现另一个函数改变了码表

一些apk文件可以压缩文件打开找到lib找到so

再次复现

CrackRTF                        分析

2019红帽杯easyRE        分析

[ACTF新生赛2020]usualCrypt        base64变表分析

[HDCTF2019]Maze        花指令and汇编

[FlareOn4]IgniteMe        很怪

Youngter-drive                汇编,线程,堆栈一类的

[GWCTF 2019]xxor        浅浅研究一下

[FlareOn6]Overlong        脚本和动态调试(学习一下)

[ACTF新生赛2020]Oruga        迷宫问题(分析一下)

[ACTF新生赛2020]Universe_final_answer        学习z3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值