package cryptoutil import ( "bytes" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/json" "encoding/pem" "fmt" "math/big" "os" "time" "github.com/lestrrat-go/jwx/jwk" ) func ExtractPublicKey(priv interface{}) interface{} { switch k := priv.(type) { case *rsa.PrivateKey: return &k.PublicKey case *ecdsa.PrivateKey: return &k.PublicKey default: return nil } } func PublicKeyToJWKJson(pub interface{}) ([]byte, error) { jk, err := jwk.New(pub) if err != nil { return nil, err } return json.Marshal(jk) } func StringToJWK(in string) (jwk.Key, error) { set, err := jwk.ParseString(in) if err != nil { return nil, err } k, ok := set.Get(0) if !ok { return nil, fmt.Errorf("No key found") } return k, nil } func PublicKeyToJWK(pub interface{}) (jwk.Key, error) { return jwk.New(pub) } func pemBlockForKey(priv interface{}) *pem.Block { switch k := priv.(type) { case *rsa.PrivateKey: return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)} case *ecdsa.PrivateKey: b, err := x509.MarshalECPrivateKey(k) if err != nil { fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err) os.Exit(2) } return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} default: return nil } } func GenCert(org, cn string) (priv *ecdsa.PrivateKey, cert *x509.Certificate, certPem string, keyPem string, err error) { priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return nil, nil, "", "", fmt.Errorf("Failed to create key: %s", err) } template := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ Organization: []string{org}, CommonName: cn, }, NotBefore: time.Now(), NotAfter: time.Now().Add(time.Hour * 24 * 180), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, ExtractPublicKey(priv), priv) if err != nil { return nil, nil, "", "", fmt.Errorf("Failed to create certificate: %s", err) } out := &bytes.Buffer{} pem.Encode(out, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certPem = out.String() out.Reset() pem.Encode(out, pemBlockForKey(priv)) keyPem = out.String() cert, err = x509.ParseCertificate(derBytes) return priv, cert, certPem, keyPem, err }