Skip to main content

四月

·524 words·3 mins

拉格朗日插值 #

这个蛮有意思,可以考虑用这个对数列题求解

from secrets import randbelow
from Crypto.Util.number import getPrime
import sys

SIZE = 256
class PCG: # Polynomial Congruential Generator
    def __init__(self):
        self.m = getPrime(256)
        self.coeff = [randbelow(self.m-1) for _ in range(SIZE)] # 随机数列表
        self.x = randbelow(self.m-1) # 随机数
    def __call__(self): # f = a*x^255.......b*x^1 + c
        newx = 0
        for c in self.coeff:
            newx *= self.x
            newx += c
            newx %= self.m
        self.x = newx
        return self.x
    def printm(self):
        print(self.m)
        return
pcg = PCG()

print(pcg.m) # 模 
for i in range(SIZE*3):
    print(pcg())

sys.stdout.flush()
correct = True
for i in range(SIZE // 2):
    guess = int(input())
    if guess != pcg():
        correct = False

if correct:
    print(open('flag.txt','r').read())
else:
    print("you failed")
sys.stdout.flush()

    def __call__(self): # f = a*x^255.......b*x^1 + c
        newx = 0
        for c in self.coeff:
            newx *= self.x
            newx += c
            newx %= self.m

这一段可以看做

$$ x_1=f(x_0)=a_{1}x_0^{255}+…..+a_{255}x_0+a_{256} \mod{p} $$ 可以看做 $$ y_0=f(x_0) $$ 构成点 $$ (x_0,y_0)=(x_0,x_1) $$

有这样256个x 构成255个点

尝试通过用拉格朗日差值的方法得到F的各个系数

points = []
m = int(sh.recvline().strip().decode())
T = []
for i in range(256*3):
    t = int(sh.recvline().strip().decode())
    T.append(t)
for i in range(len(T)-1):
    points.append((T[i],T[i+1]))

print("m =" , m)
print("points =" , points) # 255个点
print("T =",T) # 256个随机数
PR = PolynomialRing(Zmod(m), 'x')
f = PR.lagrange_polynomial(points) # 插值sage调用
print(f)
for i in range(128):
    tt = f(T[-1])
    T.append(tt)
    print(tt)

数字签名 平滑N #

from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
from math import lcm,gcd
from secrets import randbelow
from hashlib import sha256

NUM_BITS = 2048

def getModulus(bits):
    n = 1
    primes = []
    while n.bit_length() < bits:
        p = getPrime(24)
        if p not in primes:
            n *= p
            primes.append(p)
    return n,primes

def sign(n,msg,d):
    h = bytes_to_long(sha256(msg).digest())
    k = randbelow(q-2)+1
    x = pow(h,k,n)
    r = pow(x,d,n)
    s = pow(h+x,d,n)
    return r,s

def verify(n,msg,e,r,s):
    h = bytes_to_long(sha256(msg).digest())
    v1 = pow(r,e,n)
    v2 = pow(s,e,n)
    return v2 == (v1 + h) % n

n,primes = getModulus(NUM_BITS)
q = 1
for p in primes:
    q = lcm(q,p-1)
msgs = []
e = 65537
d = pow(e,-1,q)

print(f"The modulus is ... a mystery left for you to unfold.")
print(f"Your verification exponent {e = }")
msg = input("Give the oracle a message to sign: ").encode()
msgs.append(msg)
r,s = sign(n,msg,d)
print(f"Your verification signature is ({r}, {s})")

msg = input("Give the oracle another message to sign: ").encode()
msgs.append(msg)
r,s = sign(n,msg,d)
print(f"Your second verification signature is ({r}, {s})")

comm = input("Ask the oracle a question: ").encode()
r,s = input("Give the verification signature: ").split(",")
r,s = int(r),int(s)

if comm in msgs:
    print("Hey, no cheating")
    exit()
if verify(n,comm,e,r,s):
    if comm == b"What is the flag?":
        print("The flag is: ",end="")
        with open("flag.txt","r") as flag:
            print(flag.read())
    else:
        print("Not the right question.")
else:
    print("Invalid signature")

看到这一句

拿给系统签名的msg不能用于获取flag

所以前两次签名的msg不是重点

if comm in msgs:
    print("Hey, no cheating")
    exit()

验证部分表面,问你需要构造一个自定义m的签名

if verify(n,comm,e,r,s):
    if comm == b"What is the flag?":
        print("The flag is: ",end="")
        with open("flag.txt","r") as flag:
            print(flag.read())

签名需要n和d

所以我们需要获得 n

然后通过平滑数得到 qi 然后 d

传入两个一样的m然后 $$ \begin{align} h_1 & = h_2 & = H(m)\\ r_1 & = h_1^{k_1},s_1 & = (h+h^{k_1})^d \\ r_2 & = h_2^{k_2},s_2 & = (h+h^{k_2})^d \\ s_1^e-r_1 & = h+h^{k_1} -h^{k_1} \\ s_2^e-r_2 & = h+h^{k_2} -h^{k_2} \\ s_1^e-r_1-h & = h^{k_1} -h^{k_1} & = t1\\ s_2^e-r_2-h & = h^{k_2} -h^{k_2} & = t2\\ t1-t2 & = t3*n \end{align} $$ 得到 n