Second-order CPA on ASCAD traceset

This example shows how easy and fast it is to perform a second-order CPA at the example of a traceset from the ASCAD database.

The original HDF5 traceset of ASCAD (available from http://data.ascad-databases.ovh/ASCAD_data.zip, see ASCAD database for details) can be converted into the trs format using the accompanying Python script ascad2trs.py.

This example needs less than a minute to run. Compare this to the 2 hours reported in https://eprint.iacr.org/2018/196 for a Python implementation of second order analysis.

The accompanying non-notebook Julia script contains the multi-worker version of this code that can benefit from multiple cores on the same machine and in a cluster, as described in the HPC example.

The example also illustrates that the conditional leakage averaging approach can speed up the key recovery time while using more traces (set condavg parameter below to true).

For reference, the full correct key for the ASCAD source traceset is 0x4dfbe0f27221fe10a78d4adc8e490469. The traceset contains a range of samples for the recovery of only the 3rd key byte, which is 0xe0.

TODO: compare to Daredevil, add a test case to https://github.com/ikizhvatov/dpa-tools-benchmarking


In [1]:
using Jlsca.Trs
using Jlsca.Sca

Configure the attack


In [2]:
fname = "ASCAD.trs" # traceset file
nrTraces = 1000  # number of traces to attack
keyByteNum = 3   # key byte to attack; ASCAD examples and truncated traceset are for the 3rd key byte
condavg = false; # use conditional leakage averaging

In [3]:
trs = InspectorTrace(fname)


Opened ASCAD.trs, #traces 60000, #samples 700 (UInt8), #data 32
Out[3]:
InspectorTrace(0, 60000, 32, 1, UInt8, 700, 24, IOStream(<file ASCAD.trs>), "ASCAD.trs", 24, false, 18, true, MetaData(0, Pass[], Pass[], missing, missing, missing, true, #undef, #undef, #undef))

In [4]:
# attack parameters
attack = AesSboxAttack()
attack.xor = false
if condavg
    anal = CPA()
else
    anal = IncrementalCPA()
end
anal.leakages = [HW()]

params = DpaAttack(attack,anal)
maxCols = 150000 # Maximum number of samples processed in one tile. With more RAM this can be increased. Does not affect performance that much though for large values.
params.maxCols = maxCols
params.maxColsPost = maxCols
params.targetOffsets = [keyByteNum]
params.knownKey = "4dfbe0f27221fe10a78d4adc8e490469" |> hex2bytes

# add a pass doing second order combinations
reset(trs)
addSamplePass(trs, SecondOrderPass(AbsDiff()))

Run the attack


In [5]:
@time sca(trs, params, 1, nrTraces);


Jlsca running in Julia version: 1.3.0, 1 processes/1 workers/2 threads per worker

DPA parameters
attack:       AES Sbox CIPHER KL128 FORWARD
mode:         CIPHER
key length:   KL128
direction:    FORWARD
xor:          false
analysis:     Incremental CPA
leakages:     HW
maximization: abs global max
data at:      1
targets:      [3]
known key:    4dfbe0f27221fe10a78d4adc8e490469
max cols into post processor: 150000
max cols into non-inc analysis: 150000

phase: 1 / 1, #targets 16

Attacking columns 1:150000 out of 244650 columns (run 1 out of 2)
Running "Incremental correlation" on trace range 1:1:1000, 2 data passes, 1 sample passes
Processing traces 1:1000 ..100%|████████████████████████| Time: 0:00:06
Incremental CPA on range 1:150000 produced (150000, 256) correlation matrix
Results @ 1000 rows, 150000 cols (1000 rows consumed)
target: 3, phase: 1, #candidates 256
rank:   1, correct  : 0xe0, score: 0.167837 @ 98403
rank:   2, candidate: 0x12, score: 0.156420 @ 148771
rank:   3, candidate: 0x40, score: 0.155250 @ 122373
rank:   4, candidate: 0xc8, score: 0.153548 @ 37274
rank:   5, candidate: 0x13, score: 0.152902 @ 51456
recovered key material: e0
Attacking columns 150001:244650 out of 244650 columns (run 2 out of 2)
Running "Incremental correlation" on trace range 1:1:1000, 2 data passes, 1 sample passes
Processing traces 1:1000 ..100%|████████████████████████| Time: 0:00:02
Incremental CPA on range 150001:244650 produced (94650, 256) correlation matrix
Results @ 1000 rows, 244650 cols (1000 rows consumed)
target: 3, phase: 1, #candidates 256
rank:   1, correct  : 0xe0, score: 0.167837 @ 98403
rank:   2, candidate: 0xd6, score: 0.159440 @ 244643
rank:   3, candidate: 0x18, score: 0.157115 @ 224615
rank:   4, candidate: 0x12, score: 0.156420 @ 148771
rank:   5, candidate: 0x13, score: 0.155527 @ 158251
recovered key material: e0
 20.367717 seconds (29.73 M allocations: 4.825 GiB, 4.38% gc time)

In [6]:
# graceful cleanup
popSamplePass(trs)
popSamplePass(trs)
close(trs)