2017-09-18 17 views
1

Golang의 타원형 곡선 라이브러리는 X 및 Y 값 (압축되지 않은 좌표)이있는 공용 좌표에서 비밀 키를 파생시킬 수 있습니다.Go에서 ECDH P256 커브에 단일 X9.62 압축 점 압축을 푸는 방법은 무엇입니까?

그러나 제공된 점이 주어진 y 비트가있는 X9.62 압축 형식의 단일 값일 때 어떻게 압축을 풀 수 있습니까?

https://crypto.stackexchange.com/questions/8914/ecdsa-compressed-public-key-point-back-to-uncompressed-public-key-point

:도 나타납니다

https://github.com/openssl/openssl/blob/4e9b720e90ec154c9708139e96ec0ff8e2796c82/include/openssl/ec.h#L494

특별히 유사한 관련된 수학을 해결 질문,하지만 이동을위한 가장 좋은 방법이 될 수 :

은 OpenSSL은이 방법으로이 시나리오를 처리

Go에서 어떻게해야합니까?

+0

수학을 이해하는 누군가는 다른 ECC 라이브러리에서 구현을 해제해야한다고 생각합니다. 모범 사례를 요청하지만 실제로 구현을 요구하는 것 같습니다. –

답변

1

Go 표준 라이브러리 (또는 "x"패키지)에는 포인트 압축 해제 기능이 없으므로 직접 수행해야합니다 (또는 기존 구현을 찾으십시오).

구현이 너무 어렵지는 않지만 두 가지 사항을주의해야합니다.

기본적으로 X 값을 곡선 수식 Y2 = X3 + aX + b에 연결하고 부호 비트를 사용하여 원하는 두 개의 뿌리를 결정해야합니다. 까다로운 점은이 모든 것이이 그룹의 전성기를 강 조할 필요가 있음을 기억하는 것입니다.

변경 가능한 값을 사용하기 때문에 Go’s big integer package이 약간 이상 할 수 있지만, 우리에게는 훨씬 편하게 들릴 modular square root function이 있습니다. 곡선 매개 변수는 crypto/elliptic package에서 사용할 수 있지만 a 매개 변수는 항상이 곡선에 대해 -3임을 알아야합니다.

당신이 compressed_bytes에서의 following should work (주요 0x02 또는 0x03 포함) []byte로 압축 지점이 가정. 이것은 방정식을 아주 직접적으로 구현 한 것으로, 주석과 많은 명명 된 변수로 분해되어 무슨 일이 일어나는지 설명하려고합니다. 약간 더 효율적인 (그리고 더 짧은) 구현을 위해 CurveParams.IsOnCurve의 출처를 살펴보십시오. 모듈 식 제곱근까지는 기본적으로 같습니다.

compressed_bytes := //... 

// Split the sign byte from the rest 
sign_byte := uint(compressed_bytes[0]) 
x_bytes := compressed_bytes[1:] 

// Convert to big Int. 
x := new(big.Int).SetBytes(x_bytes) 

// We use 3 a couple of times 
three := big.NewInt(3) 

// and we need the curve params for P256 
c := elliptic.P256().Params() 

// The equation is y^2 = x^3 - 3x + b 
// First, x^3, mod P 
x_cubed := new(big.Int).Exp(x, three, c.P) 

// Next, 3x, mod P 
three_X := new(big.Int).Mul(x, three) 
three_X.Mod(three_X, c.P) 

// x^3 - 3x ... 
y_squared := new(big.Int).Sub(x_cubed, three_X) 

// ... + b mod P 
y_squared.Add(y_squared, c.B) 
y_squared.Mod(y_squared, c.P) 

// Now we need to find the square root mod P. 
// This is where Go's big int library redeems itself. 
y := new(big.Int).ModSqrt(y_squared, c.P) 
if y == nil { 
    // If this happens then you're dealing with an invalid point. 
    // Panic, return an error, whatever you want here. 
} 

// Finally, check if you have the correct root by comparing 
// the low bit with the low bit of the sign byte. If it’s not 
// the same you want -y mod P instead of y. 
if y.Bit(0) != sign_byte & 1 { 
    y.Neg(y) 
    y.Mod(y, c.P) 
} 

// Now your y coordinate is in y, for all your ScalarMult needs.