동현 유
척척석사
동현 유
전체 방문자
오늘
어제
  • 분류 전체보기 (178)
    • BlockChain (48)
      • [paper] Consensus (13)
      • [paper] Execution (19)
      • [paper] Storage (5)
      • [paper] ZKP (1)
      • [paper] Oracle (1)
      • Blockchains (9)
    • Java (19)
      • Java의 정석 (13)
      • Java 파헤치기 (5)
    • Python (20)
      • Python 뜯어보기 (6)
      • 데이터 분석 기초 (5)
      • Python 기초 강의 (6)
      • Python 기초 강의 부록 (3)
    • Golang (0)
    • MySQL (3)
      • programmers (2)
      • 기본 문법 (0)
    • 웹 프로젝트 (IBAS) (36)
      • Django 레거시 (14)
      • SpringBoot api 개편 (14)
      • Infra (3)
      • 서버 장애 기록 (4)
      • 신입팀원 교육 자료 (1)
    • CS (30)
      • Operating System (22)
      • Computer Security (3)
      • Network (4)
      • DBMS (1)
    • 책 (10)
      • 도메인 주도 설계 철저 입문 (9)
      • Real MySQL 8.0 (1)
    • BOJ 문제 풀이 (3)
    • 이러쿵저러쿵 (7)
    • 회고 (1)

인기 글

최근 댓글

최근 글

hELLO · Designed By 정상우.
동현 유

척척석사

CS/Computer Security

타원곡선암호 연산 파이썬 구현(ECC, P-192)

2022. 7. 20. 21:04

Implementing Elliptic Curve Cryptography operation in Python on the Curve P-192

 


P-192 곡선 파라미터 선언

# define P-192 parameters
p = 2 ** 192 - 2 ** 64 - 1
a = -3
b = 0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1
n = 0xFFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831
gx = 0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012
gy = 0x07192B95FFC8DA78631011ED6B24CDD573F977A11E794811

WeierStrass Form

def valid(P: Affine_Point) -> bool:	
    """
    Check if P is on the curve, i.e., it is a valid point or not
    Return True: P is a valid point
           False: P is not a valid point
    """
    x, y = P
    return y ** 2 % p == (x ** 3 + a * x + b) % p

Jacobian Projection 정의

from typing import Union  
from collections import namedtuple  

Affine_Point = namedtuple('Affine_Point', 'x y')
Jacobian_Point = namedtuple('Jacobian_Point', 'x y z')


def _to_jacobian(P: Affine_Point)-> Jacobian_Point:
    
    if inf(P):
        return JACOBIAN_INF
    else:
        return Jacobian_Point(P.x, P.y, 1)


def _to_affine(P: Jacobian_Point) -> Affine_Point:
    
    if P.z == 0:
        return INF
    else:
        inverse = pow(P.z, -1, p)
        return Affine_Point(P.x * inverse**2 % p, P.y * inverse**3 % p)

무한원점 정의

# INF = (p, p)
INF = Affine_Point(0, 0)
JACOBIAN_INF = Jacobian_Point(1, 1, 0)

def inf(P: Affine_Point) -> bool:
    """
    Check if P is INF or not
    Return True: P is INF
           False: P is not INF
    """
    return P is INF
       
        
 def neg(P: Affine_Point) -> Affine_Point:
    """
    Negate P (P is the affine point on the curve)
    """
    return Affine_Point(P.x, -1 * P.y)

덧셈 정의

def add(P1: Affine_Point, P2: Affine_Point) -> Affine_Point:
    """
    add(P1, P2)

    Point addition (P1 and P2 are the point on the curve P-192)
    """
    return _to_affine(_jacobian_affine_addition(_to_jacobian(P1), P2))


def _jacobian_affine_addition(P1: Jacobian_Point, P2: Affine_Point) -> Jacobian_Point:
    
    # case1 : check identity
    if _is_identity_of_addition(P1):
        return Jacobian_Point(P2.x, P2.y, 1)
    elif _is_identity_of_addition(P2):
        return P1

    x1, y1, z1 = P1
    x2, y2 = P2
    t1 = z1 ** 2 % p
    t2 = t1 * z1 % p
    t1 = t1 * x2 % p
    t2 = t2 * y2 % p
    t1 = (t1 - x1) % p
    t2 = (t2 - y1) % p

    # case2 & case3 : check inverse & doubling
    if t1 == 0:
        return _jacobian_double((x2, y2, 1)) if t2 == 0 else JACOBIAN_INF

    # case 4 : do addition
    c_z = z1 * t1 % p
    t3 = t1 ** 2 % p
    t4 = t3 * t1 % p
    t3 = t3 * x1 % p
    t1 = 2 * t3 % p
    c_x = t2 ** 2 % p
    c_x = (c_x - t1 - t4) % p
    t3 = t3 - c_x
    t3 = t3 * t2 % p
    t4 = t4 * y1 % p
    c_y = (t3 - t4) % p

    return Jacobian_Point(c_x, c_y, c_z)
    
    
 def _is_identity_of_addition(P: Union[Affine_Point, Jacobian_Point]) -> bool:
    """
    Determine whether the input point is the point at infinity or not.
    For the jacobian projection, z-value of the point at infinity is 0. 

    :param P: a jacobian point OR an affine point
    :return: true - if the input point is at infinity
    """
    if type(P) is Affine_Point:
        return inf(P)
    elif type(P) is Jacobian_Point:
        return P.z % p == 0

더블링 정의

def dbl(P: Affine_Point)-> Affine_Point:
    """
    dbl(P)

    Point doubling (P is the point on the curve P-192)
    """
    if inf(P):
        return INF

    return _to_affine(_jacobian_double(_to_jacobian(P)))


def _jacobian_double(P: Jacobian_Point)-> Jacobian_Point:
    
    if _is_identity_of_addition(P):
        return JACOBIAN_INF

    x, y, z = P
    t = (3 * x ** 2 + a * z ** 4) % p
    c_x = (t ** 2 - 8 * x * y ** 2) % p
    c_y = (t * (4 * x * y ** 2 - c_x) - 8 * y ** 4) % p
    c_z = (2 * y * z) % p

    return Jacobian_Point(c_x, c_y, c_z)

Scala Multiplication 정의

def mul(k: int, P: Affine_Point) -> Affine_Point:
    """
    mul(k, P)

    Point multiplication (P is the point on the curve P-192, integer k >= 0 )
    """
    Q = JACOBIAN_INF
    k_binary = _to_binary(k)
    for i in k_binary:
        Q = _jacobian_double(Q)
        if i == '1':
            Q = _jacobian_affine_addition(Q, P)

    return _to_affine(Q)

def _to_binary(num: int) -> list:
    """
    return type is list, of which each element is character type
    """
    return list(bin(num))[2:]  # eliminate first two, ex) 0b00101001

 

더보기
"""
Implement ECC operations on the curve P-192
"""

######################### Define Projective ############################
from typing import Union
from collections import namedtuple

Affine_Point = namedtuple('Affine_Point', 'x y')
Jacobian_Point = namedtuple('Jacobian_Point', 'x y z')

# INF = (p, p)
INF = Affine_Point(0, 0)
JACOBIAN_INF = Jacobian_Point(1, 1, 0)

def _to_jacobian(P: Affine_Point)-> Jacobian_Point:

    if inf(P):
        return JACOBIAN_INF
    else:
        return Jacobian_Point(P.x, P.y, 1)


def _to_affine(P: Jacobian_Point) -> Affine_Point:

    if P.z == 0:
        return INF
    else:
        inverse = pow(P.z, -1, p)
        return Affine_Point(P.x * inverse**2 % p, P.y * inverse**3 % p)
########################################################################


################## Define Basic properties of P-192 ####################
p = 2 ** 192 - 2 ** 64 - 1
a = -3
b = 0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1
n = 0xFFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831
gx = 0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012
gy = 0x07192B95FFC8DA78631011ED6B24CDD573F977A11E794811


def valid(P: Affine_Point) -> bool:
    """
    Check if P is on the curve, i.e., it is a valid point or not
    Return True: P is a valid point
           False: P is not a valid point
    """
    x, y = P
    return y ** 2 % p == (x ** 3 + a * x + b) % p


def inf(P: Affine_Point) -> bool:
    """
    Check if P is INF or not
    Return True: P is INF
           False: P is not INF
    """
    return P is INF


def neg(P: Affine_Point) -> Affine_Point:
    """
    Negate P (P is the affine point on the curve)
    """
    return Affine_Point(P.x, -1 * P.y)
########################################################################



########################## Define add & dbl ############################
def add(P1: Affine_Point, P2: Affine_Point) -> Affine_Point:
    """
    add(P1, P2)

    Point addition (P1 and P2 are the point on the curve P-192)
    """
    return _to_affine(_jacobian_affine_addition(_to_jacobian(P1), P2))


def _jacobian_affine_addition(P1: Jacobian_Point, P2: Affine_Point) -> Jacobian_Point:

    # case1 : check identity
    if _is_identity_of_addition(P1):
        return Jacobian_Point(P2.x, P2.y, 1)
    elif _is_identity_of_addition(P2):
        return P1

    x1, y1, z1 = P1
    x2, y2 = P2
    t1 = z1 ** 2 % p
    t2 = t1 * z1 % p
    t1 = t1 * x2 % p
    t2 = t2 * y2 % p
    t1 = (t1 - x1) % p
    t2 = (t2 - y1) % p

    # case2 & case3 : check inverse & doubling
    if t1 == 0:
        return _jacobian_double((x2, y2, 1)) if t2 == 0 else JACOBIAN_INF

    # case 4 : do addition
    c_z = z1 * t1 % p
    t3 = t1 ** 2 % p
    t4 = t3 * t1 % p
    t3 = t3 * x1 % p
    t1 = 2 * t3 % p
    c_x = t2 ** 2 % p
    c_x = (c_x - t1 - t4) % p
    t3 = t3 - c_x
    t3 = t3 * t2 % p
    t4 = t4 * y1 % p
    c_y = (t3 - t4) % p

    return Jacobian_Point(c_x, c_y, c_z)


def _is_identity_of_addition(P: Union[Affine_Point, Jacobian_Point]) -> bool:
    """
    Determine whether the input point is the point at infinity or not.
    For the jacobian projection, z-value of the point at infinity is 0.

    :param P: a jacobian point OR an affine point
    :return: true - if the input point is at infinity
    """
    if type(P) is Affine_Point:
        return inf(P)
    elif type(P) is Jacobian_Point:
        return P.z % p == 0


def dbl(P: Affine_Point)-> Affine_Point:
    """
    dbl(P)

    Point doubling (P is the point on the curve P-192)
    """
    if inf(P):
        return INF

    return _to_affine(_jacobian_double(_to_jacobian(P)))


def _jacobian_double(P: Jacobian_Point)-> Jacobian_Point:

    if _is_identity_of_addition(P):
        return JACOBIAN_INF

    x, y, z = P
    t = (3 * x ** 2 + a * z ** 4) % p
    c_x = (t ** 2 - 8 * x * y ** 2) % p
    c_y = (t * (4 * x * y ** 2 - c_x) - 8 * y ** 4) % p
    c_z = (2 * y * z) % p

    return Jacobian_Point(c_x, c_y, c_z)
########################################################################


######################## Define multiplication #########################
def mul(k: int, P: Affine_Point) -> Affine_Point:
    """
    mul(k, P)

    Point multiplication (P is the point on the curve P-192, integer k >= 0 )
    """
    Q = JACOBIAN_INF
    k_binary = _to_binary(k)
    for i in k_binary:
        Q = _jacobian_double(Q)
        if i == '1':
            Q = _jacobian_affine_addition(Q, P)

    return _to_affine(Q)

def _to_binary(num: int) -> list:
    """
    return type is list, of which each element is character type
    """
    return list(bin(num))[2:]  # eliminate first two, ex) 0b00101001
########################################################################


############################### testcase ###############################
if __name__ == "__main__":
    G = Affine_Point(gx, gy)
    # G = (gx, gy, 1)  # for Jacobian

    score = 0

    # addition (1): Boundaries
    # identity
    if add(G, INF) == G:
        score += 1
    else:
        print("Fail: add(G, INF) == G")

    if add(INF, G) == G:
        score += 1
    else:
        print("Fail: add(INF, G) == G")

    # negate
    if add(G, neg(G)) == INF:
        score += 1
    else:
        print("Fail: add(G, neg(G)) == INF")

    # same input -> doubling
    if add(G, G) == dbl(G):
        score += 1
    else:
        print("Fail: add(G, G) == dbl(G)")

    # doubling (1) Boundaries
    # inf
    if dbl(INF) == INF:
        score += 1
    else:
        print("Fail: dbl(INF) == INF")

    # multiplication
    # boundaries
    # 0G
    if mul(0, G) == INF:
        score += 1
    else:
        print("Fail: mul(0, G) == INF")

    # (n-1)G + G = INF
    if add(mul(n - 1, G), G) == INF:
        score += 1
    else:
        print("Fail: add(mul(n-1, G), G) == INF")

    # nG=0
    if mul(n, G) == INF:
        score += 1
    else:
        print("Fail: mul(n, G) == INF")

    # (n+1)G=1G
    if mul(n + 1, G) == G:
        score += 1
    else:
        print("Fail: mul(n+1, G) == G")

    # random k
    k = n - 2
    Q = mul(k, G)
    if not inf(Q) and not valid(Q):
        print("Fail: Q is invalid")
    else:
        score += 1

    if score == 10:
        print("PASS")
    else:
        print("FAIL")
########################################################################

'CS > Computer Security' 카테고리의 다른 글

[컴퓨터 보안] 수업 필기  (0) 2022.06.24
RSA 파이썬 구현 (key pair generator)  (0) 2022.05.10
    동현 유
    동현 유
    Fault Tolerant System Researcher for more Trustful World and Better Lives. (LinkedIn: https://www.linkedin.com/in/donghyeon-ryu-526b8a276/)

    티스토리툴바