from Crypto.Util.number import * import random import os r = os.urandom(58) flag = b'flag{' + r + b'}' m = bytes_to_long(flag) print(m.bit_length()) p = getPrime(512) q = getPrime(512) n = p*q e = 3 c = pow(m,e,n) leak = (m>>72)<<72
from Crypto.Util.number import * import libnum leak = 5364346700996002419782953699183539964838028506044205579153385131511046817129051651578134266343785810441589599993973488281743331245307218897879563440750592 c = 40935151362933943549618319861069602822252994206384375794897447336909222247831278964858728027767056236448151125640558855254473877904819185119141154165089443796277880539873361002972028932876254906159097470466137303335170155152431248477323590112940870317475379089257767219445763033224635983039863076611351104336 n= 117575455116027501138912629496694211426851342451722297844472247041789855520700682789833315967293375516507091916652099874126157193406739919014990279487154654321780811384714209768811626630753881580962486730634616085329659924119107924710021010092412019109403168379014063806220470892151350863781965096437381127661 PR.<x> = PolynomialRing(Zmod(n)) m = leak + x m = m.monic() M = m((m^3-c).small_roots()[0]) print(M) print(libnum.n2s(int(M)))
from Crypto.Util.number import * import libnum import gmpy2 import uuid flag = b'flag{' + str(uuid.uuid4()).encode() + b'}' p = getPrime(512) q = getPrime(512) n = p*q m = bytes_to_long(flag) e = 65537 c = pow(m,e,n)
print('c = ', c) print('n = ', n) print('leak = ', p >> 200)
""" c = 113586177374556404023302519526754665470570871476581572924010485271609182939576292258309693919183665334593269032771168258676196238354553238207372511638353179203781100360164950899879081096534890623159302893909393987089255020158056119954592555987794050357729528077439336645285541296688606433920178147114273163214 n = 117400480938142315180437859683247427996874734449806782078398939334361106314549758122280645558538068023461810390291406250149045673033058236602564577080271495334738508492592434662896092890777780831354145755712206139360655422348268610020323769810399146777354043835879906538618644988182234583974095999379431384971 leak = 6988520536508181139792486524710394841324279945751362186371062878730048665522475016854515443490 """
defsmall_roots(self, X=None, beta=1.0, epsilon=None, **kwds): r""" Let `N` be the characteristic of the base ring this polynomial is defined over: ``N = self.base_ring().characteristic()``. This method returns small roots of this polynomial modulo some factor `b` of `N` with the constraint that `b >= N^\beta`. Small in this context means that if `x` is a root of `f` modulo `b` then `|x| < X`. This `X` is either provided by the user or the maximum `X` is chosen such that this algorithm terminates in polynomial time. If `X` is chosen automatically it is `X = ceil(1/2 N^{\beta^2/\delta - \epsilon})`. The algorithm may also return some roots which are larger than `X`. 'This algorithm' in this context means Coppersmith's algorithm for finding small roots using the LLL algorithm. The implementation of this algorithm follows Alexander May's PhD thesis referenced below. INPUT: - ``X`` -- an absolute bound for the root (default: see above) - ``beta`` -- compute a root mod `b` where `b` is a factor of `N` and `b \ge N^\beta`. (Default: 1.0, so `b = N`.) - ``epsilon`` -- the parameter `\epsilon` described above. (Default: `\beta/8`) - ``**kwds`` -- passed through to method :meth:`Matrix_integer_dense.LLL() <sage.matrix.matrix_integer_dense.Matrix_integer_dense.LLL>`. EXAMPLES: First consider a small example:: sage: N = 10001 sage: K = Zmod(10001) sage: P.<x> = PolynomialRing(K, implementation='NTL') sage: f = x^3 + 10*x^2 + 5000*x - 222 This polynomial has no roots without modular reduction (i.e. over `\ZZ`):: sage: f.change_ring(ZZ).roots() [] To compute its roots we need to factor the modulus `N` and use the Chinese remainder theorem:: sage: p, q = N.prime_divisors() sage: f.change_ring(GF(p)).roots() [(4, 1)] sage: f.change_ring(GF(q)).roots() [(4, 1)] sage: crt(4, 4, p, q) 4 This root is quite small compared to `N`, so we can attempt to recover it without factoring `N` using Coppersmith's small root method:: sage: f.small_roots() [4] An application of this method is to consider RSA. We are using 512-bit RSA with public exponent `e=3` to encrypt a 56-bit DES key. Because it would be easy to attack this setting if no padding was used we pad the key `K` with 1s to get a large number:: sage: Nbits, Kbits = 512, 56 sage: e = 3 We choose two primes of size 256-bit each:: sage: p = 2^256 + 2^8 + 2^5 + 2^3 + 1 sage: q = 2^256 + 2^8 + 2^5 + 2^3 + 2^2 + 1 sage: N = p*q sage: ZmodN = Zmod( N ) We choose a random key:: sage: K = ZZ.random_element(0, 2^Kbits) and pad it with `512-56=456` 1s:: sage: Kdigits = K.digits(2) sage: M = [0]*Kbits + [1]*(Nbits-Kbits) sage: for i in range(len(Kdigits)): M[i] = Kdigits[i] sage: M = ZZ(M, 2) Now we encrypt the resulting message:: sage: C = ZmodN(M)^e To recover `K` we consider the following polynomial modulo `N`:: sage: P.<x> = PolynomialRing(ZmodN, implementation='NTL') sage: f = (2^Nbits - 2^Kbits + x)^e - C and recover its small roots:: sage: Kbar = f.small_roots()[0] sage: K == Kbar True The same algorithm can be used to factor `N = pq` if partial knowledge about `q` is available. This example is from the Magma handbook: First, we set up `p`, `q` and `N`:: sage: length = 512 sage: hidden = 110 sage: p = next_prime(2^int(round(length/2))) sage: q = next_prime(round(pi.n()*p)) # needs sage.symbolic sage: N = p*q # needs sage.symbolic Now we disturb the low 110 bits of `q`:: sage: qbar = q + ZZ.random_element(0, 2^hidden - 1) # needs sage.symbolic And try to recover `q` from it:: sage: F.<x> = PolynomialRing(Zmod(N), implementation='NTL') # needs sage.symbolic sage: f = x - qbar # needs sage.symbolic We know that the error is `\le 2^{\text{hidden}}-1` and that the modulus we are looking for is `\ge \sqrt{N}`:: sage: from sage.misc.verbose import set_verbose sage: set_verbose(2) sage: d = f.small_roots(X=2^hidden-1, beta=0.5)[0] # time random # needs sage.symbolic verbose 2 (<module>) m = 4 verbose 2 (<module>) t = 4 verbose 2 (<module>) X = 1298074214633706907132624082305023 verbose 1 (<module>) LLL of 8x8 matrix (algorithm fpLLL:wrapper) verbose 1 (<module>) LLL finished (time = 0.006998) sage: q == qbar - d # needs sage.symbolic True REFERENCES: Don Coppersmith. *Finding a small root of a univariate modular equation.* In Advances in Cryptology, EuroCrypt 1996, volume 1070 of Lecture Notes in Computer Science, p. 155--165. Springer, 1996. http://cr.yp.to/bib/2001/coppersmith.pdf Alexander May. *New RSA Vulnerabilities Using Lattice Reduction Methods.* PhD thesis, University of Paderborn, 2003. http://www.cs.uni-paderborn.de/uploads/tx_sibibtex/bp.pdf """ from sage.misc.verbose import verbose from sage.matrix.constructor import Matrix from sage.rings.real_mpfr import RR
N = self.parent().characteristic()
ifnot self.is_monic(): raise ArithmeticError("Polynomial must be monic.")
beta = RR(beta) if beta <= 0.0or beta > 1.0: raise ValueError("0.0 < beta <= 1.0 not satisfied.")
f = self.change_ring(ZZ)
P,(x,) = f.parent().objgens()
delta = f.degree()
if epsilon isNone: epsilon = beta/8 verbose("epsilon = %f"%epsilon, level=2)
m = max(beta**2/(delta * epsilon), 7*beta/delta).ceil() verbose("m = %d"%m, level=2)
if X isNone: X = (0.5 * N**(beta**2/delta - epsilon)).ceil() verbose("X = %s"%X, level=2)
# we could do this much faster, but this is a cheap step # compared to LLL g = [x**j * N**(m-i) * f**i for i inrange(m) for j inrange(delta) ] g.extend([x**i * f**m for i inrange(t)]) # h
B = Matrix(ZZ, len(g), delta*m + max(delta,t) ) for i inrange(B.nrows()): for j inrange( g[i].degree()+1 ): B[i,j] = g[i][j]*X**j
B = B.LLL(**kwds)
f = sum([ZZ(B[0,i]//X**i)*x**i for i inrange(B.ncols())]) R = f.roots()
ZmodN = self.base_ring() roots = set([ZmodN(r) for r,m in R ifabs(r) <= X]) Nbeta = N**beta return [root for root in roots if N.gcd(ZZ(self(root))) >= Nbeta]