格密码之皮毛
NTRU
注:为了求最短向量有时要平衡范数,但对应的g别忘了除以相应的值
参考自https://harry0597.com/2023/02/09/初探格密码/
在一个等式中有两个未知量,可以通过构造格来解未知量
前提是化简出等式,列出未知量矩阵(一般来说,等式里能单独表示的要求量不放在未知量矩阵里)和要求量矩阵。(未知量矩阵*已知量矩阵=要求量矩阵)求出已知量矩阵,用LLL算法。
harry师傅博客中的一题
import gmpy2
from secret import flag
from Crypto.Util.number import *
def generate():
p = getStrongPrime(2048)
while True:
f = getRandomNBitInteger(1024)
g = getStrongPrime(768)
h = gmpy2.invert(f, p) * g % p
return (p, f, g, h)
def encrypt(plaintext, p, h):
m = bytes_to_long(plaintext)
r = getRandomNBitInteger(1024)
c = (r * h + m) % p
return c
p, f, g, h = generate()
c = encrypt(flag, p, h)
print('h =', h)
print('p =', p)
print('c =', c)
"""
h = 15920807412952692847985174177588211960281948838307253586797239960508125481987882224605864406372742338485793530131031795389776531751200676051949170672004649326503467447518123006808297262753280286176914568491022298784897984879823370933511805201516939304165656461649805404345353075803763209810253831770288511818668398003443730898078080711296567200650962390927974385735100849320021423318726773493255693093044142610555698370275203822724528162516863483780170076614868308468049805668954554578089167666866242081591436319781031943877834260419842837279937368942586813623585114579680192182136454951076576180846308031147577895183
p = 29616445112694260274774681537287299269831042656521626513009034520717072986110554689452007791622053679125813101887358792411152206641110832730768759894034995329749945245036475665938165090997263055454214551943883405059392525425764609291470545536168035201657530029849113821500078015786845062143152799634844986753056256220285729693791666273618731684193516606613125066125143895019716948226556471128531174411802630235945882713680099627033330758906060609807833477234842026397619463093836747345939002210487194276855948870859245196439206070300222410002340377429280616491741559912351526804469748340235688215655559714767093336011
c = 24894154600738747801028572977171957374256712941786243361235711912410748252475712552938200529578615522555383736598357845901370674754857388874985225645650913059820754690696257510209172235875364336887131653254443697948965333434213242584604843844646774324930722413839123594241879178636469903372909302377061318833174246232722769872293078758804927418352848560803152544304608965368181815249876729133751310904899772060616419975025741262545479052454752165874425435226386604586446369944613258629120527951194286510228752204113015018002437399369034486123978271982779314575972603420464431960235222295086660836240988842127196837233
"""
exp
import libnum
h = 15920807412952692847985174177588211960281948838307253586797239960508125481987882224605864406372742338485793530131031795389776531751200676051949170672004649326503467447518123006808297262753280286176914568491022298784897984879823370933511805201516939304165656461649805404345353075803763209810253831770288511818668398003443730898078080711296567200650962390927974385735100849320021423318726773493255693093044142610555698370275203822724528162516863483780170076614868308468049805668954554578089167666866242081591436319781031943877834260419842837279937368942586813623585114579680192182136454951076576180846308031147577895183
p = 29616445112694260274774681537287299269831042656521626513009034520717072986110554689452007791622053679125813101887358792411152206641110832730768759894034995329749945245036475665938165090997263055454214551943883405059392525425764609291470545536168035201657530029849113821500078015786845062143152799634844986753056256220285729693791666273618731684193516606613125066125143895019716948226556471128531174411802630235945882713680099627033330758906060609807833477234842026397619463093836747345939002210487194276855948870859245196439206070300222410002340377429280616491741559912351526804469748340235688215655559714767093336011
c = 24894154600738747801028572977171957374256712941786243361235711912410748252475712552938200529578615522555383736598357845901370674754857388874985225645650913059820754690696257510209172235875364336887131653254443697948965333434213242584604843844646774324930722413839123594241879178636469903372909302377061318833174246232722769872293078758804927418352848560803152544304608965368181815249876729133751310904899772060616419975025741262545479052454752165874425435226386604586446369944613258629120527951194286510228752204113015018002437399369034486123978271982779314575972603420464431960235222295086660836240988842127196837233
# 求解f, g
Ge = matrix(ZZ, [[1, h], [0, p]])
f, g = Ge.LLL()[0] # SVP
# 利用f, g求解m
f = abs(f)
g = abs(g)
c_ = (c*f)%p
m = c_*inverse_mod(f, g)%g
print(libnum.n2s(int(m)))
2024 sictf中的一题
from Crypto.Util.number import *
from secret import flag
import gmpy2
assert len(flag) == 47
f = bytes_to_long(flag)
p = getPrime(512)
g = getPrime(128)
h = gmpy2.invert(f, p) * g % p
print('h =', h)
print('p =', p)
"""
h = 9848463356094730516607732957888686710609147955724620108704251779566910519170690198684628685762596232124613115691882688827918489297122319416081019121038443
p = 11403618200995593428747663693860532026261161211931726381922677499906885834766955987247477478421850280928508004160386000301268285541073474589048412962888947
"""
exp
这个题是ntru格密码的一个简化版,构造的格和NTRU的格是一样的但是直接使用是做不出来,要注意f和g的长度,f是47位的测试一下大概在376位左右,而g是128位所以需要平衡范数让构造出来的向量长度相近,这里就多乘了一个2**248
h = 9848463356094730516607732957888686710609147955724620108704251779566910519170690198684628685762596232124613115691882688827918489297122319416081019121038443
p = 11403618200995593428747663693860532026261161211931726381922677499906885834766955987247477478421850280928508004160386000301268285541073474589048412962888947
from Crypto.Util.number import *
v1 = vector(ZZ, [1, 2**248*h])
v2 = vector(ZZ, [0, 2**248*p])
m = matrix([v1,v2]);
shortest_vector = m.LLL()[0]
f, g = shortest_vector
f=abs(f)
print(long_to_bytes(f))
#SICTF{e3fea01c-18f3-4638-9544-9201393940a9}
格是很难的,这里只是皮毛,目前还要去学别的,等遇到其他的格问题再完善此篇。