[羊城杯 2020]GMC

from Crypto.Util.number import getPrime,bytes_to_long,getRandomNBitInteger
from secret import flag
from gmpy2 import gcd


def gmc(a, p):
    if pow(a, (p-1)//2, p) == 1:
        return 1
    else:
        return -1


def gen_key():
    [gp,gq] = [getPrime(512) for i in range(2)]
    gN = gp * gq
    return gN, gq, gp


def gen_x(gq,gp):
    while True:
        x = getRandomNBitInteger(512)
        if gmc(x,gp) ^ gmc(x,gq) == -2:
            return x


def gen_y(gN):
    gy_list = []
    while len(gy_list) != F_LEN:
        ty = getRandomNBitInteger(768)
        if gcd(ty,gN) == 1:
            gy_list.append(ty)
    return gy_list


if __name__ == '__main__':

    flag = bin(bytes_to_long(flag))[2:]
    F_LEN = len(flag)
    N, q, p = gen_key()
    x = gen_x(q, p)
    y_list = gen_y(N)
    ciphertext = []

    for i in range(F_LEN):
        tc = pow(y_list[i],2) * pow(x,int(flag[i])) % N
        ciphertext.append(tc)

    with open('./output.txt','w') as f:
        f.write(str(N) + '\n')
        for i in range(F_LEN):
            f.write(str(ciphertext[i]) + '\n')

分析代码,发现x 的生成涉及到平方剩余。利用雅可比符号可表示为 ( x p ) ( x q ) = − 1 (\dfrac{x}{p})(\dfrac{x}{q})=-1 (px)(qx)=1。观察加密部分,根据flag[i]的值有以下两种情况:
{ t c = y i 2 m o d   n   , f l a g [ i ] = 0 t c = y i 2 ∗ x m o d   n   , f l a g [ i ] = 1 \begin{cases} tc = y_i^2\quad mod\ n\ ,\quad flag[i] = 0 \\ tc = y_i^2*x\quad mod\ n\ ,\quad flag[i] = 1 \end{cases} {tc=yi2mod n ,flag[i]=0tc=yi2xmod n ,flag[i]=1
y i y_i yi是模 n 的平方剩余,于是利用雅可比符号的可乘性,上面两个式子是否平方剩余可表示为
{ ( t c n ) = ( y i 2 n ) = 1   , f l a g [ i ] = 0 ( t c n ) = ( y i 2 n ) ( x n ) = ( x p ) ( x q ) = − 1   , f l a g [ i ] = 1 \begin{cases} (\dfrac{tc}{n}) = (\dfrac{y_i^2}{n})=1\ ,\quad flag[i] = 0 \\ (\dfrac{tc}{n}) = (\dfrac{y_i^2}{n})(\dfrac{x}{n}) = (\dfrac{x}{p})(\dfrac{x}{q})=-1 \ ,\quad flag[i] = 1 \end{cases} (ntc)=(nyi2)=1 ,flag[i]=0(ntc)=(nyi2)(nx)=(px)(qx)=1 ,flag[i]=1
根据雅可比的值的不同,推出flag。

from Crypto.Util.number import *
from gmpy2 import jacobi

f = open(r'output.txt','r')
n = int(f.readline())

cipher = f.readlines()

flag = ''
for each in cipher:
    tc = int(each)
    if jacobi(tc,n) == -1:
        flag += '1'
    else:
        flag += '0'

print(long_to_bytes(int(flag,2)))

参考:

羊城杯 2020GMC题解_mortal15的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值