Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Elliptic Curve Cryptography Attack Methods and Practical Examples

Tech May 9 3

Elliptic Curve Cryptography (ECC) presents several attack scenarios depending on curve parameters. This analysis covers discrete logarithm computation, Smart's attack, and the Pohlig-Hellman algorithm with practical implementations.

Discrete Logarithm Function

The discrete_log() function provides a general-purpose solution for elliptic curve discrete logarithm problems:

discrete_log(target_point, base_point, order=None, operation='+')

This function computes the logarithm of target_point relative to base_point. The order parameter specifies the base point's order, while operation defaults to elliptic curve point addition.

Smart's Attack Implementation

Smart's attack applies when the curve's order equals the field characteristic (anomalous curves).

def smart_attack(P, Q, prime):
    curve = P.curve()
    # Lift curve to p-adic numbers
    E_padic = EllipticCurve(Qp(prime, 2), 
                           [ZZ(coeff) + randint(0,prime)*prime 
                            for coeff in curve.a_invariants()])
    
    # Lift points to p-adic field
    P_padic_points = E_padic.lift_x(ZZ(P.xy()[0]), all=True)
    for P_padic in P_padic_points:
        if GF(prime)(P_padic.xy()[1]) == P.xy()[1]:
            break
    
    Q_padic_points = E_padic.lift_x(ZZ(Q.xy()[0]), all=True)
    for Q_padic in Q_padic_points:
        if GF(prime)(Q_padic.xy()[1]) == Q.xy()[1]:
            break
    
    # Compute p-multiples
    pP = prime * P_padic
    pQ = prime * Q_padic
    
    xP, yP = pP.xy()
    xQ, yQ = pQ.xy()
    
    # Calculate p-adic logarithms
    phi_P = -(xP / yP)
    phi_Q = -(xQ / yQ)
    
    return ZZ(phi_Q / phi_P)

secret = smart_attack(P, Q, p)

Pohlig-Hellman Algorithm

The Pohlig-Hellman method works when the curve order factors into small primes.

def pohlig_hellman(curve_order, generator, target):
    factors = list(factor(curve_order))
    prime_powers = [factors[i][0] ** factors[i][1] 
                   for i in range(len(factors))][:-1]
    
    discrete_logs = []
    for prime in prime_powers:
        multiplier = curve_order // prime
        log_val = discrete_log(multiplier * target, 
                              multiplier * generator, 
                              operation="+")
        discrete_logs.append(log_val)
    
    return crt(discrete_logs, prime_powers)

solution = pohlig_hellman(n, G, H)

ECC Challenge Analysis

A three-part challenge demonstrates these techniques:

Part 1: Direct Discrete Logarithm

p = 146808027458411567
curve = EllipticCurve(GF(p), [46056180, 2316783294673])
P = curve(119851377153561800, 50725039619018388)
Q = curve(22306318711744209, 111808951703508717)

result = discrete_log(Q, P, operation='+')

Part 2: Pohlig-Hellman Application

p = 1256438680873352167711863680253958927079458741172412327087203
curve = EllipticCurve(GF(p), [377999945830334462584412960368612, 
                             604811648267717218711247799143415167229480])
G = curve(550637390822762334900354060650869238926454800955557622817950,
          700751312208881169841494663466728684704743091638451132521079)
H = curve(1152079922659509908913443110457333432642379532625238229329830,
          819973744403969324837069647827669815566569448190043645544592)

n = curve.order()
answer = pohlig_hellman(n, G, H)

Part 3: Smart's Attack Deployment

p = 0xd3ceec4c84af8fa5f3e9af91e00cabacaaaecec3da619400e29a25abececfdc9bd678e2708a58acb1bd15370acc39c596807dab6229dca11fd3a217510258d1b
curve = EllipticCurve(GF(p), [0x95fc77eb3119991a0022168c83eee7178e6c3eeaf75e0fdf1853b8ef4cb97a9058c271ee193b8b27938a07052f918c35eccb027b0b168b4e2566b247b91dc07,
                              0x926b0e42376d112ca971569a8d3b3eda12172dfb4929aea13da7f10fb81f3b96bf1e28b4a396a1fcf38d80b463582e45d06a548e0dc0d567fc668bd119c346b2])
G = curve(10121571443191913072732572831490534620810835306892634555532657696255506898960536955568544782337611042739846570602400973952350443413585203452769205144937861,
          8425218582467077730409837945083571362745388328043930511865174847436798990397124804357982565055918658197831123970115905304092351218676660067914209199149610)
H = curve(964864009142237137341389653756165935542611153576641370639729304570649749004810980672415306977194223081235401355646820597987366171212332294914445469010927,
          5162185780511783278449342529269970453734248460302908455520831950343371147566682530583160574217543701164101226640565768860451999819324219344705421407572537)

key = smart_attack(G, H, p)

AES-ECC Hybrid Encryption

Some challenges combine ECC with symmetric encryption:

# Recover ECC secret
p = 12506217790875063466368723611056175369923
curve = EllipticCurve(GF(p), [12506217790875063466368723611052784275139,
                              12506217790875063466368723533070038257347])
G = curve(7493372729181057645036574086903590138065, 359098907392057890604329721532958479621)
H = curve(9505420031620208163682758801913524369821, 5460936589331844194485299189975059431657)

secret = smart_attack(G, H, p)

# Decrypt AES payload
from Crypto.Cipher import AES
import hashlib

key = hashlib.sha256(str(secret).encode()).digest()[:16]
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)

Invalid Point Attacks

When points don't satisfy the curve equation but standard formulas are used:

def point_addition(P1, P2, modulus, a_coeff):
    if P1 is None: return P2
    if P2 is None: return P1
    
    x1, y1 = P1
    x2, y2 = P2
    
    if x1 == x2 and (y1 + y2) % modulus == 0:
        return None
        
    if x1 == x2:
        lam = (3 * x1 * x1 + a_coeff) * pow(2 * y1, -1, modulus) % modulus
    else:
        lam = (y2 - y1) * pow(x2 - x1, -1, modulus) % modulus
    
    x3 = (lam * lam - x1 - x2) % modulus
    y3 = (lam * (x1 - x3) - y1) % modulus
    return (x3, y3)

def baby_step_giant_step(generator, target, modulus, curve_a, max_steps=1<<16):
    baby_steps = {}
    current = None
    
    for j in range(max_steps):
        baby_steps[current] = j
        current = point_addition(current, generator, modulus, curve_a)
    
    step_size = max_steps
    giant_step = current
    neg_giant = (giant_step[0], (-giant_step[1]) % modulus)
    
    current_point = target
    for i in range(max_steps + 1):
        if current_point in baby_steps:
            return i * max_steps + baby_steps[current_point]
        current_point = point_addition(current_point, neg_giant, modulus, curve_a)
    
    return None

XOR-Based ECC Encryption

Some challenges use ECC secrets for stream cipher-like encryption:

# Recover XOR key from known plaintext
ciphertext_hex = 'ac73a774a25bd512d543dc468542c9428141800dd041d043c918d112850dd515d6128214d1138211d71599'
encrypted = bytes.fromhex(ciphertext_hex)

# Assume known plaintext header
xor_key = [encrypted[0] ^ ord('H'), encrypted[1] ^ ord('S')]

plaintext = ''
for i in range(len(encrypted)):
    plaintext += chr(encrypted[i] ^ xor_key[i % 2])

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

SBUS Signal Analysis and Communication Implementation Using STM32 with Fus Remote Controller

Overview In a recent project, I utilized the SBUS protocol with the Fus remote controller to control a vehicle's basic operations, including movement, lights, and mode switching. This article is aimed...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.