// publicKeyCurve returns the Curve public key from the DNSKEY record. func (k *RR_DNSKEY) publicKeyCurve() *ecdsa.PublicKey { keybuf, err := packBase64([]byte(k.PublicKey)) if err != nil { return nil } pubkey := new(ecdsa.PublicKey) switch k.Algorithm { case ECDSAP256SHA256: pubkey.Curve = elliptic.P256() if len(keybuf) != 64 { // wrongly encoded key return nil } case ECDSAP384SHA384: pubkey.Curve = elliptic.P384() if len(keybuf) != 96 { // Wrongly encoded key return nil } } pubkey.X = big.NewInt(0) pubkey.X.SetBytes(keybuf[:len(keybuf)/2]) pubkey.Y = big.NewInt(0) pubkey.Y.SetBytes(keybuf[len(keybuf)/2:]) return pubkey }
// toECDSA takes the internal ECPublicKey and returns an equivalent // an ecdsa.PublicKey func (pk *ECPublicKey) toECDSA() *ecdsa.PublicKey { ecdsaPub := new(ecdsa.PublicKey) ecdsaPub.Curve = pk.Curve ecdsaPub.X = pk.X ecdsaPub.Y = pk.Y return ecdsaPub }
func UnmarshalPublicCertificate(data []byte) PublicCertificate { x, y := elliptic.Unmarshal(curve, data) cert := new(ecdsa.PublicKey) cert.Curve = curve cert.X = x cert.Y = y return cert }
// Extract the Curve public key from the Key record func (k *RR_DNSKEY) pubKeyCurve() *ecdsa.PublicKey { keybuf, err := packBase64([]byte(k.PublicKey)) if err != nil { return nil } var c *elliptic.Curve switch k.Algorithm { case ECDSAP256SHA256: c = elliptic.P256() case ECDSAP384SHA384: c = elliptic.P384() } x, y := c.Unmarshal(keybuf) pubkey := new(ecdsa.PublicKey) pubkey.X = x pubkey.Y = y pubkey.Curve = c return pubkey }
// ParsePubKey parses a public key for a koblitz curve from a bytestring into a // ecdsa.Publickey, verifying that it is valid. It supports compressed, // uncompressed and hybrid signature formats. func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *ecdsa.PublicKey, err error) { pubkey := ecdsa.PublicKey{} pubkey.Curve = curve format := pubKeyStr[0] ybit := (format & 0x1) == 0x1 format &= ^byte(0x1) switch len(pubKeyStr) { case 65: // normal public key if format != pubkeyUncompressed && format != pubkeyHybrid { return nil, fmt.Errorf("invalid magic in pubkey str: "+ "%d", pubKeyStr[0]) } pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33]) pubkey.Y = new(big.Int).SetBytes(pubKeyStr[33:]) // hybrid keys have extra information, make use of it. if format == pubkeyHybrid && ybit != isOdd(pubkey.Y) { return nil, fmt.Errorf("ybit doesn't match oddness") } case 33: // compressed public key // format is 0x2 | solution, <X coordinate> // solution determines which solution of the curve we use. /// y^2 = x^3 + Curve.B if format != pubkeyCompressed { return nil, fmt.Errorf("invalid magic in compressed "+ "pubkey string: %d", pubKeyStr[0]) } pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33]) // Y = +-sqrt(x^3 + B) x3 := new(big.Int).Mul(pubkey.X, pubkey.X) x3.Mul(x3, pubkey.X) x3.Add(x3, pubkey.Curve.Params().B) // now calculate sqrt mod p of x2 + B // This code used to do a full sqrt based on tonelli/shanks, // but this was replaced by the algorithms referenced in // https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294 y := new(big.Int).Exp(x3, curve.QPlus1Div4(), pubkey.Curve.Params().P) if ybit != isOdd(y) { y.Sub(pubkey.Curve.Params().P, y) } if ybit != isOdd(y) { return nil, fmt.Errorf("ybit doesn't match oddness") } pubkey.Y = y default: // wrong! return nil, fmt.Errorf("invalid pub key length %d", len(pubKeyStr)) } if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 { return nil, fmt.Errorf("pubkey X parameter is >= to P") } if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 { return nil, fmt.Errorf("pubkey Y parameter is >= to P") } if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) { return nil, fmt.Errorf("pubkey isn't on secp265k1 curve") } return &pubkey, nil }