Próbuję przeanalizować punkt WE

0441047D041C12DDAF693958F91F1174E0C790B2FF580DDCA39BC2A4F78AD041DC379AAEFE27DE2FA765F90E3F397938A58AAC8C28CA5415. \ t

Do ECDSA.Public klucz ścisłego z następującym kodem:

    x, y := readECPoint(elliptic.P256(), point)
    if x == nil || y == nil {
        panic("unable to parse the public key")
    }
    pubKey := &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}

    pubKeyBytes := elliptic.Marshal(curve, pubKey.X, pubKey.Y)

Przeglądanie Github zauważyłem ten kawałek kodu, który miał dla mnie sens:

func readECPoint(curve elliptic.Curve, ecpoint []byte) (*big.Int, *big.Int) {
    x, y := elliptic.Unmarshal(curve, ecpoint)
    if x == nil {
        // http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/os/pkcs11-curr-v2.40-os.html#_ftn1
        // PKCS#11 v2.20 specified that the CKA_EC_POINT was to be store in a DER-encoded
        // OCTET STRING.
        var point asn1.RawValue
        asn1.Unmarshal(ecpoint, &point)
        if len(point.Bytes) > 0 {
            x, y = elliptic.Unmarshal(curve, point.Bytes)
        }
    }
    return x, y
}

Inne rzeczy, które próbowałem, byli:

curve := new(secp256k1.BitCurve)
x, y := curve.Unmarshal(point)

Jednak wszystkie te poprzedni kod zawsze zwracają X = Nil i Y = Nil

Wiem, że Keypair wygenerowano w HSM z krzywą bitcoin

ASN1.Objectdentifier 1.3.132.0.10.

Czy brakuje mi czegoś innego, aby właściwie analizować punkt WE z krzywej bitcoin / etereum?

2
Jorge Alvarado 13 marzec 2021, 21:12

2 odpowiedzi

Najlepsza odpowiedź

Pierwszy fragment kodu wydaje się źle, ponieważ elliptic.P256() Zwraca krzywą, która implementuje NIST P-256 znany również jako Secp256R1 lub Prime256V1. Ale krzywa bitcoin / eteryna używa Secp256K1 Format, który jest inny.

Proponuję użyć Go-Etherium pakiet, aby utworzyć krzywą SECP256K1.

Znalazłem też problem z kluczem. Ma długość 67, ale wielkość klucza publicznego musi wynosić 65 (patrz Kod źródłowy). Wraz ze wskazany topako, pierwsze dwa bajty są prawdopodobnie ASN.1 kodujące dla ciągu oktetu (0x04) długości 65 bajtów (0x41), więc rzeczywisty klucz zaczyna się od 3 bajtu.

Napisałem ten minimalny przykład, który analizuje klucz za pomocą Go-Ethereum:

package main

import (
    "encoding/hex"
    "fmt"

    "github.com/ethereum/go-ethereum/crypto/secp256k1"
)

func main() {
    c := *secp256k1.S256()
    data, err := hex.DecodeString("04410478ed041c12ddaf693958f91f1174e0c790b2ff580ddca39bc2a4f78ad041dc379aaefe27cede2fa7601f90e3f397938ee53268564e346ac7a58aac8c28ca5415")
    if err != nil {
        panic(err)
    }
    x, y := c.Unmarshal(data[2:])
    fmt.Printf("%v\n%v\n", x, y)
}

Wynik:

54696312948195154784868816119600719747374302831648955727311433079671352319031
69965364187890201668291488802478374883818025489090614849107393112609590498325
1
jubnzv 14 marzec 2021, 10:15

W końcu znalazłem sposób, choć bardziej podręcznik niż myślałem, może ktoś ma lepszy sposób?

curve := new(secp256k1.BitCurve)

    pubKey := ecdsa.PublicKey{
        Curve: curve,
        X:     &big.Int{},
        Y:     &big.Int{},
    }
    xBytes := point[3:35] //the point array has 67 bytes, ignore the first 2
    yBytes := point[35:]

    pubKey.X = new(big.Int).SetBytes(xBytes)
    pubKey.Y = new(big.Int).SetBytes(yBytes)
0
Jorge Alvarado 14 marzec 2021, 09:59