【CISCN2018-Crypto】 crackme-java解析
2021/6/9 12:24:03
本文主要是介绍【CISCN2018-Crypto】 crackme-java解析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
今天闲着无事,于是翻到了buu密码学的最后一页,看到了一道名字带java的题,还是很亲切的,于是花了一点时间做出来了,发现网上相关的wp较少,于是有了这篇wp,一步一步分析。
1.原题
- 题目为crackme-java,包含一个java源文件,没有其它提示。
import java.math.BigInteger; import java.util.Random; public class Test1 { static BigInteger two =new BigInteger("2"); static BigInteger p = new BigInteger("11360738295177002998495384057893129964980131806509572927886675899422214174408333932150813939357279703161556767193621832795605708456628733877084015367497711"); static BigInteger h= new BigInteger("7854998893567208831270627233155763658947405610938106998083991389307363085837028364154809577816577515021560985491707606165788274218742692875308216243966916"); /* Alice write the below algorithm for encryption. The public key {p, h} is broadcasted to everyone. @param val: The plaintext to encrypt. We suppose val only contains lowercase letter {a-z} and numeric charactors, and is at most 256 charactors in length. */ public static String pkEnc(String val){ BigInteger[] ret = new BigInteger[2]; BigInteger bVal=new BigInteger(val.toLowerCase(),36); BigInteger r =new BigInteger(new Random().nextInt()+""); ret[0]=two.modPow(r,p); ret[1]=h.modPow(r,p).multiply(bVal); return ret[0].toString(36)+"=="+ret[1].toString(36); } /* Alice write the below algorithm for decryption. x is her private key, which she will never let you know. public static String skDec(String val,BigInteger x){ if(!val.contains("==")){ return null; } else { BigInteger val0=new BigInteger(val.split("==")[0],36); BigInteger val1=new BigInteger(val.split("==")[1],36); BigInteger s=val0.modPow(x,p).modInverse(p); return val1.multiply(s).mod(p).toString(36); } } */ public static void main(String[] args) throws Exception { System.out.println("You intercepted the following message, which is sent from Bob to Alice:"); System.out.println("a9hgrei38ez78hl2kkd6nvookaodyidgti7d9mbvctx3jjniezhlxs1b1xz9m0dzcexwiyhi4nhvazhhj8dwb91e7lbbxa4ieco==2q17m8ajs7509yl9iy39g4znf08bw3b33vibipaa1xt5b8lcmgmk6i5w4830yd3fdqfbqaf82386z5odwssyo3t93y91xqd5jb0zbgvkb00fcmo53sa8eblgw6vahl80ykxeylpr4bpv32p7flvhdtwl4cxqzc"); System.out.println("Please figure out the plaintext!"); } } //a9hgrei38ez78hl2kkd6nvookaodyidgti7d9mbvctx3jjniezhlxs1b1xz9m0dzcexwiyhi4nhvazhhj8dwb91e7lbbxa4ieco==2q17m8ajs7509yl9iy39g4znf08bw3b33vibipaa1xt5b8lcmgmk6i5w4830yd3fdqfbqaf82386z5odwssyo3t93y91xqd5jb0zbgvkb00fcmo53sa8eblgw6vahl80ykxeylpr4bpv32p7flvhdtwl4cxqzc
2.加解密算法分析
- 题目给出了加密和解密的算法,给出了一组密文,要求明文。
- 该加密算法可以用如下数学公式表示:
2 r M o d p = C 1 ( h r M o d p ) ∗ M = C 2 C = C 1 + C 2 2^{r} Mod\ p = C_{1}\\ (h^{r} Mod\ p) *M = C_{2}\\ C = C_{1}+C_{2} 2rMod p=C1(hrMod p)∗M=C2C=C1+C2
-
其中
{p,h}
是公钥,M
是明文,C
是密文,r
是int范围内的随机数。 -
该解密算法可以用如下数学公式表示:
s = ( C 1 x M o d p ) − 1 M o d p M = ( C 2 ∗ s ) M o d p s=(C_{1}^{x} Mod\ p)^{-1} Mod\ p\\ M=(C_{2}*s)\ Mod\ p s=(C1xMod p)−1Mod pM=(C2∗s) Mod p
- 其中
{x}
是私钥。私钥我们无从得到。 - 我们分析加密算法,可以发现,
{h,p,C1,C2}
都是已知的,只有r
是未知的。如果知道了r
,那么明文可以表示为:
M = C 2 / ( p o w ( h , r , p ) ) M=C_{2}/(pow(h,r,p)) M=C2/(pow(h,r,p))
- 而
r
是int范围内的随机数,共32位,完全可以爆破出来,r
位数较少即是该加密算法的弱点。
3.r枚举攻击
- 一共32位,视CPU的核数,我们可以开32个线程去爆破。
- 大概40分钟左右可以跑出来。放到服务器上可以更快。
from threading import Thread p=11360738295177002998495384057893129964980131806509572927886675899422214174408333932150813939357279703161556767193621832795605708456628733877084015367497711 c1=int('a9hgrei38ez78hl2kkd6nvookaodyidgti7d9mbvctx3jjniezhlxs1b1xz9m0dzcexwiyhi4nhvazhhj8dwb91e7lbbxa4ieco',36) def calr(r0,pid): print("[Process%d]: start from %d" % (pid, r0)) while r0 < 2**26*(pid+1): if pow(2,r0,p) == c1: f = open('r','w') f.write(r0) exit(0) r0+=1 if r0 % 2**18 == 0: print('[Process%d]: now %d' % (pid, r0)) print('[Process%d]: exited!' % pid) for i in range(0,32): t = Thread(target=calr,args=(i*2**26,i)) t.start()
- 最后得到r的值为:
152351913
4.解得明文
- 所有参数已知,可以解得明文M:
import base36 p = 11360738295177002998495384057893129964980131806509572927886675899422214174408333932150813939357279703161556767193621832795605708456628733877084015367497711 c1 = int('a9hgrei38ez78hl2kkd6nvookaodyidgti7d9mbvctx3jjniezhlxs1b1xz9m0dzcexwiyhi4nhvazhhj8dwb91e7lbbxa4ieco',36) c2 = int('2q17m8ajs7509yl9iy39g4znf08bw3b33vibipaa1xt5b8lcmgmk6i5w4830yd3fdqfbqaf82386z5odwssyo3t93y91xqd5jb0zbgvkb00fcmo53sa8eblgw6vahl80ykxeylpr4bpv32p7flvhdtwl4cxqzc', 36) h = int("7854998893567208831270627233155763658947405610938106998083991389307363085837028364154809577816577515021560985491707606165788274218742692875308216243966916") r = 152351913 print(base36.dumps(c2//pow(h,r,p)))
-
细节:使用双除号,使用base36实现十进制转36进制。
-
明文(flag):
ciscncongratulationsthisisdesignedbyalibabasecurity424218533
ATFWUS 2021-06-09
这篇关于【CISCN2018-Crypto】 crackme-java解析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南