aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJán Jančár2023-10-10 16:48:30 +0200
committerGitHub2023-10-10 16:48:30 +0200
commitfdab7fb1c85a9d4137312b8fdb252b1fab6aa1bc (patch)
tree77750148677c9168146a30a56350df8332ed144b
parent0e300b7b532d1796fc2dbea6f09e326b856f866a (diff)
parent79ec70d0b1acf681f73d478e775825a6f35ae1e6 (diff)
downloadpyecsca-fdab7fb1c85a9d4137312b8fdb252b1fab6aa1bc.tar.gz
pyecsca-fdab7fb1c85a9d4137312b8fdb252b1fab6aa1bc.tar.zst
pyecsca-fdab7fb1c85a9d4137312b8fdb252b1fab6aa1bc.zip
Merge pull request #44 from andrr3j/CPA_pyecsca
Add CPA
-rw-r--r--pyecsca/sca/attack/CPA.py78
-rw-r--r--pyecsca/sca/target/emulator.py8
2 files changed, 82 insertions, 4 deletions
diff --git a/pyecsca/sca/attack/CPA.py b/pyecsca/sca/attack/CPA.py
new file mode 100644
index 0000000..667078c
--- /dev/null
+++ b/pyecsca/sca/attack/CPA.py
@@ -0,0 +1,78 @@
+from pyecsca.ec.mult import ScalarMultiplier
+from pyecsca.ec.point import Point
+from pyecsca.ec.context import DefaultContext, local
+from pyecsca.ec.params import DomainParameters
+from pyecsca.ec.mod import Mod
+from pyecsca.sca.trace import Trace
+from public import public
+from scipy.stats import pearsonr
+from pyecsca.sca.attack.leakage_model import LeakageModel
+import numpy as np
+from numpy.typing import NDArray
+
+
+@public
+class CPA():
+
+ traces: NDArray
+ points: list[Point]
+ mult: ScalarMultiplier
+ params: DomainParameters
+ leakage_model: LeakageModel
+
+ def __init__(self, points: list[Point], traces: list[Trace], leakage_model: LeakageModel, mult: ScalarMultiplier, params: DomainParameters):
+ '''
+ :param points: Points on which scalar multiplication with secret scalar was performed
+ :param traces: Power traces corresponding to the scalar multiplication for each of the points
+ :param mult: Scalar multiplier used
+ :param params: Domain parameters used
+ '''
+ self.points = points
+ self.traces = np.array([trace.samples for trace in traces]).transpose()
+ self.mult = mult
+ self.params = params
+ self.leakage_model = leakage_model
+
+ def compute_intermediate_value(self, guessed_scalar: int, target_bit: int, point: Point) -> Mod:
+ with (local(DefaultContext())) as ctx:
+ self.mult.init(self.params, point)
+ self.mult.multiply(guessed_scalar)
+ action_index = -1
+ for bit in bin(guessed_scalar)[2:target_bit + 2]:
+ if bit == '1':
+ action_index += 2
+ elif bit == '0':
+ action_index += 1
+ result = ctx.actions.get_by_index([0, action_index])[0]
+ return result.output_points[0].X
+
+ def compute_correlation_trace(self, guessed_scalar: int, target_bit: int) -> list[float]:
+ correlation_trace = []
+ intermediate_values = []
+ for i in range(len(self.points)):
+ intermediate_value = self.compute_intermediate_value(guessed_scalar, target_bit, self.points[i])
+ intermediate_values.append(self.leakage_model(intermediate_value))
+ for trace in self.traces:
+ correlation_trace.append(pearsonr(intermediate_values, trace)[0])
+ return correlation_trace
+
+ def recover_bit(self, recovered_scalar: int, target_bit: int, scalar_bit_length: int, real_pub_key: Point) -> int:
+ if target_bit == scalar_bit_length - 1:
+ self.mult.init(self.params, self.params.generator)
+ if real_pub_key == self.mult.multiply(recovered_scalar):
+ return recovered_scalar
+ return recovered_scalar | 1
+ mask = 1 << (scalar_bit_length - target_bit - 1)
+ guessed_scalar_0 = recovered_scalar
+ guessed_scalar_1 = recovered_scalar | mask
+ correlation_trace_0 = self.compute_correlation_trace(guessed_scalar_0, target_bit)
+ correlation_trace_1 = self.compute_correlation_trace(guessed_scalar_1, target_bit)
+ if np.nanmax(np.abs(correlation_trace_0)) > np.nanmax(np.abs(correlation_trace_1)):
+ return guessed_scalar_0
+ return guessed_scalar_1
+
+ def perform(self, scalar_bit_length: int, real_pub_key: Point) -> int:
+ recovered_scalar = 1 << (scalar_bit_length - 1)
+ for target_bit in range(1, scalar_bit_length):
+ recovered_scalar = self.recover_bit(recovered_scalar, target_bit, scalar_bit_length, real_pub_key)
+ return recovered_scalar
diff --git a/pyecsca/sca/target/emulator.py b/pyecsca/sca/target/emulator.py
index 3bb2085..bca27cf 100644
--- a/pyecsca/sca/target/emulator.py
+++ b/pyecsca/sca/target/emulator.py
@@ -2,16 +2,16 @@ from pyecsca.ec.coordinates import CoordinateModel
from pyecsca.ec.mod import Mod
from pyecsca.ec.model import CurveModel
from pyecsca.ec.params import DomainParameters
-from pyecsca.ec.point import Point, InfinityPoint
+from pyecsca.ec.point import Point
from pyecsca.ec.mult import ScalarMultiplier
from pyecsca.ec.key_generation import KeyGeneration
from pyecsca.ec.key_agreement import KeyAgreement
from pyecsca.ec.signature import Signature, SignatureResult
from pyecsca.ec.formula import FormulaAction
-from pyecsca.ec.context import Context, DefaultContext, local
+from pyecsca.ec.context import DefaultContext, local
from pyecsca.sca.attack import LeakageModel
-from pyecsca.sca.trace import Trace, average, subtract
-from typing import Mapping, Union, Optional, Tuple
+from pyecsca.sca.trace import Trace
+from typing import Optional, Tuple
from public import public
from .base import Target
import numpy as np