func NewEcdsaPublicKey(pk *ecdsa.PublicKey) *EcdsaPublicKey { pubkey := &EcdsaPublicKey{ Curve: jwa.EllipticCurveAlgorithm(pk.Params().Name), } pubkey.X.SetBytes(pk.X.Bytes()) pubkey.Y.SetBytes(pk.Y.Bytes()) return pubkey }
// NewEcdsaPublicKey creates a new JWK from a EC-DSA public key func NewEcdsaPublicKey(pk *ecdsa.PublicKey) *EcdsaPublicKey { pubkey := &EcdsaPublicKey{ EssentialHeader: &EssentialHeader{KeyType: jwa.EC}, Curve: jwa.EllipticCurveAlgorithm(pk.Params().Name), } n := pk.Params().BitSize / 8 pubkey.X.SetBytes(i2osp(pk.X, n)) pubkey.Y.SetBytes(i2osp(pk.Y, n)) return pubkey }
func (sv *x509ECDSASignatureVerifierImpl) verifyImpl(vk *ecdsa.PublicKey, signature, message []byte) (bool, error) { ecdsaSignature := new(ECDSASignature) _, err := asn1.Unmarshal(signature, ecdsaSignature) if err != nil { return false, err } h, err := computeHash(message, vk.Params().BitSize) if err != nil { return false, err } return ecdsa.Verify(vk, h, ecdsaSignature.R, ecdsaSignature.S), nil }
// marshalPubECDSA serializes an ECDSA public key according to RFC 5656, section 3.1. func marshalPubECDSA(key *ecdsa.PublicKey) []byte { var identifier []byte switch key.Params().BitSize { case 256: identifier = []byte("nistp256") case 384: identifier = []byte("nistp384") case 521: identifier = []byte("nistp521") default: panic("ssh: unsupported ecdsa key size") } keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y) length := stringLength(len(identifier)) length += stringLength(len(keyBytes)) ret := make([]byte, length) r := marshalString(ret, identifier) r = marshalString(r, keyBytes) return ret }
// GoodKeyECDSA determines if an ECDSA pubkey meets our requirements func (policy *KeyPolicy) goodKeyECDSA(key ecdsa.PublicKey) (err error) { // Check the curve. // // The validity of the curve is an assumption for all following tests. err = policy.goodCurve(key.Curve) if err != nil { return err } // Key validation routine adapted from NIST SP800-56A § 5.6.2.3.2. // <http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf> // // Assuming a prime field since a) we are only allowing such curves and b) // crypto/elliptic only supports prime curves. Where this assumption // simplifies the code below, it is explicitly stated and explained. If ever // adapting this code to support non-prime curves, refer to NIST SP800-56A § // 5.6.2.3.2 and adapt this code appropriately. params := key.Params() // SP800-56A § 5.6.2.3.2 Step 1. // Partial check of the public key for an invalid range in the EC group: // Verify that key is not the point at infinity O. // This code assumes that the point at infinity is (0,0), which is the // case for all supported curves. if isPointAtInfinityNISTP(key.X, key.Y) { return core.MalformedRequestError("Key x, y must not be the point at infinity") } // SP800-56A § 5.6.2.3.2 Step 2. // "Verify that x_Q and y_Q are integers in the interval [0,p-1] in the // case that q is an odd prime p, or that x_Q and y_Q are bit strings // of length m bits in the case that q = 2**m." // // Prove prime field: ASSUMED. // Prove q != 2: ASSUMED. (Curve parameter. No supported curve has q == 2.) // Prime field && q != 2 => q is an odd prime p // Therefore "verify that x, y are in [0, p-1]" satisfies step 2. // // Therefore verify that both x and y of the public key point have the unique // correct representation of an element in the underlying field by verifying // that x and y are integers in [0, p-1]. if key.X.Sign() < 0 || key.Y.Sign() < 0 { return core.MalformedRequestError("Key x, y must not be negative") } if key.X.Cmp(params.P) >= 0 || key.Y.Cmp(params.P) >= 0 { return core.MalformedRequestError("Key x, y must not exceed P-1") } // SP800-56A § 5.6.2.3.2 Step 3. // "If q is an odd prime p, verify that (y_Q)**2 === (x_Q)***3 + a*x_Q + b (mod p). // If q = 2**m, verify that (y_Q)**2 + (x_Q)*(y_Q) == (x_Q)**3 + a*(x_Q)*2 + b in // the finite field of size 2**m. // (Ensures that the public key is on the correct elliptic curve.)" // // q is an odd prime p: proven/assumed above. // a = -3 for all supported curves. // // Therefore step 3 is satisfied simply by showing that // y**2 === x**3 - 3*x + B (mod P). // // This proves that the public key is on the correct elliptic curve. // But in practice, this test is provided by crypto/elliptic, so use that. if !key.Curve.IsOnCurve(key.X, key.Y) { return core.MalformedRequestError("Key point is not on the curve") } // SP800-56A § 5.6.2.3.2 Step 4. // "Verify that n*Q == O. // (Ensures that the public key has the correct order. Along with check 1, // ensures that the public key is in the correct range in the correct EC // subgroup, that is, it is in the correct EC subgroup and is not the // identity element.)" // // Ensure that public key has the correct order: // verify that n*Q = O. // // n*Q = O iff n*Q is the point at infinity (see step 1). ox, oy := key.Curve.ScalarMult(key.X, key.Y, params.N.Bytes()) if !isPointAtInfinityNISTP(ox, oy) { return core.MalformedRequestError("Public key does not have correct order") } // End of SP800-56A § 5.6.2.3.2 Public Key Validation Routine. // Key is valid. return nil }