// Decode and verify an in memory .p12 certificate (DER binary format). func Decode(p12 []byte, password string) (tls.Certificate, error) { // decode an x509.Certificate to verify privateKey, cert, err := pkcs12.Decode(p12, password) if err != nil { return tls.Certificate{}, err } if err := verify(cert); err != nil { return tls.Certificate{}, err } // wrap in a tls certificate return tls.Certificate{ Certificate: [][]byte{cert.Raw}, PrivateKey: privateKey, Leaf: cert, }, nil }
// ParseCertificatesDER parses a DER encoding of a certificate object and possibly private key, // either PKCS #7, PKCS #12, or raw x509. func ParseCertificatesDER(certsDER []byte, password string) (certs []*x509.Certificate, key crypto.Signer, err error) { certsDER = bytes.TrimSpace(certsDER) pkcs7data, err := pkcs7.ParsePKCS7(certsDER) if err != nil { var pkcs12data interface{} certs = make([]*x509.Certificate, 1) pkcs12data, certs[0], err = pkcs12.Decode(certsDER, password) if err != nil { certs, err = x509.ParseCertificates(certsDER) if err != nil { return nil, nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed) } } else { key = pkcs12data.(crypto.Signer) } } else { if pkcs7data.ContentInfo != "SignedData" { return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.DecodeFailed, errors.New("can only extract certificates from signed data content info")) } certs = pkcs7data.Content.SignedData.Certificates } if certs == nil { return nil, key, cferr.New(cferr.CertificateError, cferr.DecodeFailed) } return certs, key, nil }
// CreateClient creates HTTP/2 apns client func CreateClient(certFile string, password string, isSandbox bool) (*Client, error) { /* Condition validation: validate certificate's path */ if len(certFile) == 0 { return nil, fmt.Errorf("Invalid certificate's path.") } /* Condition validation: validate certificate's password */ if len(password) == 0 { return nil, fmt.Errorf("Invalid certificate's password.") } // Load certificate bytes, _ := ioutil.ReadFile(certFile) key, cert, err := pkcs12.Decode(bytes, password) /* Condition validation: validate the correctness of loading process */ if err != nil { return nil, err } // Create certificate certificate := tls.Certificate{ Certificate: [][]byte{cert.Raw}, PrivateKey: key, Leaf: cert, } // Define gateway var gateway string if !isSandbox { gateway = Gateway } else { gateway = SandboxGateway } // Config TLS config := &tls.Config{ Certificates: []tls.Certificate{certificate}, ServerName: gateway, } // Config transport transport := &http2.Transport{ TLSClientConfig: config, } // Finalize client := Client{ gateway: gateway, client: &http.Client{Transport: transport}, } return &client, nil }
// FromP12Bytes loads a PKCS#12 certificate from an in memory byte array and // returns a tls.Certificate. // // Use "" as the password argument if the PKCS#12 certificate is not password // protected. func FromP12Bytes(bytes []byte, password string) (tls.Certificate, error) { key, cert, err := pkcs12.Decode(bytes, password) if err != nil { return tls.Certificate{}, err } return tls.Certificate{ Certificate: [][]byte{cert.Raw}, PrivateKey: key, Leaf: cert, }, nil }
func decodePkcs12(pkcs []byte, password string) (*x509.Certificate, *rsa.PrivateKey, error) { privateKey, certificate, err := pkcs12.Decode(pkcs, password) if err != nil { return nil, nil, err } rsaPrivateKey, isRsaKey := privateKey.(*rsa.PrivateKey) if !isRsaKey { return nil, nil, fmt.Errorf("PKCS#12 certificate must contain an RSA private key") } return certificate, rsaPrivateKey, nil }
// Decode and verify an in memory .p12 certificate (DER binary format). func Decode(p12 []byte, password string) (*x509.Certificate, *rsa.PrivateKey, error) { // decode an x509.Certificate to verify privateKey, cert, err := pkcs12.Decode(p12, password) if err != nil { return nil, nil, err } if err := verify(cert); err != nil { return nil, nil, err } // assert that private key is RSA priv, ok := privateKey.(*rsa.PrivateKey) if !ok { return nil, nil, errors.New("expected RSA private key type") } return cert, priv, nil }
func loadCertificate() (tls.Certificate, error) { if *p12File != "" { cert := tls.Certificate{} b, err := ioutil.ReadFile(*p12File) if err != nil { return cert, err } key, cer, err := pkcs12.Decode(b, *p12Password) if err != nil { return cert, err } cert.PrivateKey = key cert.Certificate = [][]byte{cer.Raw} return cert, nil } else { return tls.LoadX509KeyPair(*cerFile, *keyFile) } }
func testPfxRoundTrip(t *testing.T, privateKey interface{}) interface{} { certificateBytes, err := newCertificate("hostname", privateKey) if err != nil { t.Fatal(err.Error()) } bytes, err := Encode(certificateBytes, privateKey, "sesame") if err != nil { t.Fatal(err.Error()) } key, _, err := gopkcs12.Decode(bytes, "sesame") if err != nil { t.Fatalf(err.Error()) } return key }
func main() { devP := flag.Bool("d", false, "use development push server") flag.Parse() if flag.NArg() < 1 { log.Fatalf("usage: %s [-d] cert.p12", os.Args[0]) } var server string if *devP { server = "api.development.push.apple.com" } else { server = "api.push.apple.com" } d, err := ioutil.ReadFile(flag.Arg(0)) if err != nil { log.Fatal(err) } key, cert, err := pkcs12.Decode(d, "") if err != nil { log.Fatal(err) } tlsConfig := tls.Config{ Certificates: []tls.Certificate{{ Certificate: [][]byte{cert.Raw}, PrivateKey: key.(*rsa.PrivateKey), }}, } tlsConfig.BuildNameToCertificate() client := http.Client{ Transport: &http2.Transport{ TLSClientConfig: &tlsConfig, }, } scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { var notification Notification err := json.Unmarshal([]byte(scanner.Text()), ¬ification) if err != nil { log.Fatal(err) } resp, err := client.Post(fmt.Sprintf( "https://%s/3/device/%s", server, url.QueryEscape(notification.Token), ), "", bytes.NewReader(notification.Payload)) if err != nil { log.Fatal(err) } defer resp.Body.Close() var buf bytes.Buffer buf.ReadFrom(resp.Body) var rawRes *json.RawMessage if len(buf.Bytes()) != 0 { rm := json.RawMessage(buf.Bytes()) rawRes = &rm } json, err := json.Marshal(struct { Status int `json:"status"` Body *json.RawMessage `json:"body,omitempty"` }{resp.StatusCode, rawRes}) if err != nil { log.Fatal(err) } os.Stdout.Write(json) os.Stdout.Write([]byte{'\n'}) } if err := scanner.Err(); err != nil { log.Fatal(err) } }