CTF密码学基础知识整理
一. 常见编码转换
(1)整数转ascii码
- INT->CHAR:chr(97)
- CHAR->INT:ord('a')
(2)hex转ASCII
>>> import binascii
>>> binascii.a2b_hex('666c6167')
b'flag'
>>> binascii.b2a_hex(b'flag')
b'666c6167'
(3)bytes转str
# str to bytes
sb2 = str.encode(s)
# bytes to str
bs2 = bytes.decode(b)
hex和bytes转换
int(hexdata,16).to_bytes(32,'big')
hex(int.from_bytes(bytesdata,'big'))
十进制和bytes互换
from Crypto.Util.number import *
bytes_to_long(b'flag{test123456}')
#136143999223222844293191115896490636925
#这里是将bytes转为hex,然后将hex转为十进制
#等同于int(binascii.b2a_hex(b'flag{test123456}'),16)
long_to_bytes(136143999223222844293191115896490636925) #b'flag{test123456}'
#这里是将十进制转为hex,然后将hex转为bytes
#等同于binascii.a2b_hex(hex(136143999223222844293191115896490636925)[2:])
(4)base16编码 (0-9 A-F)
例如:666C61677B746869735F69735F6261736536347D
使用python的base64库编码解码(以下base64,32,85,以及ascii85都同理)
例如:
>>> from base64 import *
>>> s = b'flag{this_is_base64}'
>>> b16encode(s)
b'666C61677B746869735F69735F6261736536347D'
>>> b = '666C61677B746869735F69735F6261736536347D'
>>> b16decode(b)
b'flag{this_is_base64}'
(5)base32编码 (A-Z 2-7)(填充=)
例如:MZWGCZ33ORUGS427NFZV6YTBONSTMND5
使用base64库
(6)base36编码
大写字母和数字
使用python的base36库
(6)base58编码
用于比特币地址
相比Base64,去掉了数字"0",字母大写"O",字母大写"I",和字母小写"l",以及"+"和"/"符号。
使用python的base58库
(6)base62编码
相比base64,减少了+和/
使用python的pybase62库
pip install pybase62
import base62
(6)base64编码 (A-Z a-z 0-9 +/)(填充=)
base64用6位二进制表示64个字符(A-Z a-z 0-9 +/)
因此原始3个字节的数据可编码为4个字符
转换时,原始数据被先后放入一个3字节24位的缓冲区中。若原始字节数不能被3整除,则在末尾用0补足,直到字节数能被3整除,对应在base64编码后面添加1个或2个=号
base64解码时,按8位二进制一组解码,多余部分丢弃
例如:ZmxhZ3t0aGlzX2lzX2Jhc2U2NH0=
可在linux命令行直接编码或解码(base32也可以):
echo -n flag{123456} | base64 #-n是删除字符串后的换行符
echo ZmxhZ3sxMjM0NTZ9Cg== | base64 -d
(7)base85编码(包括@#`^等字符)
例如:W^7?+dvs`Nb6;t5Ut(c%Wi~W@
使用base64库
(8)base91编码
94个ASCII可打印字符(0x21-0x7E)中,删去
-(破折号,0x2D)
\(反斜杠,0x5C)
'(撇号,0x27)
使用python的base91库
在线编码解码:http://www.atoolbox.net/Tool.php?Id=935
(8)base92编码
使用python的base92库
在线编码解码:https://www.amanctf.com/tool/base92
(8)base100编码
表情包编码
在线编码/解码:http://www.atoolbox.net/Tool.php?Id=936
(8)ascii85编码(和base85类似,在Adobe PDF中常用)
例如:Ao(mgHZWq8F'iX&?XdGbAMuAn
(9)URL编码
只有字母和数字[0-9a-zA-Z]、一些特殊符号"$-_.+!*'(),"[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL,其他的都需要编码。
URL编码将其他字符表示为"%"+(ASCII码的十六进制值)的形式。
例如:%66%6c%61%67%7b%31%32%33%34%35%36%7d
很多软件如hackbar,burpsuite中可以url解码
(10)HTML编码
例如:flag{you are right}
使用html文件打开即可
(11)Unicode编码
Unicode是一本很厚的字典,记录着世界上所有字符对应的一个数字。
Unicode是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
UTF-8就是一种Unicode的实现方式。即UTF-8规定了二进制代码的存储方式。
Python中unicode是最基础的编码类型,所有字符串在python内部的表示都是unicode编码。在做编码转换时,也是先从一种编码转到unicode,再转到目标编码
python中给字符串加前缀u,即表示是一个unicode字符串,直接打印就会自动解码。
例如:
>>> s = u'\u0066\u006c\u0061\u0067\u007b\u0074\u0068\u0069\u0073\u005f\u0069\u0073\u005f\u0075\u006e\u0069\u0063\u006f\u0064\u0065\u007d'
>>> s
'flag{this_is_unicode}'
unicode有两种形式
\u574f\u5973\u4eba\u4e07\u5c81\uff01
坏女人万岁!
UTF-8编码
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用一至四个字节对Unicode字符集中的所有有效编码点进行编码,属于Unicode标准的一部分,
它可以用来表示Unicode标准中的任何字符,而且其编码中的第一个字节仍与ASCII相容,使得原来处理ASCII字符的软件无须或只进行少部份修改后,便可继续使用。
UTF-8编码字节含义:
- 对于UTF-8编码中的任意字节B,如果B的第一位为0,则B独立的表示一个字符(ASCII码);
- 如果B的第一位为1,第二位为0,则B为一个多字节字符中的一个字节(非ASCII字符);
- 如果B的前两位为1,第三位为0,则B为两个字节表示的字符中的第一个字节;
- 如果B的前三位为1,第四位为0,则B为三个字节表示的字符中的第一个字节;
- 如果B的前四位为1,第五位为0,则B为四个字节表示的字符中的第一个字节;
因此,对UTF-8编码中的任意字节,根据第一位,可判断是否为ASCII字符;根据前二位,可判断该字节是否为一个字符编码的第一个字节;根据前四位(如果前两位均为1),可确定该字节为字符编码的第一个字节,并且可判断对应的字符由几个字节表示;根据前五位(如果前四位为1),可判断编码是否有错误或数据传输过程中是否有错误。
(12)XXencode编码
与base64类似,不过XXencode使用的转换表是
+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
比base64多了"-"字符,少了"/"字符,且填充使用的是"+"(base64使用的是"=")。
例如:CNalVNrhMK4JiMqxYNLo+
在线编码解码:http://web.chacuo.net/charsetxxencode/
(13)UUencode编码
Unix-to-Unix encoding
与base64类似,将6位作为一组,编码为一个字符,不足用0填充。3个原始字节可以分为4组,每组用十进制表示大小在0-63中,加上32正好在ascii可打印字符范围内。
Uuencode编码将每60个字符输出为独立的一行(相当于45个原始字节),每行开头会加上长度字符,除最后一行外,长度字符都是M(77=32+45)。
例如:
M575E;F-O9&7EL(;HOI/EA:7FEH?EK9?DNZ7FKX_DN(GDN*KEK9?HBH+DN+KE
MC97DO8WHOYOHH8SGO);GH('OO(SEIH+FK:3IAXWEI(WHOYOHH8SC@(+EIH+F
MGISFG(#ED([EB:GDN(OGFH3FEH?EK9?EL)'DNH[DN(GDN*KEK9?HBH+OO(SD
MN(WEI)_GFH3I@ZCDN[WGE*CIF[;HH:7IO9#C@(+HOYGDN(GDN*KEK9?HBH+E
MA;'FG(DR-.2XJD)I=.^\C.2[I38M8FETY+BZY8V5Y+V-Y8B&Y+BZ-.2XJN>^
MI.>[A.^\C.:OC^2XJN>^I.>[A.2[I>6-@>B_F^6(MN:=I>BAJ.>DNN:)@.6'
MNN>.L.>:A.:5L.6`O.6/JN2\FNB0O>6<J##EB+`V,^2YB^F7M..`@N6PAN:O
MC^2XJN:5L.6*H.2XBC,R[[R,YHF`Y+JGYY2?YYJ$Y[N3YIZ<Y8B:Y:6]Z)"]
MY9RH05-#24GEK9?GK*;IFX;DN*WECZ_FB9/EC;#EK9?GK*;OO(@S,BWGJ;KG
CF;TN+BXY-2WENI7GNK_OO(GGFH3HC(/EF[3DN8ODN*WC@((`
可以使用python的binascii库,a2b_uu()解码,b2a_uu()编码
在线编码解码:http://web.chacuo.net/charsetuuencode
(14)AAencode编码
js代码混淆
例如:
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');
在浏览器控制台运行解码
或者 https://cat-in-136.github.io/2010/12/aadecode-decode-encoded-as-aaencode.html
(15)JSFuck
js代码混淆
(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[+[]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[(![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]]((+((+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+[+[]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+!+[]]])+[])[!+[]+!+[]]+[+!+[]])
浏览器控制台运行解码
或者 http://ctf.ssleye.com/jsfuck.html
(16)JJencode
js代码混淆
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"('"+$.__$+$._$_+$._$$+$.$__+$.$_$+$.$$_+"');"+"\"")())();
外壳是alert('');
整体格式是alert('加密内容');
如下
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"('"`加密内容`"');"+"\"")())();
在浏览器控制台运行解码
或者
http://ctf.ssleye.com/jjencode.html
(17)brain fuck
+++++ +[->+ +++++ <]>++ +++++ +++.. ...<+ ++[-> ---<] >---- -.<++ +[->+
++<]> +++++ ..... <+++[ ->--- <]>-- ---.< +++[- >+++< ]>+++ ++... ..<++
+[->- --<]> ----- .<+++ [->++ +<]>+ ++++. ....< +++[- >---< ]>--- --.+.
(18)Ook!
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
..... ..... ..... ..... !?!!. ?.... ..... ..... ..... .?.?! .?... .!...
..... ..... !.?.. ..... !?!!. ?!!!! !!?.? !.?!! !!!.. ..... ..... .!.?.
https://www.splitbrain.org/services/ook
(19)社会主义核心价值观
例如:
公正公正公正诚信文明公正民主公正法治法治诚信民主法治民主法治民主法治民主
在线解码:http://www.hiencode.com/cvencode.html
(20)与佛论禅
例如:
新佛曰:閦諸隸僧閦降吽閦諸閦陀摩隸僧缽閦薩閦願閦耨咤閦陀願羅閦嘇喃婆如所僧如念囑囑
在线解码:http://hi.pcmoe.net/index.html
(21)与熊论道
例如:
熊曰:呋食食噔擊雜擊嘿咯人和嘶啽更
在线解码:http://hi.pcmoe.net/index.html
三. 古典密码
(1)摩斯电码
例如:..-. .-.. .- --. ----.-- -- --- .-. ... . . -. -.-. --- -.. . -----.-
(2)猪圈密码
一种替代式密码
传统猪圈密码:
变种1:
变种2:
圣堂武士密码:
银河字母密码:
跳舞的小人:
(3)夏多密码
一种需要转动纸张的替代式密码
(4)键盘密码
根据键盘字母的二维坐标编码
(5)四方密码
四方密码用4个5*5的矩阵来加密,每个矩阵都有25个字母,一般是去掉q或者将i和j当作一样
例如:bgeafgrtqqqduo
在线加解密:http://ctf.ssleye.com/four.html
首先我们需要选择两个英文单词作为密钥,如example和keyword,将其中重复的字母去除,example就变成了“exampl”,然后将其顺序放入矩阵,再将密钥中没有用到的字母顺序放入余下矩阵。另外一个“keyword”也是如此。
然后将这两个矩阵放在右上角和左下角,而左上角和右下角则使用A到Z的顺序组成矩阵。将四个矩阵组合在一起,就形成了一个四方矩阵。
随后,我们就可以来加密信息了,将信息的两个字母一组分开,如hello world,分组后为“he ll ow or ld”。
- 找出第一个字母在左上角矩阵的位置;
- 找第二个字母在右下角矩阵的位置;
- 找右上角矩阵中,和第一个字母同行,第二个字母同列的字母;
- 找左下角矩阵中,和第一个字母同列,第二个字母同行的字母;
这样,这些字母在就组成了一个四方体,而在3、4步所得到的字母,就是我们需要的密文。
以此类推,我们的明文“he ll ow or ld”在经过加密之后,就变成了“FY GF HX HQ HK”。
(6)普莱费尔密码
用一个密钥形成的5*5的矩阵加密。
密钥矩阵的生成:先填写密钥单词(去除重复字母),然后按字母表顺序填充未出现的字母,一般将i和j看作一样。
将明文2个字母组成一对。若两字母相同,将X(或Q)插入两字母之间,重新分组(例如 HELLO 将分成 HE LX LO)。若剩下一个字,也加入X字。
对密钥矩阵:同行右移;同列下移;对角顺转,解密反向。
可以使用python的pycipher模块进行加解密
例如:
>>> from pycipher import Playfair
>>> Playfair(key='zgptfoihmuwdrcnykeqaxvsbl').encipher('flag{playfair}')
'UFKFFSYKULHD'
>>> Playfair(key='zgptfoihmuwdrcnykeqaxvsbl').decipher('UFKFFSYKULHD')
'FLAGPLAYFAIR'
(7)维吉尼亚密码
是一种使用26*26字母表进行坐标式加密的移位密码,为克服频率分析法,相当于凯撒移位的改良型。
方法1:计算
密钥 k= (k1k2k3…km), m≤26, 循环使用;
加密算法:Ci= Pi + Ki mod 26;
解密算法:Pi= Ci - Ki mod 26。
方法2:查表
将凯撒密码的全部25种位移排序为一张表,与原字母序列共同组成26行及26列的字母表。
加密时以明文字母选择列,以密钥字母选择行,交点是生成的密文字母。
解密时以密钥字母选择行,从这行中找到密文字母,其所在列即为明文字母。
可以使用python的pycipher模块进行加解密
例如:
>>> from pycipher import Vigenere
>>> Vigenere('HELLO').encipher('flag{vegenere}')
'MPLRJLKPYSYI'
>>> Vigenere('HELLO').decipher('MPLRJLKPYSYI')
'FLAGVEGENERE'
密钥重复部分和明文重复部分,会在密文中产生重复部分。密文中多个重复部分的间隔,密钥长度就在其公因数中。
(8)格罗斯费尔德密码
格罗斯费尔德密码本质上是一个维吉尼亚密码,但使用数字而不是字母作为密钥
可以使用python的pycipher模块进行加解密
例如:
>>> from pycipher import Gronsfeld
>>> Gronsfeld([1,2,3,4]).encipher('flaggronsfeld')
'GNDKHTRRTHHPE'
>>> Gronsfeld([1,2,3,4]).decipher('GNDKHTRRTHHPE')
'FLAGGRONSFELD'
(9)自动密钥密码
与维吉尼亚密码类似,区别在于密钥不同,它的密钥开头是一个关键词,之后则是明文的重复。
可以使用python的pycipher模块进行加解密
例如:
>>> from pycipher import Autokey
>>> Autokey('HELLO').encipher('flagautokey')
'MPLROZEOQES'
>>> Autokey('HELLO').decipher('MPLROZEOQES')
'FLAGAUTOKEY'
(10)博福特密码
与维吉尼亚密码类似,属于对等加密,即加密算法与解密算法相同
可以使用python的pycipher模块进行加解密
例如:
>>> from pycipher import Beaufort
>>> Beaufort('HELLO').encipher('flagbeaufort')
'CTLFNDERGAQL'
>>> Beaufort('HELLO').decipher('CTLFNDERGAQL')
'FLAGBEAUFORT'
(11)ADFGX密码
使用ADFGX作为5*5方格的坐标,将每个密文字母替换为坐标,再使用密钥进行移位加密
可以使用python的pycipher模块进行加解密
例如:
>>> from pycipher import ADFGX
>>> ADFGX('phqgmeaylnofdxkrcvszwbuti','HELLO').encipher('flagadfgx')
'DAFFFDFGDGFGGDDDDA'
>>> ADFGX('phqgmeaylnofdxkrcvszwbuti','HELLO').decipher('DAFFFDFGDGFGGDDDDA')
'FLAGADFGX'
(12)ADFGVX密码
与ADFGX密码相同,只是多了一个坐标,成为6*6的方格,使得数字可用
可以使用python的pycipher模块进行加解密
例如:
>>> ADFGVX('ph0qg64mea1yl2nofdxkr3cvs5zw7bj9uti8','HELLO').encipher('flagadfgvx')
'VAXGFGFVFVFXADVGDGAA'
>>> ADFGVX('ph0qg64mea1yl2nofdxkr3cvs5zw7bj9uti8','HELLO').decipher('VAXGFGFVFVFXADVGDGAA')
'FLAGADFGVX'
(13)双密码
使用一个5*5的字母表方格进行加解密,通常省略j,按照行和列的坐标组合加密
可以使用python的pycipher模块进行加解密
例如:
>>> from pycipher import Bifid
>>> Bifid('phqgmeaylnofdxkrcvszwbuti',5).encipher('flagbifid')
'FEBCCUUBU'
>>> Bifid('phqgmeaylnofdxkrcvszwbuti',5).decipher('FEBCCUUBU')
'FLAGBIFID'
(14)埃特巴什码
字母表最后一个字母对应第一个字母,倒数第二个字母对应第二个字母
明文: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
密文:Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
(15)希尔密码
希尔密码是运用基本矩阵论原理的替换密码,使用一个m*m的矩阵作为密钥,此矩阵必须可逆,解密使用逆矩阵解密。
方阵的行列式非零(mod 26),且行列式与26互素,则方阵可逆。
方阵的秩等于它的阶数,则方阵可逆。明文分成长度为 m 的向量
密文向量=密钥矩阵*明文向量 (mod 26)
明文矩阵=密钥矩阵逆矩阵*密文向量 (mod 26)
具体参见另一篇博文:网络与系统安全 - 课程笔记
例如:eeuexpxde.zifxdc
在线加解密:https://aliyunvi.com/hill
(16)仿射密码
仿射密码是一种单表代换密码。它是利用加密函数一个字母对一个字母的加密。
它的加密函数是E(x)= (ax + b) (mod m),其中,a和m互质,m是字母的数量(26即是以26个字母作为编码)
解密函数为D(x) = a-1(x - b) (mod m),其中a-1是a在Zm群的乘法逆元
例如:IHHWVCSWFRCP
在线加解密:https://aliyunvi.com/affine
移位密码没有破坏统计规律,因此可以用字母频率分析进行破解。
英文字母频率:
[0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025,0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150,0.01974, 0.00074]
两个字母:
th, he, in, er, re, on, an, en
三个字母:
the, and, tio, ati, for, tha, ter, res
(17)二进制幂数密码
由于英文字母只有26个字母。只要2的0、1、2、3、4、5次幂就可以表示31个单元。通过用二进制幂数表示字母序号数来加密。
如o,字母序号15=20+21+22+23,密文为0123
例如:
明文: d o n o t p u l l
字母序号:4 15 14 15 20 16 21 12 12
由于4=2^2 所以d加密过之后是2; 15=2^0+2^1+2^2+2^3 所以o加密后是0123
密文:2 0123/123 0123 24/4 024 23 23
其中空格表示字母的间隔,/表示单词的间隔
(18)01248密码
又称为云影密码,使用 0,1,2,4,8 四个数字,其中 0 用来表示间隔
其他数字以加法可以表示出 如:28=10,124=7,18=9,以此表示字母序号数
例如:
密文:8842101220480224404014224202480122
明文:WELLDONE
(19)栅栏密码
以列(行)优先写出明文,以行(列)优先读出各字母作为密文。
传统栅栏密码的密钥是密文长度的因数
如密文长度为n,加密密钥为x,有n%x==0,且解密密钥为n/x
可看成按一定的步长取几组字符,再将这几组字符连起来得到密文,这里的步长就是密钥。解密同理。
加解密代码参见另一篇博文:栅栏密码&W型栅栏密码-加解密(python实现)
例如:
密文:KYsd3js2E{a2jda}
明文:KEY{sad23jjdsa2}
W型栅栏密码
w型栅栏密码的密钥不只是密文长度的因数,任何小于密文长度大于1的整数都有可能。
将明文按w型排列,然后将每一行的字母依次连起来组成密文,行数就是密钥。
例如:
密文:ccehgyaefnpeoobe{lcirg}epriec_ora_g
明文:cyberpeace{railfence_cipher_gogogo}
(20)培根密码
明文中的每个字母都会转换成一组五个英文字母
A/a aaaaa H/h aabbb O/o abbba V/v babab
B/b aaaab I/i abaaa P/p abbbb W/w babba
C/c aaaba J/j abaab Q/q baaaa X/x babbb
D/d aaabb K/k ababa R/r baaab Y/y bbaaa
E/e aabaa L/l ababb S/s baaba Z/z bbaab
F/f aabab M/m abbaa T/t baabb
G/g aabba N/n abbab U/u babaa
(21)转轮机密码
转轮机加密
源顺序不变,根据密钥将第一行放至第二行,第二行放至第三行
密文对应的是每行的第一列,因此将每行向左转,就像转轮一样
例如:
1: < ZWAXJGDLUBVIQHKYPNTCRMOSFE <
2: < KPBELNACZDTRXMJQOYHGVSFUWI <
3: < BDMAIZVRNSJUWFHTEQGYXPLOCK <
4: < RPLNDVHGFCUKTEBSXQYIZMJWAO <
5: < IHFRLABEUOTSGJVDKCPMNZQWXY <
6: < AMKGHIWPNYCJBFZDRUSLOQXVET <
7: < GWTHSPYBXIZULVKMRAFDCEONJQ <
8: < NOZUTWDCVRJLXKISEFAPMYGHBQ <
9: < XPLTDSRFHENYVUBMCQWAOIKZGJ <
10: < UDNAJFBOWTGVRSCZQKELMXYIHP <
11: < MNBVCXZQWERTPOIUYALSKDJFHG <
12: < LVNCMXZPQOWEIURYTASBKJDFHG <
13: < JZQAWSXCDERFVBGTYHNUMKILOP <
密钥为:2,3,7,5,13,12,9,1,8,10,4,11,6
密文为:NFQKSEVOQOFNP
(22)ROT13
ROT13是一种简易的替换式密码。
加密与解密算法相同
c = (p + 13)%26
例如:
密文:MzkuM3gvMUAwnzuvn3cgozMlMTuvqzAenJchMUAeqzWenzEmLJW9
明文:ZmxhZ3tiZHNjamhia3ptbmZyZGhidmNraWpuZHNrdmJramRzYWJ9
(23)费斯妥密码
费斯妥密码(英语:Feistel cipher)是用于构造分组密码的对称结构,以德国出生的物理学家和密码学家霍斯特·费斯妥(Horst Feistel)命名,他在美国IBM工作期间完成了此项开拓性研究。
通常也称为费斯妥网络(Feistel network)。大部分分组密码使用该方案,包括数据加密标准(DES)。费斯妥结构的优点在于加密和解密操作非常相似,在某些情况下甚至是相同的,只需要逆转密钥编排。因此,实现这种密码所需的代码或电路大小能几乎减半。参考自维基百科-费斯妥密码
费斯妥网络是一种迭代密码,其中的内部函数称为轮函数。
Michael Luby和Charles Rackoff分析了Feistel密码的构造,证明了如果轮函数是一个密码安全的伪随机函数,使用Ki作为种子,那么3轮足以使这种分组密码成为伪随机置换,而4轮可使它成为“强”伪随机置换。
令F为轮函数,并令\(K_0,K_1,...,K_n\)分别为轮0,1,...,n的子密钥。
基本操作如下:
将明文块拆分为两个等长的块(\(L_0,R_0\)),对每轮i = 0,1,...,n,计算
则密文为(\(R_{n+1},L_{n+1}\))。
解密密文(\(R_{n+1},L_{n+1}\)),通过计算i = n,n-1,...,0
则(\(L_0,R_0\))就是明文。
与代换-置换网络相比,Feistel模型的一个优点是轮函数F不必是可逆的。
下图显示了加密和解密的过程。注意解密时子密钥顺序反转,这是加密和解密之间的唯一区别。
四. 近代密码
1. DES
DES(Data Encryption Standard)是一种对称分组加密算法.
以8字节64位为一组对明文进行划分,加密时按组进行,不足8字节的组会自动填充。它所使用的密钥也是64位,但只有56位参与DES运算(第8、16、24、32、40、48、56、64位,即每个字节的第八位是校验位,使得每个密钥都有奇数个1)
DES把64位的明文输入块变为64位的密文输出块
3DES是使用2条56位的密钥对数据进行三次加密。是DES的一个更安全的变形。加密的过程是加密-解密-加密,解密的过程是解密-加密-解密。
分组加密算法在实际加密时会配合各种加密模式使用(ECB,CBC,CFB,OFB)
在线加解密:http://tool.chacuo.net/cryptdes
2. AES
AES(Advanced Encryption Standard)也是一种对称分组加密算法,是DES的升级版。
AES明文分组长度为16字节128位,密钥长度可以为128位,192位和256位。密钥长度不同推荐加密轮数不同,AES-128是10轮,AES-192是12轮,AES-256是14轮。
AES将16个字节的明文分组作为4*4的矩阵,称为状态矩阵。在算法的每一轮中,状态矩阵的内容不断发生变化,最后的结果作为密文输出。
128位的密钥也是作为一个4*4的矩阵,每一列称为一个32位字,通过密钥编排函数该密钥矩阵被扩展成一个44个字组成的序列,前4个字是原始密钥,后40个字分为10组,每组4个字分别用于10轮加密运算中。
加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。在第一轮迭代前,先将明文矩阵与原始密钥进行一次轮密钥加。
- 字节代换:其实就是一个简单的查表操作,AES定义了一个S盒和一个逆S盒。把一个字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。-
- 行移位:一个简单的左循环移位操作,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节。-
- 列混合:通过矩阵相乘来实现的,将状态矩阵与一个固定的矩阵相乘。(x-time运算)
- 轮密钥加:将4个字16字节的轮密钥与状态矩阵进行逐位异或操作。
详细参见:密码算法设计与分析 - 课程笔记
在线加解密:http://tool.chacuo.net/cryptaes
分组加密模式介绍
ECB(电码本方式),按照顺序将各组计算所得的数据连在一起即可,各段数据之间互不影响。
ECB模式存在的安全问题:如果使用相同的密钥,那么相同的明文块就会生成相同的密文块,不能很好的隐藏数据模式。例如下面的图:
CBC(密文分组链接方式),加密的各段数据之间有了联系,需要使用一个初始化向量IV,长度与分组长度相等。CBC模式是最常用的操作模式。
IV与第一段明文分组异或后再加密得到第一段密文分组,然后第一段密文分组在与第二段明文分组异或后再加密得到第二段密文分组,以此类推。
CBC模式的特点:
- 加密过程是串行的,不能并行化,速度比较慢。
- 解密可以并行。
- 使用不正确的IV解密导致第一个明文块被破坏,但后来的明文块将是正确的。
CFB(密文反馈模式),CFB模式使块密码成为自同步流密码
(密钥流依赖于输入的明文字符)。明文可以不进行填充(最后的明文块与最后的密钥流块的前几位异或)。
CFB模式中引入了一个数据段
的概念,分为明文段和密文段,数据段的长度为s位。当分块大小为b位时,有\(1\leq s\leq b\)。CFB模式使用s位作为单次输出的长度,s的值有时包含在模式的名称中,如1位 CFB 模式、8 位 CFB 模式、64 位 CFB 模式或 128 位 CFB 模式。
加密过程中明文与一个密钥流进行按位异或操作, 生成密文。首先将初始化向量IV放入移位寄存器,移位寄存器使用密钥加密后得到加密结果O1,将O1的前s位与s位明文p1异或,得到s位的密文输出c1。然后移位寄存器左移s位,将前面的密文c1放入移位寄存器的后s位中。以此类推。
CFB的解密跟加密过程几乎完全相同,注意它在解密过程中使用的是AES加密而不是AES解密。
OFB(输出反馈模式),OFB模式使块密码成为同步流密码
(密钥流独立于输入的明文字符)。使用分组密码算法作为密钥流产生器,生成密钥流块,然后将其与明文块进行异或运算以获得密文。
明文可以不进行填充。当最后的明文分组长度小于128位时,截取AES加密输出的前对应位数进行异或。例如最后一个明文分组是32位,而AES加密输出是128位,则截取前32位进行异或。
由于异或运算的对称性,加密和解密是完全一样的。
CTR(计数器模式),CTR模式是一种通过将逐次累加的计数器进行加密来生成密钥流的同步流密码
。明文可以不进行填充(最后的明文块与最后的密钥流块的前几位异或)。CTR模式与CBC模式一样,是经常使用的操作模式。
计数器由两部分组成,前一部分是Nonce,这部分相当于其他模式中的IV值;第二部分是一个累加值Counter,这部分的初始值是全零或者一段随机序列。
由于异或运算的对称性,加密和解密是完全一样的。
CTR模式的特点:
- 加密和解密都可以并行处理
- 不需要实现解密算法
- 随机访问性质,可以只解密其中一块密文。
比较
填充方式
AES的密钥长度可以是128、192和256位,不足需要进行填充。
AES的分组长度是128位,对于流密码操作模式(如CFB, OFB, CTR)不需要进行填充;对于块密码操作模式,最后一块分组长度不足128位(16字节)时需要进行填充,满足也需要进行填充(这样可以确定最后一个字节是填充字节)。
明文数据长度是128位(16字节)的整数倍时,如果不进行填充,则解密算法无法判断最后一个字节是明文字节还是填充字节。因此需要再附加上16个填充字节(一块分组)。
填充方式主要有NoPadding, ZerosPadding,PKCS#5, PKCS#7, ISO 10126, ANSI X9.23等。
NoPadding: 不填充
ZerosPadding: 全部填充0x00
例如:
... | DD DD DD DD DD DD DD DD | DD DD DD DD 00 00 00 00 |
PKCS#5和PKCS#7: 每个增加的字节值是增加的字节数。
例如:
... | DD DD DD DD DD DD DD DD | DD DD DD DD 04 04 04 04 |
PKCS#5 填充与 PKCS#7 填充相同,只是它仅为使用 64 位(8 字节)块大小的块密码定义。在实践中,两者可以互换使用。
ISO 10126: 最后一个字节是填充的字节数(包括最后一字节),其他全部填随机数。
例如:
... | DD DD DD DD DD DD DD DD | DD DD DD DD 81 A6 23 04 |
ANSI X9.23: 与ISO 10126类似,不过ANSI X9.23其他字节填的是0而不是随机数。
例如:
... | DD DD DD DD DD DD DD DD | DD DD DD DD 00 00 00 04 |
不同算法在不同模式下,数据加密后的长度:
算法/模式/填充 | 16字节加密后数据长度 | 不满16字节加密后长度 |
---|---|---|
AES/ECB/NoPadding | 16 | 不支持 |
AES/ECB/PKCS5Padding | 32 | 16 |
AES/ECB/ISO10126Padding | 32 | 16 |
AES/CBC/NoPadding | 16 | 不支持 |
AES/CBC/PKCS5Padding | 32 | 16 |
AES/CBC/ISO10126Padding | 32 | 16 |
AES/CFB/NoPadding | 16 | 原始数据长度 |
AES/CFB/PKCS5Padding | 32 | 16 |
AES/CFB/ISO10126Padding | 32 | 16 |
AES/OFB/NoPadding | 16 | 原始数据长度 |
AES/OFB/PKCS5Padding | 32 | 16 |
AES/OFB/ISO10126Padding | 32 | 16 |
(1)padding oracle attack
Padding Oracle Attack是针对CBC链接模式的攻击,和具体的加密算法无关
由于CBC模式的解密过程,第n组密文解密后的中间值与前一组的密文异或便可得到明文,现在我们不知道解密的密钥key,但我们知道所有的密文,因此只要我们能够得到中间值便可以得到正确的明文(进行一次异或运算便可)
而中间值是由服务器解密得到的,因此我们虽然不知道怎么解密但我们可以利用服务器帮我们解密,我们所要做的是能确定我们得到的中间值是正确的,这也是padding oracle attack的核心——找出正确的中间值。
当密文不能正常解密时,服务器返回值与正常解密不同。而服务器判断提交的密文是否能正常解密的方法,就是判断密文最后一组解密得到明文的填充值是否正确。(DES默认填充方式采用PKCS5,最大填充八字节,AES默认PKCS7,最大填充16字节,填充值等于填充字节数,比如会填充2个0x02)
可以假设填充了一个字节,即最后一个字节是0x01。构造倒数第二组密文的前七个字节都为0x00,最后一字节从0×00到0xff逐个赋值并逐个向服务器提交,直到服务返回值表示构造后的密文可以正常解密。
此时可以得知构造的倒数第二组密文的最后一个字节,和最后一组密文的最后一个字节的中间值异或的结果是0x01。根据异或运算的性质,将0x01与构造所得的最后一个字节异或就得到最后一组密文最后一个字节的中间值,设为M1。
然后继续求解最后一组密文倒数第二个字节的中间值,假设填充了两个字节,则最后两个字节是0x02。构造倒数第二组密文的前六个字节都是0x00,由前面可知最后一组最后一个字节的中间值M1,则将M1与0x02异或即可得到倒数第二组最后一个字节的值应该填什么,然后将倒数第二个字节从0×00到0xff逐个赋值并逐个向服务器提交,直到正常解密。同之前方法可得到最后一组倒数第二个字节的中间值。
以此类推得到最后一组密文的中间值,和倒数第二组的密文异或即可得到最后一组明文。
然后可以丢弃最后一组密文,只提交前面几组密文,同理依次可得每一组的明文。
详细参见:https://www.freebuf.com/articles/database/151167.html
实现脚本:https://www.cnblogs.com/ntestoc/p/11044433.html
(2)Stream Cipher Reuse Attack
流密码密钥重用攻击(Reused key attack)
对于CTR模式等流密码,如果重用密钥和IV进行加密,就有可能受到密钥重用攻击。
例如CTR模式中,加密过程是先对计数器使用密钥加密后,再与明文分组进行异或。
假设计数器加密结果是C,加密函数是E(),明文A和B。
则有:
E(A) = A xor C
E(B) = B xor C
但是异或运算是可交换的,所以有:
E(A) xor E(B) = (A xor C) xor (B xor C) = A xor B xor C xor C = A xor B xor 0 = A xor B
于是当攻击者获取到A或B其中一个明文时,就可以计算出另一个明文。
例如:
B = E(A) xor E(B) xor A
(3)Crib Drag
一次性密码(One-time Pad——OTP)是一种非常安全的加密方法。它实现起来非常简单,并且只要密钥的长度大于或等于消息的长度就非常安全,但是它要求密钥永远不会被使用超过一次。
假设明文M和密钥K,则密文C=M xor K,明文M=C xor K。
但是如果重复使用了密钥K,就会存在安全隐患。
Crib Drag就是针对这种情况的攻击。
假设bob使用密钥K对不同的明文M1和M2进行加密,得到C1和C2。则有
C1 xor C2 = M1 xor M2
cipher1 = msg1 ^ key
cipher2 = msg2 ^ key
cipher1 ^ cipher2 = (msg1 ^ key) ^ (msg2 ^ key)
cipher1 ^ cipher2 = msg1 ^ msg2 ^ key ^ key
cipher1 ^ cipher2 = msg1 ^ msg2 ^ 0
cipher1 ^ cipher2 = msg1 ^ msg2
Crib Drag的思想是首先猜出明文M1或者M2中使用的单词或句子,作为假设的明文片段M',然后找出异或密文C1^C2中每一组和M'等长的字符串C'(可以使用滑动窗口的方法),将M'和C'异或,看看是否有可读明文出现,从而揭示原始消息的部分内容。
其原理是根据异或运算的以下性质,如果假设的明文片段M'在M1中的话,那么异或得到的值应该是M2中对应位置的明文。
A ^ B = C
C ^ B = A
C ^ A = B
参考资料:
https://samwho.dev/blog/toying-with-cryptography-crib-dragging/
http://travisdazell.blogspot.com/2012/11/many-time-pad-attack-crib-drag.html
3. RSA
取两个大素数p,q
N = p*q
φ = (p-1)*(q-1)
取公钥e,1<e<φ,且e与φ互质
取私钥d,e * d ≡ 1 (mod φ) // ed互为关于模数phi的逆元
则公钥(N,e),私钥(N,d)
或公钥(e,N)加密:c = pow(m, e, N);解密:m = pow(c, d, N)
功能:加解密(密钥管理),数字签名,消息认证
大素数分解
在线分解:http://www.factordb.com/index.php?query=391
yafu:https://sourceforge.net/projects/yafu
常见攻击方法
1.对RSA的公共模数攻击
2.RSA小指数e攻击
3.RSA选择密文攻击
4.Fermat方法与Pollard rho方法
5.低加密指数攻击
6.低解密指数攻击
7.低加密指数广播攻击
8.Coppersmith定理攻击
详细参见:https://blog.csdn.net/huanghelouzi/article/details/82943615
自动化脚本:RsaCtfTool 可以自动尝试每种攻击方法进行攻击
地址:https://github.com/Ganapati/RsaCtfTool
签名
签名需要先对明文进行哈希,再对哈希值签名。
sig = hash(msg)^d mod n
如果直接对明文签名,会受到签名伪造攻击。
C1 = m1^d mod N
C2 = m2^d mod N
C1*C2 = (m1*m2)^d mod N = M^d mod N
攻击者可以伪造出明文m1*m2和签名C1*C2
混合加密
交换密钥的环节使用非对称加密,之后的通信使用对称加密。
使用对称加密算法对明文加密,使用非对称加密算法的公钥加密对称加密算法的密钥。
发送明文加密结果和密钥加密结果。
例如数字信封。
4. ECC
椭圆曲线加密,基于椭圆曲线上的离散对数问题
sage可以直接计算椭圆曲线加法和椭圆曲线乘法
椭圆曲线Ep(a,b)(p为模数),基点(生成元)G(x,y),G点的阶数n,私钥k,公钥K(x,y),随机整数r,明文为一点m(x,y),密文为两点c1(x,y)和c2(x,y)
(其中基点G,明文m,密文c1、c2都是椭圆曲线E上的点)
选择私钥k(k<n)
得到公钥K = k*G
选择随机整数r(r<n)
加密:
c1 = m+r*K
c2 = r*G
解密:
m = c1-k*c2(= c1-r*K)
椭圆曲线运算:
#点u(x,y),整数a,点v(x,y),点w(x,y)
a_inv = inverse_mod(a,fn) #(a_inv是a的乘法逆元)
v = a*u
u = v*a_inv
w = u+v
椭圆曲线参考:https://www.cnblogs.com/Kalafinaian/p/7392505.html
5. RC4
RC4(也称为 Rivest Cipher 4)是流密码的一种形式,它通过算法一次一个字节地加密消息,简单并且操作速度快。属于对称加密算法。
6. LCG
线性同余发生器(Linear congruential generator),简称LCG,是一种能产生具有不连续计算的伪随机序列的分段线性方程的算法,它代表了最古老和最知名的伪随机序列生成器算法之一。
作为流密码(stream cipher)中常用的伪随机数发生器(pseudo random number generator),其随机性能取决于参数和种子的选择。
递推公式:
- \(S\) 代表伪随机序列
- \(m,\quad(0<m)\) 表示模数
- \(a,\quad (0<a<m)\) 表示乘数
- \(b,\quad\) 表示增量
- \(S_0,\quad(0 \leq S_0<m)\) 表示初始值
求a的公式:
求b的公式:
推导过程:
阶数
\(a\) 与 \(n\) 互素, 使得
成立的最小正整数 \(x\) 称为 \(a\) 模 \(n\) 的阶, 记为 \(\operatorname{ordn}(a)\) 。
原根
如果有
称 \(a\) 为模 \(n\) 的原根
若 \(\operatorname{gcd}(a, m)=1\), 则周期 \(T=\operatorname{ordm}(a)\), 所以选取系数时应尽量使得 \(a\) 为模 \(m\) 的原根, 以此尽量延长LCG周期。
7. 其他
DSA
GGH
RSA-OAEP
五. 密码学应用
1. Hash
(1)md5
MD5哈希值是128位、16字节。
md5将无限大的明文空间,映射到大小为2^128的密文空间中。因此是多对一的关系。存在碰撞的可能。
使用hashlib求hash值,包括md5,sha256等等
>>> import hashlib
>>> h = hashlib.md5()
>>> s = '123456'
>>> h.update(s.encode())
>>> h.hexdigest()
'c4e9e3b367d7f33d5843f3c402d10252'
2. MAC
消息认证码(Message authentication code),是一种基于密钥作完整性校验的方法。通常MAC在共享密钥的双方之间,校验相互传递的信息。
使用场景为:假设通信双方 A 和 B 共享密钥 K,A用消息认证码算法将 K 和消息 M 计算出消息验证码 Mac,然后将 Mac 和 M 一起发送给 B。B 接收到 Mac 和 M 后,利用 M 和 K 计算出新的验证码 Mac*,若 Mac*和Mac 相等则验证成功,证明消息未被篡改。由于攻击者没有密钥 K,攻击者修改了消息内容后无法计算出相应的消息验证码,因此 B 就能够发现消息完整性遭到破坏。
消息认证码(MAC),在加密的过程中有两种方法,一种是用单向散列函数的实现,另一种是分组密码的实现。
(1)单向散列函数的实现
MAC函数用单项hash函数加密时,MAC被称为HMAC(Hash Message Authentication Code).
HMAC(k,m) = H((k opad ) + H( (k XORipad ) + m ) )
3. HKDF
HMAC-based KDF(key derivation function),基于HMAC的密钥推导函数
HKDF 是基于 HMAC(Hashed Message Authentication Code)的密钥派生函数(key derivation function)。它可以从一些 initial keying material派生出密码学意义上强度高的密钥。
HKDF 通常有以下几个重要输入:
- 作为输入的 keying material
- 可选的 salt, 但是使用 salt 可以明显增强 HKDF 的强度
- 可选的 info,用于指示一些信息
- Hash 函数的 mode,支持md5/sha1/sha224/sha256/sha384/sha512
输出密钥的字节长度最大值与内部使用的 Hash 函数有关,为 255 * Hash 函数输出字节长度。例如对于 sha256,输出密钥的字节长度最长为 255 * 32
HKDF包含两个基本模块,或者说两个基本使用步骤:1. 提取 Extract, 2. 扩展 Expand。
(1)提取
所谓提取就是将用户输入的密钥尽量的伪随机化。一般是使用一个哈希函数来实现,具体那种更具需要在HMAC中确定。这一过程可以表示如下:
HKDF-Extract(salt, IKM) -> PRK
这其中有2个输入和1个输出
- Salt,输入,加盐操作的盐,如果不提供则全部初始化为0的字符串,长度则为所采用哈希函数的散列值长度
- IKM,输入,原始密钥材料IKM(input keying material)
- PRK,输出,伪随机化后的密钥,长度则为所采用哈希函数的散列值长度
(2)扩展
所谓扩展,其实就是通过一系列的哈希运算将密钥扩展到我们需要的长度。这个长度我们记为L。这一过程表示如下:
HKDF-Expand(PRK, info, L) -> OKM,
其中有3个输入量和1个输出量,其中:
- PRK,输入,一般是在提取阶段得到的输出,是一个伪随机的密钥,长度不小于所采用的哈希算法的输出摘要长度
- Info,输入,可选上下文和应用程序特定信息(可以是零长度字符串)
- L,输入,以字节计算的密钥原料的长度,一般不长于哈希函数输出摘要长度的255倍
- OKM,输出,长度为L的密钥材料输出。
4. 隐私计算
隐私计算(Privacy compute 或Privacy computing)是在保护数据本身不对外泄露的前提下实现数据分析计算的技术集合,达到对数据“可用、不可见”的目的。
目前在对数据隐私的保护方面,隐私计算技术的应用主要可以分为安全多方计算,可信硬件,联邦学习三个主要流派。
- 安全多方计算(MPC):安全多方计算(Secure Multi-party Computation, MPC)是一种密码学领域的隐私保护分布式计算技术。安全多方计算能够使多方在互相不知晓对方内容的情况下,参与协同计算,最终产生有价值的分析内容。
- 秘密共享
- 混淆电路
- 同态加密(HE)
- 隐私信息检索(PIR)
- 零知识证明
- 可信执行环境(TEE):可信任执行环境(Trusted Execution Environment, TEE)指的是一个隔离的安全执行环境。其实现原理在于通过软硬件方法, 在中央处理器中,构建出一个安全区域,计算过程执行代码仅在安全区域分界中执行,外部攻击者无法通过常规手段获取和影响安全区的执行代码和逻辑。
- 联邦学习(FL):联邦学习(Federated Learning, FL)又名联邦机器学习、联合学习。相比于使用中心化方式的传统机器学习,联邦学习实现了在本地原始数据不出库的情况下,通过对中间加密数据的流通和处理,来完成多方联合的学习训练。
- 图联邦
- 其他:
- 差分隐私(DP)
- 不经意传输(OT)
- K匿名算法
- 同态承诺
- L-多样性
参考资料:
https://www.zhihu.com/question/437273004
https://blog.51cto.com/kymdidicom/5322126
https://www.zhihu.com/question/437273004
https://36kr.com/p/727146931849347
六. 工具
(1)RsaCtfTool
例如:
#根据n和e生成公钥文件
python3 RsaCtfTool.py --createpub -n 24493816160588971749455534346389861269947121809901305744877671102517333076424951483888863597563544011725032585417200878377314372325231470164799594965293350352923195632229495874587039720317200655351788887974047948082357232348155828924230567816817425104960545706688263839042183224681231800805037117758927837949941052360649778743187012198508745207332696876463490071925421229447425456903529626946628855874075846839745388326224970202749994059533831664092151570836853681204646481502222112116971464211748086292930029540995987019610460396057955900244074999111267618452967579699626655472948383601391620012180211885979095636919 -e 3683191938452247871641914583009119792552938079110383367782698429399084083048335018186915282465581498846777124014232879019914546010406868697694661244001972931366227108140590201194336470785929194895915077935083045957890179080332615291089360169761324533970721460473221959270664692795701362942487885620152952927112838769014944652059440137350285198702402612151501564899791870051001152984815689187374906618917967106000628810361686645504356294175173529719443860140795170776862320812544438211122891112138748710073230404456268507750721647637959502454394140328030018450883598342764577147457231373121223878829298942493059211583 > public.key
#根据公钥文件尝试各种攻击方法,得到私钥文件
python3 RsaCtfTool.py --publickey ../public.key --private
#由私钥文件列出各个参数
python3 RsaCtfTool.py --key private.key --dump
(3)sagemath
docker运行
docker pull sagemath/sagemath
docker run -it sagemath/sagemath:latest
sage镜像里是内置了jupyter notebook的,可以通过如下命令在网页段打开jupyter来使用。
docker run -p8888:8888 sagemath/sagemath:latest sage-jupyter
基本用法
# 解方程
var('x y')
solve([x+y==10,x*y==21],[x,y])
#求逆元
inverse_mod(e,fn)
#大数分解
factor(123456789)
#判断质数
is_prime(3803)
使用sage进行ecc处理
#取椭圆曲线E上随机一点
E.random_point()
#由x坐标取椭圆曲线E上一点
E.lift_x(126322)
#加密
p = 29
a = 4
b = 20
E = EllipticCurve(GF(p),[a,b]) #建立椭圆曲线E
G = E[13,23] #生成元G
n = G.order() #G的阶数
k = 25
K = k*G #(14,6)
r = 6
m = E(3,28) #取E上一点m
c1 = m+r*K #(6,12)
c2 = r*G #(5,7)
#解密
m = c1-k*c2
计算椭圆曲线上的离散对数问题(数据量不能太大)
a = 1234577
b = 3213242
p = 7654319
E = EllipticCurve(GF(p),[a,b])
G = E(5234568, 2287747) #生成元
#k = 1584718
K = E(2366653, 1424308) #公钥
#求解私钥,自动选择bsgs或Pohlig Hellman算法
discrete_log(K,G,operation='+')
#求解私钥,Pollard rho算法
discrete_log_rho(K,G,operation='+')
#求解私钥,Pollard Lambda算法,能够确定所求值在某一小范围时效率较高
discrete_log_lambda(K,G,(1500000,2000000),operation='+')
(4)Crypto.PublicKey.ECC
python的Crypto库
from Crypto.PublicKey import ECC
例如:
#生成ECC密钥
key = ECC.generate(curve='NIST P-256')
#公钥(point_x,point_y是基点G的坐标)
key.public_key()
#椭圆曲线
key.curve
#私钥k
key.d
#导出为pem密钥文件
key.export_key(format='PEM')
#导入密钥文件
key = ECC.import_key(f.read())
(5)词频分析
(6)ciphey
在不知道密钥或密码的情况下自动解密加密、解码编码并破解哈希值。
ciphey -t "KYYVUV3BGFMXSVCYNRKGCMTIKFKWY2CPKRCU43SQKQYEWCQ="
七. 其他
(1)椭圆曲线
#NIST P-256(Secp256r1)
#p = 2^224(2^32 − 1) + 2^192 + 2^96 − 1
p = 115792089210356248762697446949407573530086143415290314195533631308867097853951
a = -3
b = 41058363725152142129326129780047268409114441015993725554835256314039467401291
#Secp256k1(比特币使用)
#p = 2^256 − 2^32 − 2^9 − 2^8 − 2^7 − 2^6 − 2^4 − 1 = 2^256 – 2^32 – 977
p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
a = 0
b = 7
#NIST P-384
#p = 2^384 – 2^128 – 2^96 + 2^32 – 1
p = 39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319
a = -3
b = 27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764883745107765439761230575
#NIST P-521
p = 6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151
a = -3
b = 1093849038073734274511112390766805569936207598951683748994586394495953116150735016013708737573759623248592132296706313309438452531591012912142327488478985984
通过fastecdsa.Curve可以查到公开椭圆曲线的参数
import fastecdsa.curve as curve
#P-384的a
curve.P384.a
#P-384的b
curve.P384.b
#P-384的p
curve.P384.p
(2)证书
证书标准
x.509 定义了证书应该包含哪些内容
文件拓展名
证书(Certificate) - *.cer *.crt
私钥(Private Key) - *.key
证书签名请求(Certificate signing request) - *.csr
证书吊销列表(Certificate Revocation List) - *.crl
可能是pem也可能是der编码方式
pem和der是编码方式
*.pem - base64编码
以"-----BEGIN..."开头, "-----END..."结尾,内容是BASE64编码
查看PEM格式证书的信息:
openssl x509 -in certificate.pem -text -noout
*.der - 二进制编码
打开是二进制格式,不可读.
查看DER格式证书的信息:
openssl x509 -in certificate.der -inform der -text -noout
证书编码的转换
PEM转为DER openssl x509 -in cert.crt -outform der -out cert.der
DER转为PEM openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
(3) 全同态加密
对于一个加密函数f,
如果f(A)+f(B) = f(A+B),则称该函数加法同态,
如果f(A)×f(B) = f(A×B),则称该函数乘法同态,
如果一个函数同时满足加法同态和乘法同态,则称为全同态加密。
(4)符号
||
:串 和 级联
例 a=0x1234 , b=0x5678 , c=a||b=0x12345678 .
(5)密钥空间
密钥空间是指加密密钥大小的范围。
通常以位为单位,即以位的多少来对独特密钥进行计数。密钥的位越长,其密钥空间也就越大。
当密钥长度为r时,密钥空间有2的r次方个元素。例如8位密钥的密钥空间是00000000-11111111,就是0-2^8。
然而所有密码算法都由密钥来维持安全,密钥大,破解难度就大,所以现实生活中,密钥是一个极大的二进制数,以保证安全。
例如8位密钥,暴力破解穷举就能把正确的密钥尝试出来。
(6)欧拉函数
欧拉函数\(φ(m)\),用于计算小于正整数m且与这个m互素的正整数的个数。
比如m = 8,则小于8且与8互素的正整数有:1,3,5,7,共4个。若m = 9,则小于9且与9互素的正整数有:1,2,4,5,7,8,共6个。
欧拉函数的计算方法,首先将m分解为素数幂的乘积的形式。
如m=60时,\(60 = 2 * 30 = 2 * 2 * 15 = 2^2 * 3 * 5\)(这里的素数要求互不相同,遇到相同的写成幂的形式)
则\(φ(60) = (2^2 - 2^1) * (3^1 - 3^0) * (5^1 - 5^0) = 2 * 2 * 4 = 16\)
当m=26时,\(26 = 2 * 13\)
则\(φ(26) = (2 - 1) * (13 - 1) = 12\)(1代表的是他们的0次方)
当m=8时,8 = \(2^3\),则\(φ(8) = 2^3-2^2 = 8 - 4 = 4\)
当m=9时,9 = \(3^2\),则\(φ(9) = 3^2-3^1 = 6\)