def fixError (res,k,m,t): global errors errors+=1 #remove the last partial results #for i in range(0,sampleSize): # res[0][i].pop() # res[1][i].pop() k<<=1 #add a random bit; will be deleted at the beginning of the loop print "Trying to fix the error by backtracking at most "+str(len(res[0][0]))+" bits." while (len(res[0][0])>1): #while I still have previous results that I can use k>>=1 #remove a bit from the key k^=1 #flip the last bit #if I have already changed that bit once, give up if (k&1) == initial_guess[bits(k)-1]: return 0, res #print "Removed one bit" #print "1011111110001100011110011001001001001010111110011101001010000101" print "{0:b}".format(k) print "===================" for i in range(0,sampleSize): res[0][i].pop() #remove the partial results corresponding to the last removed bit res[1][i].pop() #remove the partial results corresponding to the last removed bit if test_errorFix(res,k,m,t): #temp,temp,res = classify(res,m,n,omega,k&1) return k,res return 0,res
def main(m,t,res,maxLength): global errors, threshold_difference, initial_guess errors = 0 threshold_difference = threshold_difference_init print "Starting the attack" # Temporary memory to save partial results of the exponentiation when # assuming the last bit of the key is 0 or 1 lastBit = 1 key_guess = 1; initial_guess.append(1); B = 1 # number of bits in the guessed key H = 1 # hamming weight of the guessed key average = deque([],average_n) lastError = -2 while (maxLength-B-H>0): if (maxLength-B-H<threshold_brute): print "Switch to brute forcing the key" result = brute(key_guess,B,H,maxLength) if result!=0: return result print "There might have been an error in the key before brute force" key_guess,res = fixError(res,key_guess,m,t) if key_guess==0: return -1 else: threshold_difference*=1.05 lastError = B B = bits(key_guess) H = hammingWeight(key_guess) average = deque([],average_n) lastBit = key_guess & 1 print "FIXED" print "{0:b}".format(key_guess) continue u0,u1,res = classify(res,m,n,omega,lastBit) # If the average of abs(u0-u1) for the past 'average_n' iterations drops # under 'threshold_difference' stop the attack and increase the sample # size; # Thresholding the average for the past few iterations and not just the # last result reduces the chance of getting a false positive in the # error detection; I deduced this from trial and error and from the # graph presented in the given paper [1] average.append(abs(u0-u1)) if (len(average)==average_n) and (sum(average) < (threshold_difference * len(average))): #if B-lastError>5: #threshold_difference*=1.05 print "Error detected. Trying to fix it" key_guess,res = fixError(res,key_guess,m,t) if key_guess!=0: #key_guess = ((key_guess>>2)<<1)|(key_guess&1) lastError = B B = bits(key_guess) H = hammingWeight(key_guess) average = deque([],average_n) lastBit = key_guess & 1 print "FIXED" print "{0:b}".format(key_guess) continue print "The difference between deviation of means is not big enough" print sum(average)/average_n return -1 # Append the guessed bit to the key and save the partial results of the # exponentiation in x key_guess = key_guess<<1 B+=1 lastBit = 0 if u1>u0: key_guess +=1 H+=1 lastBit = 1 if B == len(initial_guess)+1: initial_guess.append(lastBit); print "{0:b}".format(key_guess) return -1 print "Switch to brute forcing the key" return brute(key_guess,B,H,maxLength)
if B == len(initial_guess)+1: initial_guess.append(lastBit); print "{0:b}".format(key_guess) return -1 print "Switch to brute forcing the key" return brute(key_guess,B,H,maxLength) if __name__ == "__main__": if len(sys.argv) != 3: raise Excepton("Incorrect number of arguments") exe_name = "./"+sys.argv[1] params_file = open(sys.argv[2]) n = int(params_file.readline(),16) e = int(params_file.readline(),16) n_length = bits(n) #get parameters for the MontMul rho2 = getRho2(n) omega = getOmega(n) #start the oracle as a subprocess and pipe the input/output exe = subprocess.Popen(exe_name, stdout = subprocess.PIPE, stdin = subprocess.PIPE) exe_in = exe.stdin exe_out = exe.stdout # Get decryption time for c=0; # It will be used to calculate: # maxLength = bit_length(d)+hamming_weight(d)