from Crypto.Util.number import * defgetM2(a,b,c1,c2,n,e): a3 = pow(a,e,n) b3 = pow(b,e,n) first = c1-a3*c2+2*b3 first = first % n second = e*b*(a3*c2-b3) second = second % n third = second*inverse(first,n) third = third % n fourth = (third+b)*inverse(a,n) return fourth % n e=0x3 a=1 b=-1 c1=0x5f4e03f28702208b215f39f1c8598b77074bfa238dfb9ce424af7cc8a61f7ea48ffbbd5a5e1a10f686c3f240e85d011f6c8b968d1d607b2e1d5a78ad6947b7d3ec8f33ad32489befab601fe745164e4ff4aed7630da89af7f902f6a1bf7266c9c95b29f2c69c33b93a709f282d43b10c61b1a1fe76f5fee970780d7512389fd1 c2=0x5f4e03f28702208b215f39f1c8598b77074bfa238dfb9ce424af7cc8a61f7ea48ffc5c26b0c12bcff9f697f274f59f0e55a147768332fc1f1bac5bbc8f9bb508104f232bdd20091d26adc52e36feda4a156eae7dce4650f83fabc828fdcfb01d25efb98db8b94811ca855a6aa77caff991e7b986db844ff7a140218449aaa7e8 padding2=1 n=0x9371c61a2b760109781f229d43c6f05b58de65aa2a674ff92334cb5219132448d72c1293c145eb6f35e58791669f2d8d3b6ce506f4b3543beb947cf119f463a00bd33a33c4d566c4fd3f4c73c697fa5f3bf65976284b9cc96ec817241385d480003cdda9649fa0995b013e66f583c9a9710f7e18396fbf461cb31720f94a0f79 m = getM2(a,b,c1,c2,n,e)-padding2 print(long_to_bytes(m))
#!/usr/bin/python ## OTP - Recovering the private key from a set of messages that were encrypted w/ the same private key (Many time pad attack) - crypto100-many_time_secret @ alexctf 2017 # @author intrd - http://dann.com.br/ # Original code by jwomers: https://github.com/Jwomers/many-time-pad-attack/blob/master/attack.py)
import string import collections import sets, sys
# 11 unknown ciphertexts (in hex format), all encrpyted with the same key
# XORs two string defstrxor(a, b):# xor two strings (trims the longer input) return"".join([chr(ord(x) ^ ord(y)) for (x, y) inzip(a, b)])
# To store the final key final_key = [None]*150 # To store the positions we know are broken known_key_positions = set()
# For each ciphertext for current_index, ciphertext inenumerate(ciphers): counter = collections.Counter() # for each other ciphertext for index, ciphertext2 inenumerate(ciphers): if current_index != index: # don't xor a ciphertext with itself for indexOfChar, char inenumerate(strxor(ciphertext.decode('hex'), ciphertext2.decode('hex'))): # Xor the two ciphertexts # If a character in the xored result is a alphanumeric character, it means there was probably a space character in one of the plaintexts (we don't know which one) if char in string.printable and char.isalpha(): counter[indexOfChar] += 1# Increment the counter at this index knownSpaceIndexes = []
# Loop through all positions where a space character was possible in the current_index cipher for ind, val in counter.items(): # If a space was found at least 7 times at this index out of the 9 possible XORS, then the space character was likely from the current_index cipher! if val >= 7: knownSpaceIndexes.append(ind) #print knownSpaceIndexes # Shows all the positions where we now know the key!
# Now Xor the current_index with spaces, and at the knownSpaceIndexes positions we get the key back! xor_with_spaces = strxor(ciphertext.decode('hex'),' '*150) for index in knownSpaceIndexes: # Store the key's value at the correct position final_key[index] = xor_with_spaces[index].encode('hex') # Record that we known the key at this position known_key_positions.add(index)
# Construct a hex key from the currently known key, adding in '00' hex chars where we do not know (to make a complete hex string) final_key_hex = ''.join([val if val isnotNoneelse'00'for val in final_key]) # Xor the currently known key with the target cipher output = strxor(target_cipher.decode('hex'),final_key_hex.decode('hex'))
print"Fix this sentence:" print''.join([char if index in known_key_positions else'*'for index, char inenumerate(output)])+"\n"
# WAIT.. MANUAL STEP HERE # This output are printing a * if that character is not known yet # fix the missing characters like this: "Let*M**k*ow if *o{*a" = "cure, Let Me know if you a" # if is too hard, change the target_cipher to another one and try again # and we have our key to fix the entire text!
#sys.exit(0) #comment and continue if u got a good key list1=' abcdefghijklmnopqrstuvwxyz'
for i inrange(26): for j inrange(26): for k inrange(26):
# print "Decrypted msg:" # for cipher in ciphers: # print strxor(cipher.decode('hex'),key)
# print "\nPrivate key recovered: "+key+"\n"
得到的密文为r*e** answer succks*ly
爆破恢复+猜测后,得到实际密文:rrect answer successly
明文段落:
1 2 3 4 5 6 7 8 9 10 11 12
Now you need to use th own flag as the key of Time Pad Encryptin. N hat you have passed th evious RSA test, this lenge is not particula please get the true me difficult for you. It ust simple encryption. pe you can solve this lem quickly and get th rrect answer successly
得到flag:flag{it_1s_P@dd1n_@nd_好恶心啊,缺了几个字符。
仔细看明文出来的,缺了字母,恶心坏了。
缺了4个字节,最后一个字节肯定是},复原第八行明文后异或爆破前三位,得到flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import random defxor_bytes(key_stream, message): length = min(len(key_stream), len(message)) returnbytes([key_stream[i]^ message[i] for i inrange(length)]) message = b"difficult for you. It is j" for i inrange(128): for j inrange(128): for k inrange(128): key_stream = b'flag{it_1s_P@dd1n_@nd_'+f'{chr(i)}'.encode()+f'{chr(j)}'.encode()+f'{chr(k)}'.encode()+b'}' cipher = xor_bytes(key_stream, message) if cipher.hex() == "02050701120a01334553393f32441d5e1b716027107f19334417": print(key_stream) print(cipher.hex()) print(xor_bytes(key_stream, cipher))
defmain(): rsakey = gen() a = RSA._RSAobj(None, rsakey) modBits = Crypto.Util.number.size(rsakey.n) k = ceil_div(modBits,8)
while (True): dosend("Welcome to this secure cryptosystem:") dosend("1.Get flag.\n2.Have my signature.\n3.Exit.\n4.Get my key.") dosend("What is your choice?")
import hashlib str1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890' for i inrange(len(str1)): for j inrange(len(str1)): for k inrange(len(str1)): message = '{0}{1}{2}Vw3UrFafQ94N5k4QB'.format(str1[i],str1[j],str1[k]) #print(message) m = hashlib.sha224() m.update(message.encode('utf-8')) c = m.hexdigest() if c == '6da53efa50c3ef1481cc0f403212262dd1bcead74d9f0b34f306318c': print (message) print(c)
rsa_sign:pow(m,d,p) e*d+n:3563329754048976946603729466426236052000141166700839903323255268203185709020494450173369806214666850943076188175778667508946270492708397447950521732324059148390232744011000065982865974194986726739638097566303135573072114448615095262066554751858952042395375417151593676621825939069783767865138657768553767717034970 e*d-n:3563121718917234588723786463275555826875232380691165919033718924958406353810813480184744219046717838078497090403751007254545187720107602959381881715875898243474504999760208133192572812110967142474619366650504948619637909653723376917174456091396220576841259798792078769198369072982063716206690589554604992470787752 tmp = e*d please sign the message with p:you_can_get_more_message please enter sign:
解答:
先简单的二元一次方程解出n和e*d的值。
1 2
len(bin(tmp))-2=1039 len(bin(n))-2=1024
可以发现,两者差了15位。
写一个脚本爆破phi的值。
1 2 3 4 5 6
phi=[] #11个 for i inrange(2**15,2**16): if ((tmp-1) // i) * i != tmp-1: continue else: phi.append((tmp-1) // i)
可以得到有11个可能的phi值。
随后用z3爆破,得到p和q
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from z3 import * x=Int('x') y=Int('y') s = Solver()
for i inrange(11): s.add(x*y==n) s.add(x+y==n-phi[i]+1) s.add(x>0) s.add(y>0)
if s.check()!=sat: continue else: print(phi[i]) print('x=',s.model()[x]) print('y=',s.model()[y]) continue
1 2 3 4
p = 10980405508174271259925333166343579553719061316941945190323939083665489902286168861229664589365210026388298173482496757264697996404794685064674668272479771 q = 9473016801951797771267846445459738473973421588058140695253031511700407533935872397264731631901174665159278878658035094231228063878480145556088206641042779 phi=104017565871178939971501575340112562454393004836992144768171622389677604840484994312793583974506432289548886013830127200541386300397244284320008224080452437410449815269897363953401430206474104816882552899007591140131802079961736224008071736969511510673117632180401571196581547933965545949203486211512709601060 #k=34256
然后的操作比较复杂,先素数分解tmp,得到因子
279位显然是可以忽略的,然后用以下代码判断e的因子。
1 2 3 4 5
e=[3,47,97,157,1601,21851,56277292709098311733] for i inrange(7): if tmp // e[i] == inverse(e[i],phi): print('e=',e[i]) #因子为:56277292709098311733
判断完因子后,使其互乘得到所有可能的e。代码来源于Wankko Ree大佬,用的算法类似于DFS。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
a=[3,47,97,157,1601,21851] b = set()
defgo(p, t): b.add(t) if p == len(a): return go(p+1, t*a[p]) go(p+1, t)
go(0, 1) c = list(b) for i inrange(len(b)): c[i]*=56277292709098311733 print(c)