引言:这里是我做的攻防世界-crypto-基础题的一些writeup,希望能够大家一些参考,部分解题思路借鉴了其他博主,如果哪些地方有问题或更好的思路,可以一起探讨。
所用环境以及做题思路只在当时写下writeup时适用,若之后做出改动可与我联系,做出相应更改。
作者:李世荣
联系方式:点击网站头像即可与我联系
转载请标明出处
Crypto-基础题
1.base64

题目:
Y3liZXJwZWFjZXtXZWxjb21lX3RvX25ld19Xb3JsZCF9

分析:

base64 应该是编码,算不上加密。 翻了 Misc 的 Wiki,笔记在 Crypt 分区里。由于base64编码后的字符除了英文字母和数字外还有三个字符 +, /, =, 其中=只是为了补全编码后的字符数为4的整数,而+和/在一些情况下需要被替换的, b64encode和b64decode正是提供了这样的功能。 +和/需要被替换,最常见的就是对 url 进行 base64 编码的时候。所以最常用的是 b64encode, b64decode,当然某些情况用 encodestring, decodestring 也没有大碍。

解题:
用工具直接破解/网页在线破解/Python代码实现

2.Caesar
题目:
oknqdbqmoq{kag_tmhq_xqmdzqp_omqemd_qzodkbfuaz}
分析:

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
分析:

摩斯密码使用 .、- 来表示不同含义,这里只用 0和1,所以应该是用01代替.、-。 那么到底是用1代表.还是用0代表.呢? 都试一下不久好了……

1.png

用·表示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
分析:

     *提示(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
分析:

这个不是普通的栅栏密码!栅栏密码的变种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

2.png
解题:
用工具直接破解/网页在线破解/Python代码实现/纸质解题破译

6.不仅仅是Morse
题目:

--/.-/-.--/..--.-/-..././..--.-/..../.-/...-/./..--.-/.-/-./---/-/...././.-./..--.-/-.././-.-./---/-.././..../..../..../..../.-/.-/.-/.-/.-/-.../.-/.-/-.../-.../-.../.-/.-/-.../-.../.-/.-/.-/.-/.-/.-/.-/.-/-.../.-/.-/-.../.-/-.../.-/.-/.-/.-/.-/.-/.-/-.../-.../.-/-.../.-/.-/.-/-.../-.../.-/.-/.-/-.../-.../.-/.-/-.../.-/.-/.-/.-/-.../.-/-.../.-/.-/-.../.-/.-/.-/-.../-.../.-/-.../.-/.-/.-/-.../.-/.-/.-/-.../.-/.-/-.../.-/-.../-.../.-/.-/-.../-.../-.../.-/-.../.-/.-/.-/-.../.-/-.../.-/-.../-.../.-/.-/.-/-.../-.../.-/-.../.-/.-/.-/-.../.-/.-/-.../.-/.-/-.../.-/.-/.-/.-/-.../-.../.-/-.../-.../.-/.-/-.../-.../.-/.-/-.../.-/.-/-.../.-/.-/.-/-.../.-/.-/-.../.-/.-/-.../.-/.-/-.../.-/-.../.-/.-/-.../-.../.-/-.../.-/.-/.-/.-/-.../-.../.-/-.../.-/.-/-.../-.../.-

分析:

是摩斯密码的形式,先对摩斯密码解码。 工具:http://www.zhongguosou.com/zonghe/moErSiCodeConverter.aspx (这个网站对摩斯代码的分隔方式支持单斜杠和空格,比较好) 返回结果:
MAYBEHAVEANOTHERDECODEHHHHAAAAABAABBBAABBAAAAAAAABAABABAAAAAAABBABAAABBAAABBAABAAAABABAABAAABBABAAABAAABAABABBAABBBABAAABABABBAAABBABAAABAABAABAAAABBABBAABBAABAABAAABAABAABAABABAABBABAAAABBABAABBA
Maybe have another decode ...... 它的意思应该不是让你从头开始换另一个,而是对摩斯密码解析出来的再用一个的方式解密。 此刻应该关注后面的A和B很有特征的是,它只有两个字符组成,这是培根密码的典型特征。(手抓饼,A套餐,B套餐)

解题:
用工具直接破解/网页在线破解/Python代码实现

7.混合编码
题目:

c7JiM4NDsmIzY1OyYjNTI7JiM3NjsmIzEyMjsmIzEwNzsmIzUzOyYjNzY7JiMxMjI7JiM2OTsmIzEyMDsmIzc3OyYjODM7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiMxMDc7JiMxMTg7JiM3NzsmIzg0OyYjNjU7JiMxMjA7JiM3NjsmIzEyMjsmIzY5OyYjMTIwOyYjNzg7JiMxMDU7JiM1NjsmIzEyMDsmIzc3OyYjODQ7JiM2OTsmIzExODsmIzc5OyYjODQ7JiM5OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzUwOyYjNzY7JiMxMjI7JiM2OTsmIzEyMDsmIzc4OyYjMTA1OyYjNTY7JiM1MzsmIzc4OyYjMTIxOyYjNTY7JiM1MzsmIzc5OyYjODM7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiM5OTsmIzExODsmIzc5OyYjODQ7JiM5OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzExOTsmIzc2OyYjMTIyOyYjNjk7JiMxMTk7JiM3NzsmIzY3OyYjNTY7JiMxMjA7JiM3NzsmIzY4OyYjNjU7JiMxMTg7JiM3NzsmIzg0OyYjNjU7JiMxMjA7JiM3NjsmIzEyMjsmIzY5OyYjMTE5OyYjNzc7JiMxMDU7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiM2OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzExOTsmIzc2OyYjMTIyOyYjMTA3OyYjNTM7JiM3NjsmIzEyMjsmIzY5OyYjMTE5OyYjNzc7JiM4MzsmIzU2OyYjMTIwOyYjNzc7JiM4NDsmIzEwNzsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzEyMDsmIzc2OyYjMTIyOyYjNjk7JiMxMjA7JiM3ODsmIzY3OyYjNTY7JiMxMjA7JiM3NzsmIzY4OyYjMTAzOyYjMTE4OyYjNzc7JiM4NDsmIzY1OyYjMTE5Ow==

分析:
题目中给出了flag格式:cyberpeace{小写的你解出的答案},以==结尾,应该是base家族。用base64解码,得到的类似于Unicode,再用Unicode解码,再用base64,得到了类似于ASKII码的类型,用ASKII解码得到答案。

解题:

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
题目:

在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17
求解出d

分析:

RSA算法中,d,e,p,q的关系如下:
d=e^-1 mod (p-1)(q-1)
现已知p,q,e,可用扩展欧几里得算法进行求逆运算,解出d即可。

解题:

#!/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
分析:

附件是一个python的.pyc文件,大致可以理解为python程序编译得到后的文件。可以下载uncompyle库后使用uncompyle6将easychallenge.pyc反编译成py文件。
pyc介绍
Python 在解释源程序时分为两步:
第一步:将源码转为字节码
第二步:将字节码转换为机器码
pyc 文件是由 Python 解释器将 模块的源码 转换为 字节码。
(pyc,py代表pychon,c 是 compiled的含义,pyc即编译过的python文件 )
当我们的程序没有修改过,那么下次运行程序的时候,就可以跳过 从源码到字节码 的过程,直接加载 pyc 文件。
编辑解密脚本运行程序即可得到flag

uncompyle库的安装.png
解题:

反编译命令 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 = "\xa0\xbe\xa7Z\xb7\xb5Z\xa6\xa0Z\xb8\xae\xa3\xa9Z\xb7Z\xb0\xa9\xae\xa3\xa4\xad\xad\xad\xad\xad\xb2"
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:\Note\CTF> python -u "d:\Note\CTF\demo.py"Traceback (most recent call last):File "d:\Note\CTF\demo.py", line 29, in <module>flag = encode1(encode2(encode3(final)))File "d:\Note\CTF\demo.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:\Note\CTF> python -u "d:\Note\CTF\demo.py"Traceback (most recent call last):File "d:\Note\CTF\demo.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.转轮机加密
题目:

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

分析:

提示:托马斯·杰斐逊。 flag,是字符串,小写。
参看:传统密码学(三)——转轮密码机 是个多表替换密码。 基本操作是“旋转”,其余的和本题是没有关系。
加密表和密钥、密文的特点
加密表每一行都有 26 个不同的字母,密钥的长度、密文长度、表格的行数都是 13,密文中字母是有重复字母的。

解题:

首先将每一行按照密钥顺序重新排列,如第二行应至于第一行的位置,以此类推。
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)%26]
    print(flag.lower())

11.Normal_RSA
分析:

OpenSSL 使用 PEM 文件格式存储证书和密钥。PEM 实质上是 Base64 编码的二进制内容,再加上开始和结束行,如证书文件的
-----BEGIN CERTIFICATE-----
和
-----END CERTIFICATE-----
在这些标记外面可以有额外的信息,如编码内容的文字表示。文件是 ASCII 的,可以用任何文本编辑程序打开它们。
①使用openssl解密.pem中参数-->②参数十六进制转换为十进制-->③利用factor对大整数进行分解,得到p和q -->④用rsatool生成私钥文件: private.pem-->⑤用private.pem解密flag.enc

解题:

本题主要考察工具的使用,附件共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

20191024213318585.PNG

对素数乘积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

20191024222039999.PNG

用生成出的私钥文件解密flag
openssl rsautl -decrypt -in flag.enc -inkey private.pem

20191024222114993.PNG

12.easy_ECC
题目:

已知椭圆曲线加密Ep(a,b)参数为
p = 15424654874903
a = 16546484
b = 4548674875
G(6478678675,5636379357093)
私钥为
k = 546768
求公钥K(x,y)

分析:

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]))

解题:

运行上述博主代码,得到结果如下:
private key: 0x857d0
public key: (0xcb19fe553fa, 0x50545408eb4)
x + y = 19477226185390

CRYPTO-基础题.png

最后修改:2021 年 09 月 13 日 09 : 29 PM
如果觉得这篇文章不错,不妨赏我碎银几两。