Advertisement
stiansjogren

To

Jun 12th, 2016
268
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.47 KB | None | 0 0
  1. #! /usr/bin/env python2
  2. import tr_pcc
  3. import sys
  4. import argparse
  5. import des
  6. import traces
  7. # The P permutation table, as in the standard. The first entry (16) is the
  8. # position of the first (leftmost) bit of the result in the input 32 bits word.
  9. # Used to convert target bit index into SBox index (just for printed summary
  10. # after attack completion).
  11. p_table = [16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25]
  12.  
  13. def hamming_weight (v):
  14.     v = v - ((v>>1) & 0x5555555555555555)
  15.     v = (v & 0x3333333333333333) + ((v>>2) & 0x3333333333333333)
  16.     return (((v + (v>>4) & 0xF0F0F0F0F0F0F0F) * 0x101010101010101) >> 56) & 0xFF
  17. def hamming_distance(n1,n2):
  18.     return hamming_weight(n1^n2)
  19. def main ():
  20.     # ************************************************************************
  21.     # * Before doing anything else, check the correctness of the DES library *
  22.     # ************************************************************************
  23.     if not des.check ():
  24.         sys.exit ("DES functional test failed")
  25.  
  26.  
  27.     # *************************************
  28.     # * Check arguments and read datafile *
  29.     # *************************************
  30.     argparser = argparse.ArgumentParser(description="Apply P. Kocher's DPA algorithm based on decision function")
  31.     argparser.add_argument("datafile", metavar='FILE',
  32.                         help='name of the traces file in HWSec format. (e.g.  pa.dat)')
  33.     argparser.add_argument("n", metavar='N', type=int,
  34.                         help='number of acquisitions to use')
  35.     argparser.add_argument("target_bit", metavar='[B]', type=int, nargs='?', default=1,
  36.                         help='index of target bit in L15 (1 to 32, as in DES standard, default: 1)')
  37.     args = argparser.parse_args()
  38.  
  39.     if args.n < 1:                                      # If invalid number of acquisitions.
  40.         sys.exit ("Invalid number of acquisitions: %d (shall be greater than 1)" % args.n)
  41.  
  42.     if args.target_bit < 1 or args.target_bit > 32:     # If invalid target bit index.
  43.         sys.exit ("Invalid target bit index: %d (shall be between 1 and 32 included)" % args.target_bit)
  44.  
  45.     # Compute index of corresponding SBox
  46.     target_sbox = (p_table[args.target_bit - 1] - 1) / 4 + 1
  47.     # Read power traces and ciphertexts. n is the number of acquisitions to use.
  48.     ctx = read_datafile (args.datafile, args.n)
  49.     print >> sys.stderr, 'Hey'
  50.     print >> sys.stderr, 'Hope you have had a nice day ! :)'
  51.     # ***************************************************************
  52.     dpa_attack (ctx)
  53.     #print >> sys.stderr, "target bit %d" % args.target_bit
  54.     #dpa_attack(ctx, 1)
  55.     # *******************************************************************************
  56.     # * Print the 64 DPA traces in a data file named dpa.dat. Print corresponding   *
  57.     # * gnuplot commands in a command file named dpa.cmd. All DPA traces are        *
  58.     # * plotted in blue but the one corresponding to the best guess which is        *
  59.     # * plotted in red with the title "Trace X (0xY)" where X and Y are the decimal *
  60.     # * and heaxdecimal forms of the 6 bits best guess.                             *
  61.     # *******************************************************************************
  62.     # Plot DPA traces in dpa.dat, gnuplot commands in dpa.cmd
  63.  
  64.  
  65.     # *****************
  66.     # * Print summary *
  67.     # *****************
  68.     #print >> sys.stderr, "Target bit: %d" % args.target_bit
  69.     #print >> sys.stderr, "Target SBox: %d" % target_sbox
  70.     #print >> sys.stderr, "Best guess: %d (0x%02x)" % (best_guess, best_guess)
  71.     #print >> sys.stderr, "Maximum of DPA trace: %e" % best_max
  72.     #print >> sys.stderr, "Index of maximum in DPA trace: %d" % best_idx
  73.     #print >> sys.stderr, "DPA traces stored in file 'dpa.dat'. In order to plot them, type:"
  74.     #print >> sys.stderr, "$ gnuplot -persist dpa.cmd"
  75.  
  76.     # ************************
  77.     # * Print last round key *
  78.     # ************************
  79.    
  80.  
  81.  
  82. # A function to allocate cipher texts and power traces, read the
  83. # datafile and store its content in allocated context.
  84. def read_datafile (name, n):
  85.     ctx = traces.trContext (name, n)
  86.     if ctx.n != n:
  87.         sys.exit ("Could not read %d acquisitions from traces file. Traces file contains %d acquisitions." % (n, ctx.n));
  88.  
  89.     return ctx
  90.  
  91.  
  92. # Apply P. Kocher's DPA algorithm based on decision function. Computes 64 DPA
  93. # traces dpa[0..63], best_guess (6-bits subkey corresponding to highest DPA
  94. # peak), best_idx (index of sample with maximum value in best DPA trace) and
  95. # best_max (value of sample with maximum value in best DPA trace).
  96. def dpa_attack (ctx):
  97.     pcc = [0]*64
  98.     sbomask = 0xf0000000
  99.     key=[]
  100.     for sbox in range(8):
  101.         print >> sys.stderr, 'Calculating subkey for Sbox number: ' + str(sbox)
  102.         ctx_pcc = tr_pcc.pccContext(ctx.l,64) # pccContext object
  103.         for i in range(ctx.n):
  104.             ct = ctx.c[i]
  105.             r16l16 = des.ip(ct)
  106.             l16    = des.right_half(r16l16)
  107.             r15    = l16
  108.             r16    = des.left_half(r16l16)
  109.             er15   = des.e(l16)
  110.             ctx_pcc.insert_x(ctx.t[i][:])
  111.             rk= 0x0
  112.             for j in range(64):
  113.                 l15 = r16^des.p(des.sboxes(er15^rk))
  114.                 r14 = l15
  115.                 ctx_pcc.insert_y(j, int(hamming_distance(r14 & des.p(sbomask), r15 & des.p(sbomask))))
  116.                 rk+= 0x041041041041
  117.         ctx_pcc.consolidate()
  118.         dpa = list([ctx_pcc.get_pcc(g) for g in range(64)])
  119.         maxs = [max(l) for l in dpa]
  120.         idx = [l.index(m) for l,m in zip (dpa, maxs)]
  121.         # Get best maximum
  122.         best_max = max (maxs)
  123.         best_guess = maxs.index (best_max)
  124.         best_idx = idx[best_guess]
  125.         sbomask = sbomask >> 4
  126.         key.append(best_guess)
  127.         print >> sys.stderr, 'Subkey for Sbox nr. ' + str(sbox) +'are ' + str(hex(best_guess))
  128.         #traces.plot('sboxnr' + str(sbox), -1, dpa) # Plot the traces for each sbox
  129.     # Format output
  130.     res = ''
  131.     for i in range(len(key)):
  132.         res +=  bin(key[i])[2:].zfill(6)
  133.     print hex(int(res,2))
  134.    
  135. def shit_i_dont_like (ctx, target_bit):
  136.     t0 = [[0.0] * ctx.l] * 64
  137.     n0 = [0] * 64
  138.     t1 = [[0.0] * ctx.l] * 64
  139.     n1 = [0] * 64
  140.     for ct, t in zip (ctx.c, ctx.t):                        # For all acquisitions
  141.         d = decision (ct, target_bit)                       # Compute the 64 decisions
  142.  
  143.         # For all guesses (64)
  144.         for g in xrange (64):
  145.             if d[g] == 0:                                   # If decision on target bit is zero
  146.                 t0[g] = [a+b for a,b in zip (t0[g], t)]     # Accumulate power trace in zero-set
  147.                 n0[g] += 1                                  # Increment traces count for zero-set
  148.             else:                                           # If decision on target bit is one
  149.                 t1[g] = [a+b for a,b in zip (t1[g], t)]     # Accumulate power trace in one-set
  150.                 n1[g] += 1                                  # Increment traces count for one-set
  151.     #DPA=[]
  152.     #for g in range(64):
  153.         #DPA[g] = sum(t1)/float(len(t1))          
  154.     # Compute normalized one-set minus zero-set
  155.     dpa = [[t1[g][i]/n1[g] - t0[g][i]/n0[g] for i in xrange (ctx.l)] for g in xrange (64)]
  156.  
  157.     # Get max and argmax for each guess
  158.     maxs = [max(l) for l in dpa]
  159.     idx = [l.index(m) for l,m in zip (dpa, maxs)]
  160.  
  161.     # Get best maximum
  162.     best_max = max (maxs)
  163.     best_guess = maxs.index (best_max)
  164.     best_idx = idx[best_guess]
  165.  
  166.     return dpa, best_guess, best_max, best_idx
  167.  
  168.  
  169.  
  170. if __name__ == "__main__":
  171.     main ()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement