前言
最近做题的时候有遇到一个问题,就是去利用求解出来的rsa的私钥去生成pem格式的私钥文件。找到网上用的都是先令RSA去generate,然后分别给RSA的n,e,d,p,q参数赋值,再导出私钥。所以在想这种情况下怎么解决。
解决方法
现在使用Crypto.PublicKey.RSA模块时,这么做将报错
Exception has occurred: AttributeError
can't set attribute
意思就是我们不能去给他赋值了。
然后我们去找到Crypto.PublicKey.RSA模块的代码
发现可以通过构造函数传入
这边是Crypto.PublicKey.RSA模块的构造函数实现。
def construct(rsa_components, consistency_check=True):
r"""Construct an RSA key from a tuple of valid RSA components.
The modulus **n** must be the product of two primes.
The public exponent **e** must be odd and larger than 1.
In case of a private key, the following equations must apply:
.. math::
\begin{align}
p*q &= n \\
e*d &\equiv 1 ( \text{mod lcm} [(p-1)(q-1)]) \\
p*u &\equiv 1 ( \text{mod } q)
\end{align}
Args:
rsa_components (tuple):
A tuple of integers, with at least 2 and no
more than 6 items. The items come in the following order:
1. RSA modulus *n*.
2. Public exponent *e*.
3. Private exponent *d*.
Only required if the key is private.
4. First factor of *n* (*p*).
Optional, but the other factor *q* must also be present.
5. Second factor of *n* (*q*). Optional.
6. CRT coefficient *q*, that is :math:`p^{-1} \text{mod }q`. Optional.
consistency_check (boolean):
If ``True``, the library will verify that the provided components
fulfil the main RSA properties.
Raises:
ValueError: when the key being imported fails the most basic RSA validity checks.
Returns: An RSA key object (:class:`RsaKey`).
"""
class InputComps(object):
pass
input_comps = InputComps()
for (comp, value) in zip(('n', 'e', 'd', 'p', 'q', 'u'), rsa_components):
setattr(input_comps, comp, Integer(value))
n = input_comps.n
e = input_comps.e
if not hasattr(input_comps, 'd'):
key = RsaKey(n=n, e=e)
else:
d = input_comps.d
if hasattr(input_comps, 'q'):
p = input_comps.p
q = input_comps.q
else:
# Compute factors p and q from the private exponent d.
# We assume that n has no more than two factors.
# See 8.2.2(i) in Handbook of Applied Cryptography.
ktot = d * e - 1
# The quantity d*e-1 is a multiple of phi(n), even,
# and can be represented as t*2^s.
t = ktot
while t % 2 == 0:
t //= 2
# Cycle through all multiplicative inverses in Zn.
# The algorithm is non-deterministic, but there is a 50% chance
# any candidate a leads to successful factoring.
# See "Digitalized Signatures and Public Key Functions as Intractable
# as Factorization", M. Rabin, 1979
spotted = False
a = Integer(2)
while not spotted and a < 100:
k = Integer(t)
# Cycle through all values a^{t*2^i}=a^k
while k < ktot:
cand = pow(a, k, n)
# Check if a^k is a non-trivial root of unity (mod n)
if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1:
# We have found a number such that (cand-1)(cand+1)=0 (mod n).
# Either of the terms divides n.
p = Integer(n).gcd(cand + 1)
spotted = True
break
k *= 2
# This value was not any good... let's try another!
a += 2
if not spotted:
raise ValueError("Unable to compute factors p and q from exponent d.")
# Found !
assert ((n % p) == 0)
q = n // p
if hasattr(input_comps, 'u'):
u = input_comps.u
else:
u = p.inverse(q)
# Build key object
key = RsaKey(n=n, e=e, d=d, p=p, q=q, u=u)
# Verify consistency of the key
if consistency_check:
# Modulus and public exponent must be coprime
if e <= 1 or e >= n:
raise ValueError("Invalid RSA public exponent")
if Integer(n).gcd(e) != 1:
raise ValueError("RSA public exponent is not coprime to modulus")
# For RSA, modulus must be odd
if not n & 1:
raise ValueError("RSA modulus is not odd")
if key.has_private():
# Modulus and private exponent must be coprime
if d <= 1 or d >= n:
raise ValueError("Invalid RSA private exponent")
if Integer(n).gcd(d) != 1:
raise ValueError("RSA private exponent is not coprime to modulus")
# Modulus must be product of 2 primes
if p * q != n:
raise ValueError("RSA factors do not match modulus")
if test_probable_prime(p) == COMPOSITE:
raise ValueError("RSA factor p is composite")
if test_probable_prime(q) == COMPOSITE:
raise ValueError("RSA factor q is composite")
# See Carmichael theorem
phi = (p - 1) * (q - 1)
lcm = phi // (p - 1).gcd(q - 1)
if (e * d % int(lcm)) != 1:
raise ValueError("Invalid RSA condition")
if hasattr(key, 'u'):
# CRT coefficient
if u <= 1 or u >= q:
raise ValueError("Invalid RSA component u")
if (p * u % q) != 1:
raise ValueError("Invalid RSA component u with p")
return key
也就是说我们传入一个元组也就是tuple类型的值就行了。那我们就传入(n,e,d,p,q)
我这边给一个我的一个exp
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
f=open("public.key","r")
key=RSA.import_key(f.read())
f.close()
e=key.e
n=key.n
import base64
from Crypto.Util.number import *
import gmpy2
p= 3133337
q=25478326064937419292200172136399497719081842914528228316455906211693118321971399936004729134841162974144246271486439695786036588117424611881955950996219646807378822278285638261582099108339438949573034101215141156156408742843820048066830863814362379885720395082318462850002901605689761876319151147352730090957556940842144299887394678743607766937828094478336401159449035878306853716216548374273462386508307367713112073004011383418967894930554067582453248981022011922883374442736848045920676341361871231787163441467533076890081721882179369168787287724769642665399992556052144845878600126283968890273067575342061776244939
print(p*q==n)
f=open("flag.enc","r")
c_base64=f.read().strip("\n")
c_bytes=base64.b64decode(c_base64)
c=bytes_to_long(c_bytes)
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
rsa_components=(n,e,int(d),p,q)
arsa=RSA.construct(rsa_components)
rsakey = RSA.importKey(arsa.exportKey())
rsakey = PKCS1_OAEP.new(rsakey)
decrypted = rsakey.decrypt(c_bytes)
print(decrypted)
主要就是从公钥里面把n和e取出来
然后把n分解出p、q
接着计算私钥d
然后传入RSA模块的构造函数,导出私钥。利用私钥对我们的密文进行求解即可