N1CTF 2018:RSA_Padding

题目如下:

首先:

验证工作

如何解,请看下面工作量证明算法
接下来:
图片.png

选择1 get code,得到加密脚本
选择2,填充字符,得到密文
加密脚本如下:

#!/usr/bin/env python3
# -*- coding=utf-8 -*-
 
from Crypto.Util.number import getPrime, GCD, bytes_to_long
from hashlib import sha256
import random
import signal
import sys, os
 
signal.alarm(20)
 
m = b"xxxxxxxxxxxxxx"
n = 21727106551797231400330796721401157037131178503238742210927927256416073956351568958100038047053002307191569558524956627892618119799679572039939819410371609015002302388267502253326720505214690802942662248282638776986759094777991439524946955458393011802700815763494042802326575866088840712980094975335414387283865492939790773300256234946983831571957038601270911425008907130353723909371646714722730577923843205527739734035515152341673364211058969041089741946974118237091455770042750971424415176552479618605177552145594339271192853653120859740022742221562438237923294609436512995857399568803043924319953346241964071252941
e = 3
 
def proof():
    strings = "abcdefghijklmnopqrstuvwxyzWOERFJASKL"
    prefix = "".join(random.sample(strings, 6))
    starwith = str(random.randint(10000, 99999))
    pf = """
sha256("%s"+str).hexdigest().startswith("%s") == True
Please give me str
"""%(prefix, starwith)
    print(pf)
    s = input().strip()
    if sha256((prefix+s).encode()).hexdigest().startswith(starwith):
        return True
    else:
        return False
 
def cmd():
    help = """
1. get code
2. get flag
Please tell me, what you want?
"""
    while True:
        print(help)
        c = input().strip()
        if c == "1":
            return True
        elif c == "2":
            return False
        else:
            print("Enter Error!")
 
def main():
    if not proof():
        print("Check Failed!")
        return
    welcom()
    if cmd():
        f = open("file.py")
        print(f.read())
        return
    mm = bytes_to_long(m)
    assert pow(mm, e) != pow(mm, e, n)
    sys.stdout.write("Please give me a padding: ")
    padding = input().strip()
    padding = int(sha256(padding.encode()).hexdigest(),16)
    c = pow(mm+padding, e, n)
    print("Your Ciphertext is: %s"%c)
 
if __name__ == '__main__':
    main()

一:先说一个阿三的例子:

(阿三不是侮辱称呼,是亲切称呼)

由题目给的加密算法:


加密算法

转化成数学公式如下:

c =(m + sha256(pad))** 3%n

注意:m**3>n(这里没明白,为什么要>N)

以下就是阿三的重点:

阿三做了两次填充,分别求出两个密文(c1,c2)如下所示:

hash1 = int(sha256('2').hexdigest(), 16)
c1 = pow(m + hash1, e, n)

hash2 = int(sha256('1').hexdigest(), 16)
c2 = pow(m + hash2, e, n)

破解密码算法如下:

1

消去共有项(h1 – h2):


图片.png

我相信大家看到这里就明白了吧。本人做一个简单的解释:

1.由于e=3,幂指数比较低,且明文m和模数n都不变;
2.对c1,c2三次幂进行展开,消除同类项,得到一个二次幂的公式,
3.重点来了:使用二次幂求根公式,如下所示:

求根公式

这里不得不佩服阿三了,用一个简单的办法来解决办法。
代码如下:

mport hashlib
import gmpy2
from Crypto.Util.number import *
 
hash1 = int(hashlib.sha256('2').hexdigest(), 16)
hash2 = int(hashlib.sha256('1').hexdigest(), 16)
diff = hash1 - hash2
print "diff: ", diff
 
# M1 = M2 + diff
n = 21727106551797231400330796721401157037131178503238742210927927256416073956351568958100038047053002307191569558524956627892618119799679572039939819410371609015002302388267502253326720505214690802942662248282638776986759094777991439524946955458393011802700815763494042802326575866088840712980094975335414387283865492939790773300256234946983831571957038601270911425008907130353723909371646714722730577923843205527739734035515152341673364211058969041089741946974118237091455770042750971424415176552479618605177552145594339271192853653120859740022742221562438237923294609436512995857399568803043924319953346241964071252941L
e = 3
 
c1 = 14550589053226237723784378782911157204367764723816957959635387925652898370034365455451983914571405062459535687617841302966938233065296973978472553109061974458935966754832788411876301179210585984208608247433383774246743661884093657109502619626436726032508763685599880808525861655167503719155953736308920858354069083437923495143680174206534169208623366776314544036377265501358254923029291010047210371394197963442022610746743020719292018028518885149189744832788117626194748311114409968846879212425054195323473068436359069318372735069308398135560733890706617536127579272964863500568572120716434126233695562326533941909353
c2 = 14550589053226237723784378782911157204367764723813789158271625147472004207734354619642445255036997940341703539883653916130592718879734436263217819317202435434496341973502556894834798718992952369685841347018901038478081710519253844078907000973324354805502890255414196801758171762906898874914776720897920729518384393581853690034053515213192846817920534901501370942556249012415259244063185938984570137371682805276444650716010228924732495062415330875872004691866847132147232457398743319930259327973290858489741376000333603734294893832124907092640953321640151851853501528390729805151850605432707293088635480863375398001441
b = 3*(hash1+hash2)
a = 3
c=(hash1**2+hash1*hash2+hash2**2)-(c1-c2)/(hash1-hash2)
 det_pre=b**2-4*a*c 
det = gmpy2.iroot(b**2 - 4*a*c, 2)
det = det=tuple(det)[0]
sol1 = (det - b)/(2*a)
print long_to_bytes(sol1)
#最终得到答案

小结:

  1. 阿三对数学和密码学运算掌握的比较熟,能够融汇贯通。
  2. 这道题原本的用意应该不是这种解法。也许碰巧能用求根公式做。
  3. 本人还是不明白,为什么要m^3>n, 若有人知道这个简单问题,请留言。

方法二:使用 sage

import hashlib

def chunk(input_data, size):
    return [input_data[i:i+size] for i in range(0, len(input_data), size)]

def long_to_bytes(data):
    data = int(data)
    data = hex(data).rstrip('L').lstrip('0x')
    if len(data) % 2 == 1:
        data = '0' + data
    return bytes(bytearray(int(c, 16) for c in chunk(data, 2)))
def gcd(a, b): 
    while b:
        a, b = b, a % b
    return a.monic() 
#monic()表示首系数为1的单项式
def franklin(n, pad1, pad2, c1, c2):
    R.<X> = PolynomialRing(Zmod(n))
    f1 = (X + pad1)^3 - c1
    f2 = (X + pad2)^3 - c2
    return -gcd(f1, f2).coefficients()[0]
#ciefficient():多项式的系数集合,顺序和集合的下标相对应
def main():
    n = 21727106551797231400330796721401157037131178503238742210927927256416073956351568958100038047053002307191569558524956627892618119799679572039939819410371609015002302388267502253326720505214690802942662248282638776986759094777991439524946955458393011802700815763494042802326575866088840712980094975335414387283865492939790773300256234946983831571957038601270911425008907130353723909371646714722730577923843205527739734035515152341673364211058969041089741946974118237091455770042750971424415176552479618605177552145594339271192853653120859740022742221562438237923294609436512995857399568803043924319953346241964071252941
    pad1 = int(hashlib.sha256("1").hexdigest(),16)
    pad2 = int(hashlib.sha256("2").hexdigest(),16)
    c1 = 14550589053226237723784378782911157204367764723813789158271625147472004207734354619642445255036997940341703539883653916130592718879734436263217819317202435434496341973502556894834798718992952369685841347018901038478081710519253844078907000973324354805502890255414196801758171762906898874914776720897920729518384393581853690034053515213192846817920534901501370942556249012415259244063185938984570137371682805276444650716010228924732495062415330875872004691866847132147232457398743319930259327973290858489741376000333603734294893832124907092640953321640151851853501528390729805151850605432707293088635480863375398001441
    c2 = 14550589053226237723784378782911157204367764723816957959635387925652898370034365455451983914571405062459535687617841302966938233065296973978472553109061974458935966754832788411876301179210585984208608247433383774246743661884093657109502619626436726032508763685599880808525861655167503719155953736308920858354069083437923495143680174206534169208623366776314544036377265501358254923029291010047210371394197963442022610746743020719292018028518885149189744832788117626194748311114409968846879212425054195323473068436359069318372735069308398135560733890706617536127579272964863500568572120716434126233695562326533941909353
    result = franklin(n, pad1, pad2, c1, c2)
    print(long_to_bytes(result))
#我理解的意思是:
#1.消去多项式的最大公约数
#2.并把gcd返回的结果变成一个一次多项式 x+c
#3.取0次幂项(就是所说的常数c)的相反数,n-c为结果
#4.由于多项式模运算,所以 以模n为界。
main()

解释:

R.<X> = PolynomialRing(Zmod(n))
Zmod(n):
1.指定模,定义界限为n的环;Z表示整数
2.指定模是划定这个环的界限:
3.就是有效的数字只有从0到n
4.其他的都通过与n取模来保证在0~n这个范围内
5:Zmod代表这是一个整数域中的n模环
R:只是一个指针,指向用polynomialring指定的那个环(可以使用任意字符)
PolynomialRing:这个就是说建立多项式环
.<X>:指定一个变量的意思(可以用任意字符)


以下是一些做本次题目的相关知识:

Python strip()方法:

描述

Python strip() 方法用于移除字符串头尾指定的字符(默认为空格)。

语法

strip()方法语法:

'str.strip([chars]);'

参数

  • chars -- 移除字符串头尾指定的字符。

返回值

返回移除字符串头尾指定的字符生成的新字符串。

实例

以下实例展示了strip()函数的使用方法:

str = "0000000     Runoob  0000000"; 
print str.strip( '0' );  # 去除首尾字符 0
str2 = "   Runoob      ";   # 去除首尾空格
print str2.strip();
*********************************************************
以上实例输出结果如下:
    Runoob  
Runoob

Python xrange() 函数:

xrange()用法和让完全按相同,不同的就是生成不是一个数组,而是一个生成器。

xrange 语法:

xrange(stop)
xrange(start, stop[, step])

参数说明:

参数说明:

  • start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价 于range(0, 5);
  • stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5
  • step:步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)

返回值

返回生成器。

实例

以下实例展示了 xrange 的使用方法:

>>>xrange(8)
xrange(8)
>>> list(xrange(8))
[0, 1, 2, 3, 4, 5, 6, 7]
>>> range(8)                 # range 使用
[0, 1, 2, 3, 4, 5, 6, 7]
>>> xrange(3, 5)
xrange(3, 5)
>>> list(xrange(3,5))
[3, 4]
>>> range(3,5)               # 使用 range
[3, 4]
>>> xrange(0,6,2)
xrange(0, 6, 2)              # 步长为 2
>>> list(xrange(0,6,2))
[0, 2, 4]
>>>

累加移位输出:

for i in '-'+string.digits:
    ...:     for j in '-'+string.digits:
    ...:         for k in string.digits:
    ...:             if((i!='-')and(j!='-')):
    ...:                 print(prepend+i+j+k)
    ...:             elif((i=='-')and(j!='-')):
    ...:                  print(prepend+j+k) 
    ...:                  if((j=='-')and(i=='-')):
    ...:                      print (prepend + k)

工作量证明算法:

(n1ctf 2018 解题前的验证算法)

from pwn import *
import hashlib
import string
from Crypto.Util.number import *
 
r = remote("47.75.39.249",'23333')
 
r.recvline()
str1 = r.recvline().strip()
print "condition: ", str1
 
prepend = str1[8:14]
sha_end = str1[len(str1)-15:len(str1)-10]
 
for i in string.letters + string.digits:
    for j in string.letters + string.digits:
        for k in string.letters + string.digits:
            for l in string.letters + string.digits:
                var = hashlib.sha256(prepend + i + j + k + l).hexdigest()[:5]
                if var == sha_end:
                    print "gotit!"
                    print "happening: ", r.recvline()
                    r.recvline()
                    r.sendline(i + j + k + l)
                    print r.recvuntil("want?\n\n")
                    r.interactive()
                    r.sendline("1")
                    print r.recvall()
                    exit()
                    break
print "Failed!"

hash.digest() 
返回摘要,作为二进制数据字符串值
hash.hexdigest() 
返回摘要,作为十六进制数据字符串值

参考文献:
工作量证明算法:http://blog.csdn.net/AAA123524457/article/details/52837510
mpz的一些用法:http://mcs.une.edu.au/doc/python3-gmpy2/mpz.html
sage网站:http://doc.sagemath.org/html/en/reference/polynomial_rings/sage/rings/polynomial/polynomial_ring_constructor.html
sage中文:https://www.lainme.com/doku.php/topic/sage/chapter_02/section_09

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容

  • 这个不错分享给大家,从扣上看到的,就转过来了 《电脑专业英语》 file [fail] n. 文件;v. 保存文...
    麦子先生R阅读 6,545评论 5 24
  • 能逃得过世人甚至警察法眼的,往往是最不起眼的人事。例如,谁会想到,一个尘封十九年的未解命案,凶手居然只是一个小学生...
    JoelyZhao阅读 682评论 0 7
  • 没有你的日子我也过得很充实,及时每天很累,但是不在那么想念你了。 若不复相见,平安唯愿! 辛辛苦苦干了,一年...
    DOVE_5214阅读 200评论 0 0
  • 每位老师都很努力,很用心,几个月来有哭有笑,有吵有闹,磕磕绊绊走到现在,没有一个人说要放弃,因为我也曾从助教...
    童心童画关老师阅读 121评论 0 0
  • Given a time represented in the format "HH:MM", form the ...
    Jeanz阅读 719评论 0 0