func (k *JSONWebKey) Public() JSONWebKey {
	if k.IsPublic() {
		return *k
	}
	ret := *k
	switch key := k.Key.(type) {
	case *ecdsa.PrivateKey:
		ret.Key = key.Public()
	case *rsa.PrivateKey:
		ret.Key = key.Public()
	case ed25519.PrivateKey:
		ret.Key = key.Public()
	default:
		return JSONWebKey{}  
	}
	return ret
}
Public creates JSONWebKey with corresponding publik key if JWK represents asymmetric private key.
package jose
import (
	"bytes"
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"
	"math/big"
	"net/url"
	"reflect"
	"strings"
	"golang.org/x/crypto/ed25519"
	"gopkg.in/square/go-jose.v2/json"
)
type rawJSONWebKey struct {
	Use string      `json:"use,omitempty"`
	Kty string      `json:"kty,omitempty"`
	Kid string      `json:"kid,omitempty"`
	Crv string      `json:"crv,omitempty"`
	Alg string      `json:"alg,omitempty"`
	K   *byteBuffer `json:"k,omitempty"`
	X   *byteBuffer `json:"x,omitempty"`
	Y   *byteBuffer `json:"y,omitempty"`
	N   *byteBuffer `json:"n,omitempty"`
	E   *byteBuffer `json:"e,omitempty"`
	D  *byteBuffer `json:"d,omitempty"`
	P  *byteBuffer `json:"p,omitempty"`
	Q  *byteBuffer `json:"q,omitempty"`
	Dp *byteBuffer `json:"dp,omitempty"`
	Dq *byteBuffer `json:"dq,omitempty"`
	Qi *byteBuffer `json:"qi,omitempty"`
	X5c       []string `json:"x5c,omitempty"`
	X5u       *url.URL `json:"x5u,omitempty"`
	X5tSHA1   string   `json:"x5t,omitempty"`
	X5tSHA256 string   `json:"x5t#S256,omitempty"`
}
type JSONWebKey struct {
	Key interface{}
	KeyID string
	Algorithm string
	Use string
	Certificates []*x509.Certificate
	CertificatesURL *url.URL
	CertificateThumbprintSHA1 []byte
	CertificateThumbprintSHA256 []byte
}
func (k JSONWebKey) MarshalJSON() ([]byte, error) {
	var raw *rawJSONWebKey
	var err error
	switch key := k.Key.(type) {
	case ed25519.PublicKey:
		raw = fromEdPublicKey(key)
	case *ecdsa.PublicKey:
		raw, err = fromEcPublicKey(key)
	case *rsa.PublicKey:
		raw = fromRsaPublicKey(key)
	case ed25519.PrivateKey:
		raw, err = fromEdPrivateKey(key)
	case *ecdsa.PrivateKey:
		raw, err = fromEcPrivateKey(key)
	case *rsa.PrivateKey:
		raw, err = fromRsaPrivateKey(key)
	case []byte:
		raw, err = fromSymmetricKey(key)
	default:
		return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key))
	}
	if err != nil {
		return nil, err
	}
	raw.Kid = k.KeyID
	raw.Alg = k.Algorithm
	raw.Use = k.Use
	for _, cert := range k.Certificates {
		raw.X5c = append(raw.X5c, base64.StdEncoding.EncodeToString(cert.Raw))
	}
	x5tSHA1Len := len(k.CertificateThumbprintSHA1)
	x5tSHA256Len := len(k.CertificateThumbprintSHA256)
	if x5tSHA1Len > 0 {
		if x5tSHA1Len != sha1.Size {
			return nil, fmt.Errorf("square/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len)
		}
		raw.X5tSHA1 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA1)
	}
	if x5tSHA256Len > 0 {
		if x5tSHA256Len != sha256.Size {
			return nil, fmt.Errorf("square/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len)
		}
		raw.X5tSHA256 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA256)
	}
	if len(k.Certificates) > 0 {
		expectedSHA1 := sha1.Sum(k.Certificates[0].Raw)
		expectedSHA256 := sha256.Sum256(k.Certificates[0].Raw)
		if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(k.CertificateThumbprintSHA1, expectedSHA1[:]) {
			return nil, errors.New("square/go-jose: invalid SHA-1 thumbprint, does not match cert chain")
		}
		if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(k.CertificateThumbprintSHA256, expectedSHA256[:]) {
			return nil, errors.New("square/go-jose: invalid or SHA-256 thumbprint, does not match cert chain")
		}
	}
	raw.X5u = k.CertificatesURL
	return json.Marshal(raw)
}
func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
	var raw rawJSONWebKey
	err = json.Unmarshal(data, &raw)
	if err != nil {
		return err
	}
	certs, err := parseCertificateChain(raw.X5c)
	if err != nil {
		return fmt.Errorf("square/go-jose: failed to unmarshal x5c field: %s", err)
	}
	var key interface{}
	var certPub interface{}
	var keyPub interface{}
	if len(certs) > 0 {
		certPub = certs[0].PublicKey
	}
	switch raw.Kty {
	case "EC":
		if raw.D != nil {
			key, err = raw.ecPrivateKey()
			if err == nil {
				keyPub = key.(*ecdsa.PrivateKey).Public()
			}
		} else {
			key, err = raw.ecPublicKey()
			keyPub = key
		}
	case "RSA":
		if raw.D != nil {
			key, err = raw.rsaPrivateKey()
			if err == nil {
				keyPub = key.(*rsa.PrivateKey).Public()
			}
		} else {
			key, err = raw.rsaPublicKey()
			keyPub = key
		}
	case "oct":
		if certPub != nil {
			return errors.New("square/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain")
		}
		key, err = raw.symmetricKey()
	case "OKP":
		if raw.Crv == "Ed25519" && raw.X != nil {
			if raw.D != nil {
				key, err = raw.edPrivateKey()
				if err == nil {
					keyPub = key.(ed25519.PrivateKey).Public()
				}
			} else {
				key, err = raw.edPublicKey()
				keyPub = key
			}
		} else {
			err = fmt.Errorf("square/go-jose: unknown curve %s'", raw.Crv)
		}
	default:
		err = fmt.Errorf("square/go-jose: unknown json web key type '%s'", raw.Kty)
	}
	if err != nil {
		return
	}
	if certPub != nil && keyPub != nil {
		if !reflect.DeepEqual(certPub, keyPub) {
			return errors.New("square/go-jose: invalid JWK, public keys in key and x5c fields to not match")
		}
	}
	*k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use, Certificates: certs}
	k.CertificatesURL = raw.X5u
	x5tSHA1bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA1)
	if err != nil {
		return errors.New("square/go-jose: invalid JWK, x5t header has invalid encoding")
	}
	if len(x5tSHA1bytes) == 2*sha1.Size {
		hx, err := hex.DecodeString(string(x5tSHA1bytes))
		if err != nil {
			return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t: %v", err)
		}
		x5tSHA1bytes = hx
	}
	k.CertificateThumbprintSHA1 = x5tSHA1bytes
	x5tSHA256bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA256)
	if err != nil {
		return errors.New("square/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
	}
	if len(x5tSHA256bytes) == 2*sha256.Size {
		hx256, err := hex.DecodeString(string(x5tSHA256bytes))
		if err != nil {
			return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t#S256: %v", err)
		}
		x5tSHA256bytes = hx256
	}
	k.CertificateThumbprintSHA256 = x5tSHA256bytes
	x5tSHA1Len := len(k.CertificateThumbprintSHA1)
	x5tSHA256Len := len(k.CertificateThumbprintSHA256)
	if x5tSHA1Len > 0 && x5tSHA1Len != sha1.Size {
		return errors.New("square/go-jose: invalid JWK, x5t header is of incorrect size")
	}
	if x5tSHA256Len > 0 && x5tSHA256Len != sha256.Size {
		return errors.New("square/go-jose: invalid JWK, x5t#S256 header is of incorrect size")
	}
	if len(k.Certificates) > 0 {
		leaf := k.Certificates[0]
		sha1sum := sha1.Sum(leaf.Raw)
		sha256sum := sha256.Sum256(leaf.Raw)
		if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(sha1sum[:], k.CertificateThumbprintSHA1) {
			return errors.New("square/go-jose: invalid JWK, x5c thumbprint does not match x5t value")
		}
		if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(sha256sum[:], k.CertificateThumbprintSHA256) {
			return errors.New("square/go-jose: invalid JWK, x5c thumbprint does not match x5t#S256 value")
		}
	}
	return
}
type JSONWebKeySet struct {
	Keys []JSONWebKey `json:"keys"`
}
func (s *JSONWebKeySet) Key(kid string) []JSONWebKey {
	var keys []JSONWebKey
	for _, key := range s.Keys {
		if key.KeyID == kid {
			keys = append(keys, key)
		}
	}
	return keys
}
const rsaThumbprintTemplate = `{"e":"%s","kty":"RSA","n":"%s"}`
const ecThumbprintTemplate = `{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`
const edThumbprintTemplate = `{"crv":"%s","kty":"OKP",x":"%s"}`
func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
	coordLength := curveSize(curve)
	crv, err := curveName(curve)
	if err != nil {
		return "", err
	}
	if len(x.Bytes()) > coordLength || len(y.Bytes()) > coordLength {
		return "", errors.New("square/go-jose: invalid elliptic key (too large)")
	}
	return fmt.Sprintf(ecThumbprintTemplate, crv,
		newFixedSizeBuffer(x.Bytes(), coordLength).base64(),
		newFixedSizeBuffer(y.Bytes(), coordLength).base64()), nil
}
func rsaThumbprintInput(n *big.Int, e int) (string, error) {
	return fmt.Sprintf(rsaThumbprintTemplate,
		newBufferFromInt(uint64(e)).base64(),
		newBuffer(n.Bytes()).base64()), nil
}
func edThumbprintInput(ed ed25519.PublicKey) (string, error) {
	crv := "Ed25519"
	if len(ed) > 32 {
		return "", errors.New("square/go-jose: invalid elliptic key (too large)")
	}
	return fmt.Sprintf(edThumbprintTemplate, crv,
		newFixedSizeBuffer(ed, 32).base64()), nil
}
// Thumbprint computes the JWK Thumbprint of a key using the
// indicated hash algorithm.
func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
	var input string
	var err error
	switch key := k.Key.(type) {
	case ed25519.PublicKey:
		input, err = edThumbprintInput(key)
	case *ecdsa.PublicKey:
		input, err = ecThumbprintInput(key.Curve, key.X, key.Y)
	case *ecdsa.PrivateKey:
		input, err = ecThumbprintInput(key.Curve, key.X, key.Y)
	case *rsa.PublicKey:
		input, err = rsaThumbprintInput(key.N, key.E)
	case *rsa.PrivateKey:
		input, err = rsaThumbprintInput(key.N, key.E)
	case ed25519.PrivateKey:
		input, err = edThumbprintInput(ed25519.PublicKey(key[32:]))
	default:
		return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key))
	}
	if err != nil {
		return nil, err
	}
	h := hash.New()
	h.Write([]byte(input))
	return h.Sum(nil), nil
}
func (k *JSONWebKey) IsPublic() bool {
	switch k.Key.(type) {
	case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
		return true
	default:
		return false
	}
}