引言:这里是我做的攻防世界-crypto-基础题的一些writeup,希望能够大家一些参考,部分解题思路借鉴了其他博主,如果哪些地方有问题或更好的思路,可以一起探讨。 所用环境以及做题思路只在当时写下writeup时适用,若之后做出改动可与我联系,做出相应更改。 转载请标明出处 Crypto-基础题 1.base64
题目: Y3liZXJwZWFjZXtXZWxjb21lX3RvX25ld19Xb3JsZCF9
分析:
代码语言:javascript复制base64 应该是编码,算不上加密。 翻了 Misc 的 Wiki,笔记在 Crypt 分区里。由于base64编码后的字符除了英文字母和数字外还有三个字符 , /, =, 其中=只是为了补全编码后的字符数为4的整数,而 和/在一些情况下需要被替换的, b64encode和b64decode正是提供了这样的功能。 和/需要被替换,最常见的就是对 url 进行 base64 编码的时候。所以最常用的是 b64encode, b64decode,当然某些情况用 encodestring, decodestring 也没有大碍。
解题: 用工具直接破解/网页在线破解/Python代码实现
2.Caesar 题目: oknqdbqmoq{kag_tmhq_xqmdzqp_omqemd_qzodkbfuaz} 分析:
代码语言:javascript复制1、打开题目
2、凯撒密码解密即可。脑补一下凯撒密码的原理(简单移位即可)。恺撒密码(英语:Caesar cipher),或称恺撒加密、恺撒变换、变换加密,是一种最简单且最广为人知的加密技术。它是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。这个加密方法是以罗马共和时期恺撒的名字命名的,当年恺撒曾用此方法与其将军们进行联系。
解题: 用工具直接破解/网页在线破解/Python代码实现
3.Morse 题目: 11 111 010 000 0 1010 111 100 0 00 000 000 111 00 10 1 0 010 0 000 1 00 10 110 分析:
代码语言:javascript复制摩斯密码使用 .、- 来表示不同含义,这里只用 0和1,所以应该是用01代替.、-。 那么到底是用1代表.还是用0代表.呢? 都试一下不久好了……
代码语言:javascript复制用·表示0,-表示0
11 111 010 000 0 1010 111 100 0 00 000 000 111 00 10 1 0 010 0 000 1 00 10 110
m o r s e c o d e i s s o i n t e r e s t i n g
-> morsecodeissointeresting
cyberpeace{morsecodeissointeresting}
解题:
用工具直接破解/网页在线破解/Python代码实现 4.幂数加密
题目: 8842101220480224404014224202480122 分析:
代码语言:javascript复制 *提示(flag为cyberpeace{你解答出的八位大写字母})
因为提示是八位大写字母,又发现有7个0,所以我们可以猜想分成8段
a=["88421","0122","048","02244","04","0142242","0248","0122"]
flag=""
for j in range(0,len(a)):
str = a[j]
list=[]
sum=0
for i in str:
list.append(i)
length = len(list)
for i in range(0,length):
sum =int(list[i])
flag =chr(64 sum)
print flag
云影密码(01248码)
这种加密方式仅使用01248这5种数字来进行,其中0用来唯一表示间隔,其他数字用加法和表示替换密文。再使用数字1~26表示字母A~Z。
如:18 = 1 8 = 9 = I,1248 = 1 2 4 8 = 15 = O
特点:密文中仅存在01248,加密对象仅有字母
例:CRYPTO001
88421 0122 048 02244 04 0142242 0248 0122
23 5 12 12 4 15 14 5
W E L L D O N E
可知falg为WELLDONE
解题: 用工具直接破解/网页在线破解/Python代码实现
5.Railfence(栅栏密码)
题目: ccehgyaefnpeoobe{lcirg}epriec_ora_g 分析:
代码语言:javascript复制这个不是普通的栅栏密码!栅栏密码的变种WWW型
传统型
假如有一个字符串:123456789
取字符串长度的因数进行分组,假如key=3
1 2 3 \分组情况,每三个数字一组,分为三组
4 5 6
7 8 9
然后每一组依次取一个数字组成一个新字符串:147258369 \加密完成的字符串
WWW型
同样一个字符串:123456789
key=3
1----5----9 \让数字以W型组织,同样是三组,但每组的数量不一定相同
-2--4-6--8
--3----7--
加密密文:159246837
解题: 用工具直接破解/网页在线破解/Python代码实现/纸质解题破译
6.不仅仅是Morse 题目:
代码语言:javascript复制--/.-/-.--/..--.-/-..././..--.-/..../.-/...-/./..--.-/.-/-./---/-/...././.-./..--.-/-.././-.-./---/-.././..../..../..../..../.-/.-/.-/.-/.-/-.../.-/.-/-.../-.../-.../.-/.-/-.../-.../.-/.-/.-/.-/.-/.-/.-/.-/-.../.-/.-/-.../.-/-.../.-/.-/.-/.-/.-/.-/.-/-.../-.../.-/-.../.-/.-/.-/-.../-.../.-/.-/.-/-.../-.../.-/.-/-.../.-/.-/.-/.-/-.../.-/-.../.-/.-/-.../.-/.-/.-/-.../-.../.-/-.../.-/.-/.-/-.../.-/.-/.-/-.../.-/.-/-.../.-/-.../-.../.-/.-/-.../-.../-.../.-/-.../.-/.-/.-/-.../.-/-.../.-/-.../-.../.-/.-/.-/-.../-.../.-/-.../.-/.-/.-/-.../.-/.-/-.../.-/.-/-.../.-/.-/.-/.-/-.../-.../.-/-.../-.../.-/.-/-.../-.../.-/.-/-.../.-/.-/-.../.-/.-/.-/-.../.-/.-/-.../.-/.-/-.../.-/.-/-.../.-/-.../.-/.-/-.../-.../.-/-.../.-/.-/.-/.-/-.../-.../.-/-.../.-/.-/-.../-.../.-
分析:
代码语言:javascript复制是摩斯密码的形式,先对摩斯密码解码。 工具:http://www.zhongguosou.com/zonghe/moErSiCodeConverter.aspx (这个网站对摩斯代码的分隔方式支持单斜杠和空格,比较好) 返回结果:
MAYBEHAVEANOTHERDECODEHHHHAAAAABAABBBAABBAAAAAAAABAABABAAAAAAABBABAAABBAAABBAABAAAABABAABAAABBABAAABAAABAABABBAABBBABAAABABABBAAABBABAAABAABAABAAAABBABBAABBAABAABAAABAABAABAABABAABBABAAAABBABAABBA
Maybe have another decode ...... 它的意思应该不是让你从头开始换另一个,而是对摩斯密码解析出来的再用一个的方式解密。 此刻应该关注后面的A和B很有特征的是,它只有两个字符组成,这是培根密码的典型特征。(手抓饼,A套餐,B套餐)
解题: 用工具直接破解/网页在线破解/Python代码实现
7.混合编码 题目:
代码语言:javascript复制c7JiM4NDsmIzY1OyYjNTI7JiM3NjsmIzEyMjsmIzEwNzsmIzUzOyYjNzY7JiMxMjI7JiM2OTsmIzEyMDsmIzc3OyYjODM7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiMxMDc7JiMxMTg7JiM3NzsmIzg0OyYjNjU7JiMxMjA7JiM3NjsmIzEyMjsmIzY5OyYjMTIwOyYjNzg7JiMxMDU7JiM1NjsmIzEyMDsmIzc3OyYjODQ7JiM2OTsmIzExODsmIzc5OyYjODQ7JiM5OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzUwOyYjNzY7JiMxMjI7JiM2OTsmIzEyMDsmIzc4OyYjMTA1OyYjNTY7JiM1MzsmIzc4OyYjMTIxOyYjNTY7JiM1MzsmIzc5OyYjODM7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiM5OTsmIzExODsmIzc5OyYjODQ7JiM5OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzExOTsmIzc2OyYjMTIyOyYjNjk7JiMxMTk7JiM3NzsmIzY3OyYjNTY7JiMxMjA7JiM3NzsmIzY4OyYjNjU7JiMxMTg7JiM3NzsmIzg0OyYjNjU7JiMxMjA7JiM3NjsmIzEyMjsmIzY5OyYjMTE5OyYjNzc7JiMxMDU7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiM2OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzExOTsmIzc2OyYjMTIyOyYjMTA3OyYjNTM7JiM3NjsmIzEyMjsmIzY5OyYjMTE5OyYjNzc7JiM4MzsmIzU2OyYjMTIwOyYjNzc7JiM4NDsmIzEwNzsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzEyMDsmIzc2OyYjMTIyOyYjNjk7JiMxMjA7JiM3ODsmIzY3OyYjNTY7JiMxMjA7JiM3NzsmIzY4OyYjMTAzOyYjMTE4OyYjNzc7JiM4NDsmIzY1OyYjMTE5Ow==
分析: 题目中给出了flag格式:cyberpeace{小写的你解出的答案},以==结尾,应该是base家族。用base64解码,得到的类似于Unicode,再用Unicode解码,再用base64,得到了类似于ASKII码的类型,用ASKII解码得到答案。
解题:
代码语言:javascript复制1.base64->text
LzExOS8xMDEvMTA4Lzk5LzExMS8xMDkvMTAxLzExNi8xMTEvOTcvMTE2LzExNi85Ny85OS8xMDcvOTcvMTEwLzEwMC8xMDAvMTAxLzEwMi8xMDEvMTEwLzk5LzEwMS8xMTkvMTExLzExNC8xMDgvMTAw
2.unicode
LzExOS8xMDEvMTA4Lzk5LzExMS8xMDkvMTAxLzExNi8xMTEvOTcvMTE2LzExNi85Ny85OS8xMDcvOTcvMTEwLzEwMC8xMDAvMTAxLzEwMi8xMDEvMTEwLzk5LzEwMS8xMTkvMTExLzExNC8xMDgvMTAw
3.再次base64
/119/101/108/99/111/109/101/116/111/97/116/116/97/99/107/97/110/100/100/101/102/101/110/99/101/119/111/114/108/100
4.再次unicode
welcometoattackanddefenceworld
8.easy_RSA 题目:
代码语言:javascript复制在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17
求解出d
分析:
代码语言:javascript复制RSA算法中,d,e,p,q的关系如下:
d=e^-1 mod (p-1)(q-1)
现已知p,q,e,可用扩展欧几里得算法进行求逆运算,解出d即可。
解题:
代码语言:javascript复制#!/usr/bin/python
# -*- coding=utf -*-
def exgcd(a, n):
if n == 0:
return 1, 0
else:
x, y = exgcd(n, a % n)
x, y = y, x - (a // n) * y
return x, y
def getReverse(a, n):
re, y = exgcd(a, n)
while(re < 0):
re = n
return re
if __name__ == "__main__":
p = 473398607161
q = 4511491
e = 17
d = getReverse(e, (p - 1)*(q - 1))
print('d = ' str(d))
输出:d = 125631357777427553
或者:
import gmpy2
p = 473398607161
q = 4511491
e = 17
phi = (p -1) * (q -1)
d = gmpy2.invert(e, phi)
print(d)
9.easychallenge 分析:
代码语言:javascript复制附件是一个python的.pyc文件,大致可以理解为python程序编译得到后的文件。可以下载uncompyle库后使用uncompyle6将easychallenge.pyc反编译成py文件。
pyc介绍
Python 在解释源程序时分为两步:
第一步:将源码转为字节码
第二步:将字节码转换为机器码
pyc 文件是由 Python 解释器将 模块的源码 转换为 字节码。
(pyc,py代表pychon,c 是 compiled的含义,pyc即编译过的python文件 )
当我们的程序没有修改过,那么下次运行程序的时候,就可以跳过 从源码到字节码 的过程,直接加载 pyc 文件。
编辑解密脚本运行程序即可得到flag
解题:
代码语言:javascript复制反编译命令 uncompyle6 crypto11.pyc
或使用在线网址反编译:http://tools.bugscaner.com/decompyle/
解密脚本:
#!/usr/bin/env python
# encoding: utf-8
import base64
'''
a = 'UC7KOWVXWVNKNIC2XCXKHKK2W5NLBKNOUOSK3LNNVWW3E==='
b = base64.b32decode(a)
'''
# 先将字符串base32解码出来,然后将其变为字符串再进行ord等操作。
b = "xa0xbexa7Zxb7xb5Zxa6xa0Zxb8xaexa3xa9Zxb7Zxb0xa9xaexa3xa4xadxadxadxadxadxb2"
s = ''
for i in b:
s = chr((ord(i) ^ 36) - 36)
l = ''
for i in s:
l = chr((ord(i) - 25) ^ 36)
print ('flag is ',l)
或:
在mima.pyc所在文件夹位置打开cmder,输入命令
uncompyle6 -o . mima.pyc 成功反编译为mima.py文件
这里二话没说,先运行了一下,之后编译器提示错误,一共有两个,第一个是print’correct’报错,第二个是flag=raw_input()报错继续百度,发现这两处错误都是由于python2和python3版本不兼容造成的
将print’correct’改为print(‘correct’),将flag=raw_input()改为flag = eval(input())就行了然后运行发现是需要输入一个flag值,经过运算之后,输出correct或者wrong。将print’correct’改为print(‘correct’),将flag=raw_input()改为flag = eval(input())就行了然后运行发现是需要输入一个flag值,经过运算之后,输出correct或者wrong再回过头去仔细看代码发现代码结构很简单,就是要求用户输入一个flag值,然后依次通过三个函数进行加密,其中encode1和encode2是做异或和加和运算,encode3是调用base64库里的b32encode()函数进行base32运算。然后将结果与代码给定的final值进行比较(这里根据final结尾的三个”=”以及均为数字和大写字母的结构也能看出是进行了base32加密),如果相等输出correct,如果不相等,输出wrong。
所以,出题者的意思就很明显了,也就是让我们根据这个加密运算过程,写出逆过程,将final值作为输入进函数的值,然后以与之前相反的顺序调用函数,最后输出的值就是flag。
将print’correct’改为print(‘correct’),将flag=raw_input()改为flag = eval(input())就行了然后运行发现是需要输入一个flag值,经过运算之后,输出correct或者wrong再回过头去仔细看代码发现代码结构很简单,就是要求用户输入一个flag值,然后依次通过三个函数进行加密,其中encode1和encode2是做异或和加和运算,encode3是调用base64库里的b32encode()函数进行base32运算。然后将结果与代码给定的final值进行比较(这里根据final结尾的三个”=”以及均为数字和大写字母的结构也能看出是进行了base32加密),如果相等输出correct,如果不相等,输出wrong。所以,出题者的意思就很明显了,也就是让我们根据这个加密运算过程,写出逆过程,将final值作为输入进函数的值,然后以与之前相反的顺序调用函数,最后输出的值就是flag接下来,就修改了原始代码,首先是进入函数的顺序改成先进函数3再进2最后进1。然后就是每个函数内部运算, 变-,-变 ,异或运算的逆过程就是再做一次异或,所以不用变,base64.b32encode()改成base64.32decode()。然后把return之前的语句颠倒一下顺序,最后的拍到第一个,以此类推。需要注意的是,还要按照代码逻辑,把i和x给相互换一下,不然会报错。
最后代码如下:
importbase64
defencode1(ans):
s=‘'
for I in ans:
x=ord(i)-25
x=x^36
s =chr(x)
return s
defencode2(ans):
s=‘'
for I in ans:
x=ord(i)^36
x=x-36
s =chr(x)
return s
defencode3(ans):
returnbase64.b32decode(ans)
final='UC7KOWVXWVNKNIC2XCXKHKK2W5NLBKNOUOSK3LNNVWW3E===‘
flag=‘'
flag=encode1(encode2(encode3(final)))
print("flag={}".format(flag))
flag=''flag=encode1(encode2(encode3(final)))print("flag={}".format(flag))兴奋的去运行程序,结果编译器又报错PS D:NoteCTF> python -u "d:NoteCTFdemo.py"Traceback (most recent call last):File "d:NoteCTFdemo.py", line 29, in <module>flag = encode1(encode2(encode3(final)))File "d:NoteCTFdemo.py", line 16, in encode2x = ord(i) ^ 36TypeError: ord() expected string of length 1, but int found
错误提示是ord()函数想要一个长度为1的str类型,但是现在是int类型之后经过一番周折,发现是base64.32decode()的问题,它的返回类型是types,而这里ord()是想要一个str型的数据,于是又百度知道可以用decode()函数进行类型转换,于是将encode3(final)改为encode3(final).decode()
运行程序,还是报错,错误提示是PS D:NoteCTF> python -u "d:NoteCTFdemo.py"Traceback (most recent call last):File "d:NoteCTFdemo.py", line 29, in <module>flag = encode1(encode2(encode3(final).decode()))UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 0: invalid start byte也就是变成了UTF-8编码不能解码的问题
继续百度,发现decode()函数默认使用UTF-8编码,于 是 , 改成encode3(final).decode(‘unicode’)和encode3(final).decode(‘gbk’),发现还是一样的错误最后,在stackoverflow上找到了解决方案,就是用'ISO-8859-1'编码,具体原因还不清楚,以后再研究。。。。于是改成encode3(final).decode('ISO-8859-1')之后,程序顺利运行,得到flag
10.转轮机加密 题目:
代码语言:javascript复制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
分析:
代码语言:javascript复制提示:托马斯·杰斐逊。 flag,是字符串,小写。
参看:传统密码学(三)——转轮密码机 是个多表替换密码。 基本操作是“旋转”,其余的和本题是没有关系。
加密表和密钥、密文的特点
加密表每一行都有 26 个不同的字母,密钥的长度、密文长度、表格的行数都是 13,密文中字母是有重复字母的。
解题:
代码语言:javascript复制首先将每一行按照密钥顺序重新排列,如第二行应至于第一行的位置,以此类推。
2: < KPBELNACZDTRXMJQOYHGVSFUWI <
3: < BDMAIZVRNSJUWFHTEQGYXPLOCK <
7: < GWTHSPYBXIZULVKMRAFDCEONJQ <
5: < IHFRLABEUOTSGJVDKCPMNZQWXY <
13: < JZQAWSXCDERFVBGTYHNUMKILOP <
12: < LVNCMXZPQOWEIURYTASBKJDFHG <
9: < XPLTDSRFHENYVUBMCQWAOIKZGJ <
1: < ZWAXJGDLUBVIQHKYPNTCRMOSFE <
8: < NOZUTWDCVRJLXKISEFAPMYGHBQ <
10: < UDNAJFBOWTGVRSCZQKELMXYIHP <
4: < RPLNDVHGFCUKTEBSXQYIZMJWAO <
11: < MNBVCXZQWERTPOIUYALSKDJFHG <
6: < AMKGHIWPNYCJBFZDRUSLOQXVET <
密钥为:2,3,7,5,13,12,9,1,8,10,4,11,6
密文为:NFQKSEVOQOFNP
1. 密文为:NFQKSEVOQOFNP
然后按照密文,将每一行进行循环移位,使得其首位字母与对应的密文相同。
最后就是瞎眼时间,找到通顺的一列明文:fireinthehole
< NACZDTRXMJQOYHGVS F UWIKPBEL <
< FHTEQGYXPLOCKBDMA I ZVRNSJUW <
< QGWTHSPYBXIZULVKM R AFDCEONJ <
< KCPMNZQWXYIHFRLAB E UOTSGJVD <
< SXCDERFVBGTYHNUMK I LOPJZQAW <
< EIURYTASBKJDFHGLV N CMXZPQOW <
< VUBMCQWAOIKZGJXPL T DSRFHENY <
< OSFEZWAXJGDLUBVIQ H KYPNTCRM <
< QNOZUTWDCVRJLXKIS E FAPMYGHB <
< OWTGVRSCZQKELMXYI H PUDNAJFB <
< FCUKTEBSXQYIZMJWA O RPLNDVHG <
< NBVCXZQWERTPOIUYA L SKDJFHGM <
< PNYCJBFZDRUSLOQXV E TAMKGHIW <
密文为:NFQKSEVOQOFNP
Python代码实现:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import re
sss = '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 <'
m = 'NFQKSEVOQOFNP'
# 将sss转化为列表形式
content=re.findall(r'< (.*?) <',sss,re.S)
# re.S:DOTALL,此模式下,"."的匹配不受限制,可匹配任何字符,包括换行符
iv=[2,3,7,5,13,12,9,1,8,10,4,11,6]
print(content)
vvv=[]
for i in range(13):
index=content[iv[i]-1].index(m[i])
vvv.append(index)
print(vvv)
for i in range(0,26):
flag=""
for j in range(13):
flag = content[iv[j]-1][(vvv[j] i)&]
print(flag.lower())
11.Normal_RSA 分析:
代码语言:javascript复制OpenSSL 使用 PEM 文件格式存储证书和密钥。PEM 实质上是 Base64 编码的二进制内容,再加上开始和结束行,如证书文件的
-----BEGIN CERTIFICATE-----
和
-----END CERTIFICATE-----
在这些标记外面可以有额外的信息,如编码内容的文字表示。文件是 ASCII 的,可以用任何文本编辑程序打开它们。
①使用openssl解密.pem中参数-->②参数十六进制转换为十进制-->③利用factor对大整数进行分解,得到p和q -->④用rsatool生成私钥文件: private.pem-->⑤用private.pem解密flag.enc
解题:
代码语言:javascript复制本题主要考察工具的使用,附件共2个文件,flag.enc与pubkey.pem
OpenSSL (开放式安全套接层协议)使用 PEM 文件格式存储证书和密钥。PEM 实质上是 Base64 编码的二进制内容,再加上开始和结束行。
kali,自带openssl
第一步,提取pem文件信息
openssl rsa -pubin -text -modulus -in warmup -in pubkey.pem
得到大素数乘积n,此处为16进制,使用工具转换为10进制
Modulus=C2636AE5C3D8E43FFB97AB09028F1AAC6C0BF6CD3D70EBCA281BFFE97FBE30DD
代码语言:javascript复制对素数乘积n进行分解,解出素数q、p。大数分解
分解网址:http://www.factordb.com/
n=87924348264132406875276140514499937145050893665602592992418171647042491658461
275127860351348928173285174381581152299
319576316814478949870590164193048041239
现已知大素数p、q,取随机素数e,使用rsatool生成私钥文件
python rsatool.py -o private.pem -e 65537 -p 275127860351348928173285174381581152299 -q 319576316814478949870590164193048041239
代码语言:javascript复制用生成出的私钥文件解密flag
openssl rsautl -decrypt -in flag.enc -inkey private.pem
12.easy_ECC 题目:
代码语言:javascript复制已知椭圆曲线加密Ep(a,b)参数为
p = 15424654874903
a = 16546484
b = 4548674875
G(6478678675,5636379357093)
私钥为
k = 546768
求公钥K(x,y)
分析:
代码语言:javascript复制flag格式为cyberpeace{x y的值}
椭圆加密算法(ECC)是一种公钥加密体制,最初由Koblitz和Miller两人于1985年提出,其数学基础是利用椭圆曲线上的有理点构成Abel加法群上椭圆离散对数的计算困难性。公钥密码体制根据其所依据的难题一般分为三类:大素数分解问题类、离散对数问题类、椭圆曲线类。有时也把椭圆曲线类归为离散对数类。
ECC椭圆曲线加密学习笔记:https://bbs.pediy.com/thread-253672.htm
椭圆曲线的奇妙比喻:https://blog.csdn.net/dianqu6970/article/details/76534222
SCDN博主代码参考:
import collections
def inverse_mod(k, p):
"""Returns the inverse of k modulo p.
This function returns the only integer x such that (x * k) % p == 1.
k must be non-zero and p must be a prime.
"""
if k == 0:
raise ZeroDivisionError('division by zero')
if k < 0:
# k ** -1 = p - (-k) ** -1 (mod p)
return p - inverse_mod(-k, p)
# Extended Euclidean algorithm.
s, old_s = 0, 1
t, old_t = 1, 0
r, old_r = p, k
while r != 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
old_t, t = t, old_t - quotient * t
gcd, x, y = old_r, old_s, old_t
assert gcd == 1
assert (k * x) % p == 1
return x % p
# Functions that work on curve points #########################################
def is_on_curve(point):
"""Returns True if the given point lies on the elliptic curve."""
if point is None:
# None represents the point at infinity.
return True
x, y = point
return (y * y - x * x * x - curve.a * x - curve.b) % curve.p == 0
def point_neg(point):
"""Returns -point."""
assert is_on_curve(point)
if point is None:
# -0 = 0
return None
x, y = point
result = (x, -y % curve.p)
assert is_on_curve(result)
return result
def point_add(point1, point2):
"""Returns the result of point1 point2 according to the group law."""
assert is_on_curve(point1)
assert is_on_curve(point2)
if point1 is None:
# 0 point2 = point2
return point2
if point2 is None:
# point1 0 = point1
return point1
x1, y1 = point1
x2, y2 = point2
if x1 == x2 and y1 != y2:
# point1 (-point1) = 0
return None
if x1 == x2:
# This is the case point1 == point2.
m = (3 * x1 * x1 curve.a) * inverse_mod(2 * y1, curve.p)
else:
# This is the case point1 != point2.
m = (y1 - y2) * inverse_mod(x1 - x2, curve.p)
x3 = m * m - x1 - x2
y3 = y1 m * (x3 - x1)
result = (x3 % curve.p,
-y3 % curve.p)
assert is_on_curve(result)
return result
def scalar_mult(k, point):
"""Returns k * point computed using the double and point_add algorithm."""
assert is_on_curve(point)
if k < 0:
# k * point = -k * (-point)
return scalar_mult(-k, point_neg(point))
result = None
addend = point
while k:
if k & 1:
# Add.
result = point_add(result, addend)
# Double.
addend = point_add(addend, addend)
k >>= 1
assert is_on_curve(result)
return result
# Keypair generation and ECDHE ################################################
def make_keypair():
"""Generates a random private-public key pair."""
private_key = curve.n
public_key = scalar_mult(private_key, curve.g)
return private_key, public_key
EllipticCurve = collections.namedtuple('EllipticCurve', 'name p a b g n h')
curve = EllipticCurve(
'secp256k1',
# Field characteristic.
p=15424654874903,
# Curve coefficients.
a=16546484,
b=4548674875,
# Base point.
g=(6478678675,5636379357093),
# Subgroup order.
n=546768,
# Subgroup cofactor.
h=1,
)
private_key, public_key = make_keypair()
print("private key:", hex(private_key))
print("public key: (0x{:x}, 0x{:x})".format(*public_key))
print("x y = " str(public_key[0] public_key[1]))
解题:
代码语言:javascript复制运行上述博主代码,得到结果如下:
private key: 0x857d0
public key: (0xcb19fe553fa, 0x50545408eb4)
x y = 19477226185390