// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { var w struct { Curve string KeyBytes []byte Rest []byte `ssh:"rest"` } if err := Unmarshal(in, &w); err != nil { return nil, nil, err } key := new(ecdsa.PublicKey) switch w.Curve { case "nistp256": key.Curve = elliptic.P256() case "nistp384": key.Curve = elliptic.P384() case "nistp521": key.Curve = elliptic.P521() default: return nil, nil, errors.New("ssh: unsupported curve") } key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) if key.X == nil || key.Y == nil { return nil, nil, errors.New("ssh: invalid curve point") } return (*ecdsaPublicKey)(key), w.Rest, nil }
// 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 }
// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. func parseECDSA(in []byte) (out *ecdsa.PublicKey, rest []byte, ok bool) { var identifier []byte if identifier, in, ok = parseString(in); !ok { return } key := new(ecdsa.PublicKey) switch string(identifier) { case "nistp256": key.Curve = elliptic.P256() case "nistp384": key.Curve = elliptic.P384() case "nistp521": key.Curve = elliptic.P521() default: ok = false return } var keyBytes []byte if keyBytes, in, ok = parseString(in); !ok { return } key.X, key.Y = elliptic.Unmarshal(key.Curve, keyBytes) if key.X == nil || key.Y == nil { ok = false return } return key, in, ok }
// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { var identifier []byte var ok bool if identifier, in, ok = parseString(in); !ok { return nil, nil, errShortRead } key := new(ecdsa.PublicKey) switch string(identifier) { case "nistp256": key.Curve = elliptic.P256() case "nistp384": key.Curve = elliptic.P384() case "nistp521": key.Curve = elliptic.P521() default: return nil, nil, errors.New("ssh: unsupported curve") } var keyBytes []byte if keyBytes, in, ok = parseString(in); !ok { return nil, nil, errShortRead } key.X, key.Y = elliptic.Unmarshal(key.Curve, keyBytes) if key.X == nil || key.Y == nil { return nil, nil, errors.New("ssh: invalid curve point") } return (*ecdsaPublicKey)(key), in, nil }
// 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 }
func verify(signerKeyFile, userKeyFile, sigFile string) bool { rawSigner, err := ioutil.ReadFile(signerKeyFile) if err != nil { fmt.Printf("Failed to read signature key: %v\n", err) return false } var signer ecdsa.PublicKey signer.X, signer.Y = elliptic.Unmarshal(elliptic.P521(), rawSigner) if signer.X == nil { fmt.Println("Invalid signature key.") return false } signer.Curve = elliptic.P521() rawUser, err := ioutil.ReadFile(userKeyFile) if err != nil { fmt.Printf("Failed to read user key: %v\n", err) return false } x, _ := elliptic.Unmarshal(elliptic.P521(), rawUser) if x == nil { fmt.Println("Invalid user key.") return false } rawSig, err := ioutil.ReadFile(sigFile) if err != nil { fmt.Printf("Failed to load signature: %v\n", err) return false } var sig ECDSASignature _, err = asn1.Unmarshal(rawSig, &sig) if err != nil { fmt.Printf("Failed to parse signature: %v\n", err) return false } h := sha512.Sum384(rawUser) return ecdsa.Verify(&signer, h[:], sig.R, sig.S) }
// 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 }
// Multiplies the base G by a large integer. The resulting // point is represented as an ECDSA public key since that's // typically how they're used. func ScalarBaseMult(k *big.Int) *ecdsa.PublicKey { key := new(ecdsa.PublicKey) key.Curve = Secp256k1() key.X, key.Y = Secp256k1().ScalarBaseMult(k.Bytes()) return key }
// Adds two points to create a third. Points are represented as // ECDSA public keys. func Add(a, b *ecdsa.PublicKey) *ecdsa.PublicKey { key := new(ecdsa.PublicKey) key.Curve = Secp256k1() key.X, key.Y = Secp256k1().Add(a.X, a.Y, b.X, b.Y) return key }
// Multiply a large integer and a point. The resulting point // is represented as an ECDSA public key. func ScalarMult(k *big.Int, B *ecdsa.PublicKey) *ecdsa.PublicKey { key := new(ecdsa.PublicKey) key.Curve = Secp256k1() key.X, key.Y = Secp256k1().ScalarMult(B.X, B.Y, k.Bytes()) return key }