我一直在Lua中使用RSA加密脚本,在BigNumbers(
http://oss.digirati.com.br/luabignum/bn/index.htm)的帮助下,我几乎有一个工作代码.但是,我被卡住了,因为在一小部分情况下,加密的原始邮件没有被解密为原始邮件,我无法弄清楚原因.请注意,这将处理非常大的数字(例如,1.08e107).我写的完整代码如下,但这里是它应该做的细分.
print(rsa_getkey())
p: 83
q: 23
n: 1909
e: 19
d: 1899
phi: 1804
以上设置键值,其中公钥由[n,e]表示,私钥由[n,d]表示.这是通过以下代码完成的:
function rsa_getkey()
rsa_e = 0
local primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 57, 71, 73, 79, 83, 89, 97}
math.randomseed = os.time()
rsa_p = primes[math.random(5,#primes)]
rsa_q = rsa_p
while rsa_q == rsa_p do
math.randomseed = os.time()
rsa_q = primes[math.random(5,#primes)]
end
rsa_n = rsa_p*rsa_q
rsa_phi = (rsa_p-1)*(rsa_q-1)
while rsa_e == 0 do
local prime = primes[math.random(1,10)]
if rsa_phi%prime > 0 then
rsa_e = prime
end
end
for i = 2, rsa_phi/2 do
if ((i*rsa_phi)+1)%rsa_e == 0 then
rsa_d = ((i*rsa_phi)+1)/rsa_e
break
end
end
return "p: ",rsa_p,"\nq: ",rsa_q,"\nn: ",rsa_n,"\ne: ",rsa_e,"\nd: ",rsa_d,"\nphi: ",rsa_phi,"\n"
end
确定密钥后,您可以加密消息.为了将纯文本(“Hello world”)转换为数字系统,我创建了一个不是100%完整的函数,但是以最基本的形式工作:
print(rsa_plaintext("Hello_world"))
1740474750625850534739
以下函数是确定消息的方式:
function rsa_plaintext(x)
local alphanum = {A=10, B=11, C=12, D=13, E=14, F=15, G=16, H=17, I=18, J=19, K=20, L=21, M=22, N=23, O=24, P=25, Q=26, R=27, S=28, T=29, U=30, V=31, W=32, X=33, Y=34, Z=35, a=36, b=37, c=38, d=39, e=40, f=41, g=42, h=43, i=44, j=45, k=46, l=47, m=48, n=49, o=50, p=51, q=52, r=53, s=54, t=55, u=56, v=57, w=58, x=59, y=60, z=61, _=62}
rsa_cipher = ""
for i = 1, #x do
local s = x:sub(i,i)
rsa_cipher = rsa_cipher .. alphanum[s]
end
return rsa_cipher
end
最后,为了使这个更易于管理,我必须将其细分为几个部分.为了节省时间和代码,我将实际加密与从明文到数字格式到加密的转换相结合,尽管我已经为调试目的添加了解密.该代码还考虑将0添加到消息中以确保每个分组中的4个数字.这是我的问题所在;消息和解密应该是相同的.
print(rsa_group("Hello world"))
Msg: 1740
Encrypted: 1560
Decrypted: 1740
Msg: 4747
Encrypted: 795
Decrypted: 929
Msg: 5062
Encrypted: 1659
Decrypted: 1244
Msg: 5850
Encrypted: 441
Decrypted: 123
Msg: 5347
Encrypted: 429
Decrypted: 1529
Msg: 3900
Encrypted: 1244
Decrypted: 82
这是通过以下两个功能完成的:
function rsa_group(str)
local cipher = {}
local str = rsa_plaintext(str:gsub(" ","_"))
local len = #str
local fillin = ""
if len%4 ~= 0 then
fillin = string.rep(0,(4-len%4))
end
str = str..fillin
for i = 1, #str, 4 do
local s,e = i, i+3
local part = str:sub(s,e)
print(rsa_encrypt(part))
end
end
function rsa_encrypt(msg)
bnrsa_e = BigNum.new(rsa_e)
bnrsa_n = BigNum.new(rsa_n)
bnmsg = BigNum.new(msg)
result = 0
quo = BigNum.new()
rsa_c = BigNum.new()
result = BigNum.pow(bnmsg, bnrsa_e)
BigNum.div(result, bnrsa_n, quo, rsa_c)
bnrsa_c = BigNum.new(rsa_c)
bnrsa_d = BigNum.new(rsa_d)
result = 0
quo = BigNum.new()
rsa_C = BigNum.new()
result = BigNum.pow(bnrsa_c, bnrsa_d)
BigNum.div(result, bnrsa_n, quo, rsa_C)
return "Msg:",msg,"\nEncrypted:",rsa_c,"\nDecrypted:",rsa_C,"\n"
end
现在,我知道这是一个很长的问题,问题本身有很多组成部分.我不知道如何找出问题所在.有什么我想念的吗?一双新鲜的眼睛可能是我的解决方案.
最佳答案 经过仔细检查,看起来消息M必须是你的两个素数的
less than the product n.在上面的测试用例中,除了第一个消息之外的所有消息都未能正确解密,因为它们大于n = 1909.
例如,考虑M刚超过n = 1909的位置:
Msg: 1910
Encrypted: 1
Decrypted: 1
Msg: 1911
Encrypted: 1222
Decrypted: 2
Msg: 1912
Encrypted: 1179
Decrypted: 3
在现实世界的例子中,n当然要大得多,因此这个问题不太可能出现.