# Crack one-block VMAC with N=17 rounds # # The input data does not conform to the SHA-256 padding requirements. # import sha, random N = 17 # extract internal SHA-256 variables # def extract(H): h = (H - sha._H0[7]) & sha._mask; H >>= 32 g = (H - sha._H0[6]) & sha._mask; H >>= 32 f = (H - sha._H0[5]) & sha._mask; H >>= 32 e = (H - sha._H0[4]) & sha._mask; H >>= 32 d = (H - sha._H0[3]) & sha._mask; H >>= 32 c = (H - sha._H0[2]) & sha._mask; H >>= 32 b = (H - sha._H0[1]) & sha._mask; H >>= 32 a = (H - sha._H0[0]) & sha._mask; return (a,b,c,d,e,f,g,h) # extract V = T1 - offset = h + W[N-1] # # The previous round values a,b,c,d,e,f,g,T1,T2 can be determined directly, # but not h (see notes in file REVERSE here). # # T1 ~= h + (F XOR Key7), with T1 known, but h, F, and Key7 unknown. # def reverse( D, N, K): H = sha.VMAC( D, N, K) W = sha.W[N-1] hprev = sha.hprev (an,b,c,d,e,f,g,h) = extract(H) # a = b; b = c; c = d; e = f; f = g; g = h T2 = (sha.Sigma0(a) + sha.Maj(a,b,c)) & sha._mask T1 = (an - T2) & sha._mask V = (T1 - sha.Sigma1(e) - sha.Ch(e,f,g) - sha._K[N-1]) & sha._mask # if V != (hprev + W) & sha._mask: print( "error in reverse, V is wrong") return (V, W, hprev) for keyloop in range(1000): # random KEY # KEY = random.getrandbits(256) for dataloop in range(1000): # random or zero input Data # Data = random.getrandbits(512) #-- Data = 0 # set data bits 42,43 low # ones = (1 << 512) - 1 # 11...11 # for i in [42, 43]: Data &= (1 << i) ^ ones # with bits (43,42) = each 0 or 1 # # the hprev values will all be equal # (V00, W00, hprev00) = reverse( Data, 17, KEY) if (V00 & 7) == 0: # (V01, W01, hprev01) = reverse( Data | (1 << 42), 17, KEY) (V10, W10, hprev10) = reverse( Data | (1 << 43), 17, KEY) (V11, W11, hprev11) = reverse( Data | (1 << 43) | (1 << 42), 17, KEY) # # print( format( (((V00^V01) & 15) << 10) | (((V00^V10) & 15) << 6) | (((V00^V11) & 15) << 2) | hprev00 & 3, '014b') ) # print( format( ((V00 & 7) << 8) | (((V00^V01) & 7) << 5) | (((V00^V10) & 7) << 2) | hprev00 & 3, '011b') ) # print( format( (((V00^V01) & 7) << 7) | (((V00^V10) & 7) << 4) | (((V00^V11) & 7) << 1) | hprev00 & 1, '010b') ) print( format( ((V01 & 7) << 8) | ((V10 & 7) << 5) | ((V11 & 7) << 2) | hprev00 & 3, '011b') ) # print( format( ((V001 & 15) << 10) | ((V010 & 15) << 6) | ((V100 & 15) << 2) | hprev000 & 3, '014b') ) break # # x0 = (V00 ^ V01) >> 1) & 1 # # print() # print( "W00 =", format(W00,'032b')) # print( "W01 =", format(W01,'032b')) # print( "W10 =", format(W10,'032b')) # print( "W11 =", format(W11,'032b')) # print() # print( " h =", format(hprev00,'032b')) # print() # print( "V00 =", format(V00,'032b')) # print( "V01 =", format(V01,'032b')) # print( "V10 =", format(V10,'032b')) # print( "V11 =", format(V11,'032b')) # print() # print( " ", format( (V00^V01) & 7, '03b'), hprev00 & 1) # print( " ", format((V00-V01)&sha._mask,'032b')) # print( " ", format((V00-V10)&sha._mask,'032b')) # print( " ", format((V00-V11)&sha._mask,'032b')) # print( "h00 =", format(hprev00,'032b')) # print( "h01 =", format(hprev01,'032b')) # print( "h10 =", format(hprev10,'032b')) # print( "h11 =", format(hprev11,'032b'))