Beispiel #1
0
// 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
}
Beispiel #2
0
// 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
}
Beispiel #3
0
// 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
}
Beispiel #4
0
// 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
}
Beispiel #6
0
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
}
Beispiel #7
0
// 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
}
Beispiel #8
0
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)
}
Beispiel #9
0
// 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
}
Beispiel #10
0
// 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
}
Beispiel #11
0
// 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
}
Beispiel #12
0
// 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
}