密码学实验报告

实验目标

第一部分

下列密文均使用古典密码加密,请识别并写出下列密文的加密类型。

  1. tsrlnhiafcisiee

  2. wklvlvfdvhu

  3. BAABBAABBBABAAABAABAABAAABAABAAAAABAAAAAAAABAABBBAABBABABAAAAAAAAABBAB

第二部分

下面是一次RSA加密中的数据,请尝试识别可用的攻击方式,写出解密思路,并写出对应的python脚本。

c = 11236059610940155040515420815459088108548438695111162676979740370803612682449595975315521615456835907246170497671938930521670240256368063

e = 3

n = 123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009

详细步骤

第一部分

1.tsrlnhiafcisiee

古典密码,这么少肯定不是维吉尼亚,估计是凯撒和栅栏挑一个

这个是栅栏

image-20210731153858547

thisisrailfence

2.wklvlvfdvhu

第一个栅栏,那这个就是凯撒了

image-20210731201230164

thisiscaser

3.BAABBAABBBABAAABAABAABAAABAABAAAAABAAAAAAAABAABBBAABBABABAAAAAAAAABBAB

还是古典密码,BABA好明显,甚至都不会误会成morse (:з」∠)

img

1

thisisbaconian

这里建议再吃一个韭菜盒子补充一下营养~

image-20210731154604222

很多连续的字符,第一反应是Morse,然鹅这些没空格,所以一般不是Morse

脑子里就蹦出来培根

代码:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;

int main()
{
    string s,s1;
    int i;
    s1="ottttootoootooooottoootooottotootttootooottotttooootttototoottooootoooottotoottottooooooooottotootto";
    cout<<s1.size();
    s="11 111 010 000 0 1010 111 100 0 00 000 000 111 00 10 1 0 010 0 000 1 00 10 110";
    for(i=0;i<s.size();i++)
    {
        if(s[i]=='1') s1=s1+"-";
        else if(s[i]=='0') s1=s1+".";
        else if(s[i]==' ') s1+="/";

    }
    //cout<<s1;
    return 0;
}

image-20210731154715867

统计出来长度是100,培根密码5个一组,且纯字母,对上了

拿去用word替换

abbbbaabaaabaaaaabbaaabaaabbabaabbbaabaaabbabbbaaaabbbababaabbaaaabaaaabbabaabbabbaaaaaaaaabbabaabba

网址:https://tool.bugku.com/peigen/

加上flag格式就解出来了

完结撒花(。・・。)ノ♡

第二部分

小明文加密,我是懒狗,直接贴超长脚本

# coding:utf-8
import gmpy2, libnum
from Crypto.Util.number import long_to_bytes
from Crypto.PublicKey import RSA
from Crypto.Util.number import bytes_to_long

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
    return (g, x - (b // a) * y, y)

def extended_gcd(a, b):
    x, y = 0, 1
    lastx, lasty = 1, 0
    while b:
        a, (q, b) = b, divmod(a, b)
        x, lastx = lastx - q * x, x
        y, lasty = lasty - q * y, y
    return (lastx, lasty, a)
def CRT(items):  # 中国剩余定理
    N = 1
    for a, n in items:
        N *= n
    result = 0
    for a, n in items:
        m = N // n
        r, s, d = extended_gcd(n, m)
        if d != 1:
            N = N // n
            continue
        result += a * s * m
    return result % N, N

def p_q_e():
    p = int(input("p="))
    q = int(input("q="))
    e = int(input("e="))
    c = int(input("c="))
    phi = (p - 1) * (q - 1)
    n = p * q
    d = gmpy2.invert(e, phi)
    m = pow(c, d, n)
    #print("明文:", libnum.n2s(m))
    string = long_to_bytes(m)
    print(string)

def Common_Modulus():
    n = int(input("n="))
    e1 = int(input("e1="))
    c1 = int(input("c1="))
    e2 = int(input("e2="))
    c2 = int(input("c2="))

    s = egcd(e1, e2)
    s1 = s[1]
    s2 = s[2]
    # 求模反元素
    if s1 < 0:
        s1 = - s1
        c1 = gmpy2.invert(c1, n)
    elif s2 < 0:
        s2 = - s2
        c2 = gmpy2.invert(c2, n)

    m = pow(c1, s1, n) * pow(c2, s2, n) % n
    print("明文:", libnum.n2s(m))

def Small_plaintext_e3():
    e = int(input("e="))
    n = int(input("n="))
    c = int(input("c="))
    for k in range(200000000):
        if gmpy2.iroot(c + n * k, e)[1] == 1:
            m = gmpy2.iroot(c + n * k, e)[0]
            print("明文:", libnum.n2s(m))
            break

def n_e_dp():
    n = int(input("n="))
    e = int(input("e="))
    dp = int(input("dp="))
    c = int(input("c="))
    for i in range(1, 65538):
        if (dp * e - 1) % i == 0:
            if n % (((dp * e - 1) // i) + 1) == 0:
                p = ((dp * e - 1) // i) + 1
                q = n // p
                phi = (p - 1) * (q - 1)
                d = gmpy2.invert(e, phi) % phi
                print(libnum.n2s(pow(c, d, n)))

def N2_equal_P():
    n1 = int(input("n1="))
    n2 = int(input("n2="))
    e1 = int(input("e1="))
    e2 = int(input("e2="))
    c1 = int(input("c1="))
    c2 = int(input("c2="))
    p = gmpy2.gcd(n1, n2)
    # print(p)
    q1 = n1 // p
    q2 = n2 // p
    phi_1 = (p - 1) * (q1 - 1)
    phi_2 = (p - 1) * (q2 - 1)
    d1 = gmpy2.invert(e1, phi_1)
    d2 = gmpy2.invert(e2, phi_2)
    print("m1:", libnum.n2s(pow(c1, d1, n1)))
    print("m2:", libnum.n2s(pow(c2, d2, n2)))

def Prime_3():
    p = int(input("p="))
    q = int(input("q="))
    r = int(input("r="))
    e = int(input("e="))
    c = int(input("c="))
    s = (p - 1) * (q - 1) * (r - 1)
    d = (gmpy2.invert(e, s))
    n = p * q * r
    m = pow(c, d, n)
    print("明文:", libnum.n2s(m))

def RSA_File():
    public_name = input("请输入公钥文件名(没有直接回车):")
    flag_name = input("请输入加密文件名:")
    private_name = input("请输入私钥文件名(没有直接回车):")
    with open(flag_name, 'rb') as f:
        c = bytes_to_long(f.read())
    if private_name == "":
        pass
    else:
        with open(private_name, 'rb') as private:
            Key = RSA.importKey(private.read())
            n, e, d, p, q = Key.n, Key.e, Key.d, Key.p, Key.q
            m = pow(c, d, n)
            print("明文:", libnum.n2s(m))
            return
    with open(public_name, 'rb') as public:
        key = RSA.importKey(public.read())
        n, e = key.n, key.e

    print("n=", n)
    print("e=", e)
    print("c=", c)
def next_prime():
    n = int(input("n="))
    e = int(input("e="))
    c = int(input("c="))
    i = gmpy2.isqrt(n)
    p, q = 0, 0
    while True:
        if n - (i * (n // i)) == 0:
            p = i
            q = n // i
            break
        i += 1
    phi = (p - 1) * (q - 1)
    d = gmpy2.invert(e, phi)
    m = pow(c, d, n)
    print("明文:", libnum.n2s(m))

def Broadcast():
    print('n,e,c由文件导入,请确保格式为[{"c": , "e": , "n":}]')
    print("不同组用逗号隔开,如[{},{}]")
    file_name = input("请输入文件名:")
    with open(file_name, 'r') as f:
        f = f.read()
    sessions = eval(f)#把字符串变表达式
    #print(sessions)
    data = []
    for session in sessions:
        e = session['e']
        n = session['n']
        msg = session['c']
        data = data + [(msg, n)]  #字典相加还是字典
        #print(data)
    print("Please wait, performing CRT")
    x, n = CRT(data) #中国剩余定理
    e = session['e']
    m = gmpy2.iroot(x, e)[0] #求大整数x开n次根,[0]是直接把开出来的数字拿出来
    print("明文:", libnum.n2s(m))

if __name__ == "__main__":
    print("1.已知p,q,e")
    print("2.共模攻击")
    print("3.小明文攻击,e一般为3")
    print("4.已知n,e,dp")
    print("5.模不互素,求出共因子p")
    print("6.三个素数的RSA")
    print("7.读取RSA公钥文件,私钥文件和密文")
    print("8.p,q相近")
    print("9.低加密指数广播攻击")
    x = input("请选择解密方法:")

    if x == '1':
        p_q_e()
    if x == '2':
        Common_Modulus()
    if x == '3':
        Small_plaintext_e3()
    if x == '4':
        n_e_dp()
    if x == '5':
        N2_equal_P()
    if x == '6':
        Prime_3()
    if x == '7':
        RSA_File()
    if x == '8':
        next_prime()
    if x == '9':
        Broadcast()

image-20210731155254732

do_you_like_crypto?

对大一孩子就应该出这种题

image-20210731155653490

image-20210731155726974

image-20210731155801447

先贴一下答案

image-20210731155838263

先检验一下md5格式,32位小写

image-20210731201321058

转化成Latex格式

\sqrt[2020]{2020!}-\frac{1}{112}-\frac{28\pi}{3}

拿去md5

MD5网址:https://www.sojson.com/md5/

image-20210731201348756

所以flag:unctf{41089a0397ae9cd1bc1f2f4894924359}

image-20210731160019904

可以很好地考察大一孩子们的数学功底(bushi

(:з」∠)

总结反思

ppt做的非常好看,希望可以要到一个可以下载的版本收藏

梦成小哥哥最好啦~~

img

补充:找到可以下载的pdf了,我是垃圾~(:з」∠)


一只古灵古灵的精怪