비밀키, 공개키, 서명, 그리고 검증 방법까지 알아보았다. 하지만 이러한 값을 가지고 있기만 해서는 결제라는 행위가 이루어질 수 없다. 어딘가로 보내야 한다. 그때 필요한 기술인 직렬화를 알아보자.
S256Point
를 직렬화해보자.에 대해 비압축 SEC 표현 방식은 다음과 같다.
0x04
의 1바이트 prefix로 시작한다.047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316677
- marker: 04
- x: 7211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073
- y: dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316677
class S256Point(Point):
...
def sec(self):
return b'\x04' + self.x.num.to_bytes(32, 'big') + self.y.num.to_bytes(32, 'big')
b'\x04'
는 python에서 bytes
객체를 생성하는 방법이다.to_bytes()
함수는 정수형을 bytes
형으로 바꾸는 메서드이다.타원 곡선 위의 점(공개키)를 보내고 싶은쪽을 A, 받는쪽을 B라 하겠다.
0349c4e631e3624a545de3f89f5d8684c7b81386d94bdd531d2e213bf016b278a
- y marker - 03
- even: 02
- odd: 03
- × - 49c4e631e3624a545de3f89f5d8684c7b81386d94bdd531d2e213bf016b278a(32 bytes)
class S256Point(Point):
...
def sec(self, compressed=True):
'''returns the binary version of the SEC format'''
if compressed:
if self.y.num % 2 == 0:
return b'\x02' + self.x.num.to_bytes(32, 'big')
else:
return b'\x03' + self.x.num.to_bytes(32, 'big')
else:
return b'\x04' + self.x.num.to_bytes(32, 'big') + \
self.y.num.to_bytes(32, 'big')
...
class S256Field(FieldElement):
...
def sqrt(self):
return self**((P + 1) // 4)
class S256Point(Point):
...
@classmethod
def parse(self, sec_bin): # SEC 바이너리를 인자로 받음
'''returns a Point object from a SEC binary (not hex)'''
if sec_bin[0] == 4: # 첫 값이 4라면, 비압축임
x = int.from_bytes(sec_bin[1:33], 'big')
y = int.from_bytes(sec_bin[33:65], 'big')
return S256Point(x=x, y=y)
is_even = sec_bin[0] == 2 # 2나, 3이라면 압축방식임
x = S256Field(int.from_bytes(sec_bin[1:], 'big'))
# right side of the equation y^2 = x^3 + 7
alpha = x**3 + S256Field(B) # B = 7
# solve for left side
beta = alpha.sqrt() # y값을 구함
if beta.num % 2 == 0: # 짝수라면 홀수값도 구해줘야 함
even_beta = beta
odd_beta = S256Field(P - beta.num)
else: # 홀수라면 짝수값도 구해줘야 함
even_beta = S256Field(P - beta.num)
odd_beta = beta
if is_even: # 최종적으로 바이너리에서 홀/짝 요청에 따른 값을 반환함
return S256Point(x, even_beta)
else:
return S256Point(x, odd_beta)