zoukankan      html  css  js  c++  java
  • 攻防世界-密码学-onetimepad

    1. 题目信息

    附件中包含实现加密的Python脚本,与密文文件。

    2. 分析

    2.1. 有限域GF(2^n)

    构造有限域GF(2n)时,首先需要GF(2)上次数为n的本原多项式g(x);对于GF(2n)上的每个元素a,都可以用一个次数不超过n的多项式(f_{a})表示:(f_{a}(x)=sum_{i=0}^{n-1}a_{i}cdot x^{i}),其中(a_{n-1}cdots a_{0})是a的二进制表示;从而GF(2^n)上的四则运算定义如下:

    • 加法:对于(a,bin GF(2^{n})),它们的多项式表示分别为(f_{a},f_{b}),记(f_{c}=f_{a}+f_{b})(其中系数的加法为GF(2)上的加法,即异或运算),则(c_{n-1}cdots c_{0})的二进制值c为a+b的值;

    • 减法:由于GF(2)上的加法与减法等价,因此对于(a,bin GF(2^{n})),a+b=a-b;

    • 乘法:同样地,a,b的多项式表示(f_{a},f_{b}),记(f_c=f_{a}cdot f_{b} extrm{mod} g),由于多项式(g)的次数为n,故多项式(f_{c})的次数不超过n,则(c_{n-1}cdots c_{0})的二进制值c为(acdot b)的值;

    • 除法:先介绍(乘法)逆元,本原多项式是一种具有特殊性质的不可约多项式,对GF(2)上任意次数不超过n的多项式f,都存在GF(2)上次数不超过n的多项式h,使得(fcdot h equiv 1 extrm{mod} g);与f作除法等价于与f的逆元h作乘法;

    2.2. process(m,k)

    考虑(t^{2},tin GF(2^{256})),构造(GF(2^{256}))的本原多项式为(g=x^{256}+x^{10}+x^{5}+x^{2}+1),记t的二进制表示为(t_{n-1}cdots t_{0}),则t的多项式表示(f_{t}(x)=sum_{i=0}^{n-1}t_{i}cdot x^{i}=(((t_{n-1}cdot x+t_{n-2})cdot x+cdots +t_{1})cdot x+t_{0})),考虑(t^{2})

    (f_{t}^{2} extrm{mod} g)

    (=(((t_{n-1}cdot x+t_{n-2})cdot x+cdots +t_{1})cdot x+t_{0})cdot f_{t} extrm{mod} g)

    (=((((t_{n-1}cdot f_{t})cdot x+t_{n-2}cdot f_{t})cdot x+cdots +t_{1}cdot f_{t})cdot x+t_{0}cdot f_{t}) extrm{mod} g)

    (=((((((t_{n-1}cdot f_{t})cdot x+t_{n-2}cdot f_{t}) extrm{mod} g)cdot x+cdots +t_{1}cdot f_{t}) extrm{mod} g)cdot x+t_{0}cdot f_{t}) extrm{mod} g)

    我们再来对比函数process(m,k):

    def process(m, k):
        tmp = m ^ k
        res = 0
        for i in bin(tmp)[2:]:
            res = res << 1;
            if (int(i)):
                res = res ^ tmp
            if (res >> 256):
                res = res ^ P
        return res
    

    res=res<<1代表乘以x,多项式的系数全体左移一位;

    if (int(i)):res=tmp等价于res=int(i)*tmp,代表(+t_{i}cdot f_{t})

    if (res>>256):res^=P代表模本原多项式g;

    综上,process(m,k)实际上实现了GF(2^256)上的元素m与k之和的平方((m+k)^{2})

    2.3. 解密过程

    (k_{2}=(k_{1}+secret)^{2},k_{3}=(k_{2}+secret)^{2})(在GF(2^256)上的运算)

    (c_{1}=m_{1}oplus k_{1},c_{2}=m_{2}oplus k_{2},c_{3}=m_{3}oplus k_{3}),其中(c_{i}(i=1,2,3),m_{i}(i=1,2))已知

    (k_{2}=m_{2}oplus c_{2},k_{3}=m_{3}oplus c_{3}),可解出secret:(secret=k_{3}^{1/2}+k_{2})(在GF(2^256)上的运算)

    接下来解出(k_{1})(k_{1}=k_{2}^{1/2}+secret)(在GF(2^256)上的运算)

    然后解出flag(即(m_{1})):(m_{1}=c_{1}oplus k_{1})

    3. 解题

    实现的sage脚本如下:

    from Crypto.Util.number import bytes_to_long,long_to_bytes
    
    K.<x>=GF(2L**256,modulus=x^256+x^10+x^5+x^2+1)
    
    def polify(N):
        bN=list(bin(N)[2:])
        bN.reverse()
        return K(bN)
    
    def unpolify(Poly):
        bN=Poly.polynomial().list()
        bN.reverse()
        return long(''.join([str(it) for it in bN]),2)
    
    def solve():
        cip1=polify(0xaf3fcc28377e7e983355096fd4f635856df82bbab61d2c50892d9ee5d913a07f)
        cip2=polify(0x630eb4dce274d29a16f86940f2f35253477665949170ed9e8c9e828794b5543c)
        cip3=polify(0xe913db07cbe4f433c7cdeaac549757d23651ebdccf69d7fbdfd5dc2829334d1b)
        msg2=polify(bytes_to_long('I_am_not_a_secret_so_you_know_me'))
        msg3=polify(bytes_to_long('feeddeadbeefcafefeeddeadbeefcafe'))
        secret=cip2+msg2+(cip3+msg3).sqrt()
        key1=(cip2+msg2).sqrt()+secret
        msg1=cip1+key1
        return long_to_bytes(unpolify(msg1))
    
    if __name__=='__main__':
        print 'flag{'+solve()+'}'
    

    程序运行结果如下:

    $ sage solve.sage
    flag{t0_B3_r4ndoM_en0Ugh_1s_nec3s5arY}
    
  • 相关阅读:
    15调度
    如何在idea中找到通过依赖添加的jar包位置
    验证码实现步骤
    重构:利用postman检测前后端互相传值
    反射机制
    Unexpected update count received. Changes will be rolled back. SQL: DELETE FROM `myproject`.`role_module` WHERE `role_id` = ? AND `module_id` = ?
    JavaSE基础之 IO_Buffer
    JavaSE基础之 IO流
    JavaSE基础之 XML(可扩展标记语言)
    JavaSE基础之继承
  • 原文地址:https://www.cnblogs.com/coming1890/p/13607557.html
Copyright © 2011-2022 走看看