the cryptopals crypto challenges学习记录(一)
目录
前言
第一次手写base64解密和异或
简单介绍base64
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。
以给aa进行base编码为例:
aa的二进制为:01100001 01100001
分成6位一组:011000 010110 000100(最后两个是补上的0)
转为10进制:24 22 4
查表,转为base64,为:Y W E =(=是填充上的)
set1 challenge1
python实现(附带10进制转base64):
代码如下:
#16进制转base64 python
from enum import Enum
b64_encode = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
class abc(Enum):#定义一个类 包含3种情况
one = 0
two = 1#需要填充2bit
four = 2#需要填充4bit
def hex_to_base64(hexdata):
b64data = ""
sixbits = 0
ab = abc.one
for hexchar in hexdata:
dec = int(hexchar, 16)#把16进制字符转为对应的十进制字符
if ab == abc.one:
sixbits = dec
ab = abc.two
#如果是新的一组.将一个16进制字符的4位放入
#那么还需要两个bit进行填充.接着将ab设置为填充2位的情况
elif ab == abc.two:
sixbits = (sixbits << 2) | (dec >> 2)
b64data += b64_encode[sixbits]
sixbits = (dec & 0x3) #0x3 is 0x11
ab = abc.four
#如果需要填充2位,则填充后该组就完整了,就可以通过编码表进行对应编码了
#编码后将其附加到编码后字符串末尾.接着将ab设置为填充4位的情况
elif ab == abc.four:
sixbits = (sixbits << 4) | dec
b64data += b64_encode[sixbits]
ab = abc.one
#如果需要填充4位,则填充后该组就完整了,就可以通过编码表进行对应编码了
#编码后将其附加到编码后字符串末尾.接着将status设置为处理新一组的情况
if ab == abc.two:
sixbits <<= 2
b64data += b64_encode[sixbits]
b64data += "="
elif ab == abc.four:
sixbits <<= 4
b64data += b64_encode[sixbits]
b64data += "=="
return b64data
def main():
cc=hex_to_base64('49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d')
print(cc)
if __name__ == '__main__':
main()
#---------------------------------------------------------------
#10进制转base64
def base64(str):
ret = bytearray("",encoding="utf-8")# 定义一个bytearray 类型,可以修改的byte类型
length = len(str)
r = 0# 记录补 0 个数,之后会替换为 =
for x in range(0,length,3):
if x+3 <= length: #判断是否满足凑够三个字节,能凑够三个字节,则计算,不能凑够则补0
y = str[x:x+3]
else:
y = str[x:]
r = 3-len(y)# 计算补0的个数
y = y + "\x00"*r
a = int.from_bytes(y.encode(), "big") # 大端对齐
for i in range(18, -1, -6):
if i == 18:
index = a >> i # 6个bit,6个bit一起
else:
index = a >> i & 0x3f##0011 1111
ret.append(alphabet[index]) # 最佳Base64 编码
for i in range(1,r+1):
ret[-i] = 0x3D ##不够的部分补 =
return ret
if __name__ == "__main__":
alphabet = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
#base64编码表
str = input()
print(base64(str).decode("utf-8"))
输出结果:
C++实现
代码如下:
#include<bits/stdc++.h>
using namespace std;
struct twoandsixteen
{
int c[4];//二进制
char b;//对应十六进制字符
};
struct base64
{
int t[6];//6bit
int x;
char d;
};
struct bas64a
{
int p;//base64编码的值
char q;//base64编码值对应的字符
};
int main()
{
struct twoandsixteen sss[16]={
{{0,0,0,0},'0'},
{{0,0,0,1},'1'},
{{0,0,1,0},'2'},
{{0,0,1,1},'3'},
{{0,1,0,0},'4'},
{{0,1,0,1},'5'},
{{0,1,1,0},'6'},
{{0,1,1,1},'7'},
{{1,0,0,0},'8'},
{{1,0,0,1},'9'},
{{1,0,1,0},'a'},
{{1,0,1,1},'b'},
{{1,1,0,0},'c'},
{{1,1,0,1},'d'},
{{1,1,1,0},'e'},
{{1,1,1,1},'f'}
};
struct bas64a www[64]={
{0,'A'},{1,'B'},{2,'C'},{3,'D'},{4,'E'},{5,'F'},{6,'G'},{7,'H'},{8,'I'},{9,'J'},
{10,'K'},{11,'L'},{12,'M'},{13,'N'},{14,'O'},{15,'P'},{16,'Q'},{17,'R'},{18,'S'},{19,'T'},
{20,'U'},{21,'V'},{22,'W'},{23,'X'},{24,'Y'},{25,'Z'},{26,'a'},{27,'b'},{28,'c'},{29,'d'},
{30,'e'},{31,'f'},{32,'g'},{33,'h'},{34,'i'},{35,'j'},{36,'k'},{37,'l'},{38,'m'},{39,'n'},
{40,'o'},{41,'p'},{42,'q'},{43,'r'},{44,'s'},{45,'t'},{46,'u'},{47,'v'},{48,'w'},{49,'x'},
{50,'y'},{51,'z'},{52,'0'},{53,'1'},{54,'2'},{55,'3'},{56,'4'},{57,'5'},{58,'6'},{59,'7'},
{60,'8'},{61,'9'},{62,'+'},{63,'/'}
};
struct twoandsixteen a[10000];
int n=0;
while(a[n].b=getchar())//逐个输入要加密的字符并记录位数
{
if(a[n].b=='\n') break;
n=n+1;
}
for(int h=0;h<n;h++)//拷贝操作,将输入字符串对应的二进制拷贝入a[]中
{
for(int e=0;e<16;e++)
{
if(a[h].b==sss[e].b)
{
a[h].c[0]=sss[e].c[0];
a[h].c[1]=sss[e].c[1];
a[h].c[2]=sss[e].c[2];
a[h].c[3]=sss[e].c[3];
}
}
}
int w[4*n],z=0;
for(int h=0;h<4*n+4;h=h+4)//将a[]中数据拷贝到w[]中 可用函数处理
{
w[h]=a[z].c[0];
w[h+1]=a[z].c[1];
w[h+2]=a[z].c[2];
w[h+3]=a[z].c[3];
z=z+1;
}
struct base64 y[(4*n)/6];//6bit
int m=0;
for(int h=0;h<(4*n)/6;h++)//把w[]中的0,1进行划分,6个一组
{
int n1=0;
for(int e=m;e<m+6;e++)
{
y[h].t[n1]=w[e];
n1=n1+1;
}
m=m+6;
}
for(int h=0;h<(4*n)/6;h++)//把划分后的二进制转化位10进制
{
y[h].x=y[h].t[0]*32+y[h].t[1]*16+y[h].t[2]*8+y[h].t[3]*4+y[h].t[4]*2+y[h].t[5]*1;
}
for(int h=0;h<(4*n)/6;h++)//根据转化后的10进制找对应的base64编码
{
for(int e=0;e<64;e++)
{
if(y[h].x==www[e].p) y[h].d=www[e].q;
}
}
for(int h=0;h<(4*n)/6;h++)//将编码输出
{
cout<<y[h].d;
}
if(((4*n)%6)==2)//如果余数为2后边补0,补足6位
{
int k=w[4*n-2]*32+w[4*n-1]*16;
for(int e=0;e<64;e++)
{
if(k==www[e].p) cout<<www[e].q;
}
cout<<"=";
}
else if(((4*n)%6)==4)//如果余数为4后边补0,补足6位
{
int k=w[4*n-4]*32+w[4*n-3]*16+w[4*n-2]*8+w[4*n-1]*4;
for(int e=0;e<64;e++)
{
if(k==www[e].p) cout<<www[e].q;
}
cout<<"=";
}
cout<<endl;
//system("pause");
return 0;
}
介绍异或
异或:异或运算符”∧” 。参加运算的两个二进位同号,则结果为0(假);异号则为1(真)。即 0∧0=0,0∧1=1, 1^0=1,1∧1=0。
异或的运算:先转化为二进制,再对照位来进行运算,相同为0,不同为1。
通过按位异或运算,可以实现两个值的交换,而不必使用临时变量。例如交换两个整数a=3,b=4的值,可通过下列语句实现:
a=a∧b
b=b∧a
a=a∧b
set1 challenge2
python实现
def hex_xor (hexdata1, hexdata2):
a1 = int(hexdata1, 16)
a2 = int(hexdata2, 16)
xor1 = a1 ^ a2
return hex(xor1)[2:]
def main():
a = hex_xor("1c0111001f010100061a024b53535009181c686974207468652062756c6c277320657965")
print(a)
if __name__ == '__main__':
main()
结果: