Beispiel #1
0
func (g giImpl) PublicCertificates() ([]info.Certificate, error) {
	certs, err := appengine.PublicCertificates(g.aeCtx)
	if err != nil {
		return nil, err
	}
	ret := make([]info.Certificate, len(certs))
	for i, c := range certs {
		ret[i] = info.Certificate(c)
	}
	return ret, nil
}
Beispiel #2
0
// Certificate will return all public certificates assigned by App Engine in PEM format.
func Certificate(ctx context.Context, w http.ResponseWriter, r *http.Request) (status int, err error) {
	var certs []appengine.Certificate
	if certs, err = appengine.PublicCertificates(ctx); err != nil {
		return http.StatusInternalServerError, err
	}

	w.Header().Add("Content-Type", "application/x-pem-file")

	for _, cert := range certs {
		w.Write([]byte("KeyName: \"" + cert.KeyName + "\""))
		w.Write(cert.Data)
	}

	return http.StatusOK, nil
}
// PublicCerts returns list of public certificates.
func PublicCerts(c context.Context) (*PublicCertificates, error) {
	aeCerts, err := appengine.PublicCertificates(c)
	if err != nil {
		return nil, err
	}
	var certs []Certificate
	for _, ac := range aeCerts {
		certs = append(certs, Certificate{
			KeyName:            ac.KeyName,
			X509CertificatePEM: string(ac.Data),
		})
	}
	return &PublicCertificates{
		Certificates: certs,
		Timestamp:    time.Now().Unix(),
	}, nil
}
Beispiel #4
0
// Certificate will return all public certificates assigned by App Engine in PEM format.
func Certificate(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, error) {
	certs, err := appengine.PublicCertificates(ctx)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	// TODO(flowlo): Is this really the appropriate MIME type?
	w.Header().Add("Content-Type", "application/x-pem-file")

	for _, cert := range certs {
		p := make([]byte, 13+len(cert.KeyName)+len(cert.Data))
		p = append(p, []byte("KeyName: \""+cert.KeyName+"\"\n")...)
		p = append(p, cert.Data...)
		p = append(p, []byte("\n")...)
		if _, err := w.Write(p); err != nil {
			return http.StatusInternalServerError, err
		}
	}

	return http.StatusOK, nil
}
Beispiel #5
0
// VerifyBytes verifies a signature produced by appengine.SignBytes. c must be a
// context.Context created from appengine.NewContext.
func VerifyBytes(c context.Context, bytes []byte, sig []byte) error {
	certs, err := appengine.PublicCertificates(c)
	if err != nil {
		return err
	}

	lastErr := ErrNoPublicCertificates

	signBytesHash := crypto.SHA256
	h := signBytesHash.New()
	h.Write(bytes)
	hashed := h.Sum(nil)

	for _, cert := range certs {
		block, _ := pem.Decode(cert.Data)
		if block == nil {
			lastErr = ErrPemDecodeFailure
			continue
		}
		x509Cert, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			lastErr = err
			continue
		}
		pubkey, ok := x509Cert.PublicKey.(*rsa.PublicKey)
		if !ok {
			lastErr = ErrNotRSAPublicKey
			continue
		}
		err = rsa.VerifyPKCS1v15(pubkey, signBytesHash, hashed, sig)
		if err != nil {
			lastErr = err
			continue
		}

		return nil
	}

	return lastErr
}
Beispiel #6
0
// Implements the Verify method from SigningMethod
// For this signing method, a valid appengine.Context must be
// passed as the key.
func (s *SigningMethodAppEngine) Verify(signingString, signature string, key interface{}) error {
	var ctx context.Context

	switch k := key.(type) {
	case context.Context:
		ctx = k
	default:
		return jwt.ErrInvalidKey
	}

	var sig []byte
	var err error
	if sig, err = jwt.DecodeSegment(signature); err != nil {
		return err
	}

	var certs certificates
	certs, err = appengine.PublicCertificates(ctx)
	if err != nil {
		return err
	}

	hasher := sha256.New()
	hasher.Write([]byte(signingString))

	var certErr error
	for _, cert := range certs {
		rsaKey, err := jwt.ParseRSAPublicKeyFromPEM(cert.Data)
		if err != nil {
			return err
		}

		if certErr = rsa.VerifyPKCS1v15(rsaKey, crypto.SHA256, hasher.Sum(nil), sig); certErr == nil {
			return nil
		}
	}

	return certErr
}