|  | // Copyright 2014 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package tls_test | 
|  |  | 
|  | import ( | 
|  | "crypto/tls" | 
|  | "crypto/x509" | 
|  | "errors" | 
|  | "log" | 
|  | "net/http" | 
|  | "net/http/httptest" | 
|  | "os" | 
|  | "time" | 
|  | ) | 
|  |  | 
|  | // zeroSource is an io.Reader that returns an unlimited number of zero bytes. | 
|  | type zeroSource struct{} | 
|  |  | 
|  | func (zeroSource) Read(b []byte) (n int, err error) { | 
|  | for i := range b { | 
|  | b[i] = 0 | 
|  | } | 
|  |  | 
|  | return len(b), nil | 
|  | } | 
|  |  | 
|  | func ExampleDial() { | 
|  | // Connecting with a custom root-certificate set. | 
|  |  | 
|  | const rootPEM = ` | 
|  | -----BEGIN CERTIFICATE----- | 
|  | MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT | 
|  | MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i | 
|  | YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG | 
|  | EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy | 
|  | bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB | 
|  | AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP | 
|  | VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv | 
|  | h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE | 
|  | ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ | 
|  | EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC | 
|  | DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7 | 
|  | qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD | 
|  | VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g | 
|  | K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI | 
|  | KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n | 
|  | ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB | 
|  | BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY | 
|  | /iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/ | 
|  | zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza | 
|  | HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto | 
|  | WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6 | 
|  | yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx | 
|  | -----END CERTIFICATE-----` | 
|  |  | 
|  | // First, create the set of root certificates. For this example we only | 
|  | // have one. It's also possible to omit this in order to use the | 
|  | // default root set of the current operating system. | 
|  | roots := x509.NewCertPool() | 
|  | ok := roots.AppendCertsFromPEM([]byte(rootPEM)) | 
|  | if !ok { | 
|  | panic("failed to parse root certificate") | 
|  | } | 
|  |  | 
|  | conn, err := tls.Dial("tcp", "mail.google.com:443", &tls.Config{ | 
|  | RootCAs: roots, | 
|  | }) | 
|  | if err != nil { | 
|  | panic("failed to connect: " + err.Error()) | 
|  | } | 
|  | conn.Close() | 
|  | } | 
|  |  | 
|  | func ExampleConfig_keyLogWriter() { | 
|  | // Debugging TLS applications by decrypting a network traffic capture. | 
|  |  | 
|  | // WARNING: Use of KeyLogWriter compromises security and should only be | 
|  | // used for debugging. | 
|  |  | 
|  | // Dummy test HTTP server for the example with insecure random so output is | 
|  | // reproducible. | 
|  | server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) | 
|  | server.TLS = &tls.Config{ | 
|  | Rand: zeroSource{}, // for example only; don't do this. | 
|  | } | 
|  | server.StartTLS() | 
|  | defer server.Close() | 
|  |  | 
|  | // Typically the log would go to an open file: | 
|  | // w, err := os.OpenFile("tls-secrets.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) | 
|  | w := os.Stdout | 
|  |  | 
|  | client := &http.Client{ | 
|  | Transport: &http.Transport{ | 
|  | TLSClientConfig: &tls.Config{ | 
|  | KeyLogWriter: w, | 
|  |  | 
|  | Rand:               zeroSource{}, // for reproducible output; don't do this. | 
|  | InsecureSkipVerify: true,         // test server certificate is not trusted. | 
|  | }, | 
|  | }, | 
|  | } | 
|  | resp, err := client.Get(server.URL) | 
|  | if err != nil { | 
|  | log.Fatalf("Failed to get URL: %v", err) | 
|  | } | 
|  | resp.Body.Close() | 
|  |  | 
|  | // The resulting file can be used with Wireshark to decrypt the TLS | 
|  | // connection by setting (Pre)-Master-Secret log filename in SSL Protocol | 
|  | // preferences. | 
|  | } | 
|  |  | 
|  | func ExampleLoadX509KeyPair() { | 
|  | cert, err := tls.LoadX509KeyPair("testdata/example-cert.pem", "testdata/example-key.pem") | 
|  | if err != nil { | 
|  | log.Fatal(err) | 
|  | } | 
|  | cfg := &tls.Config{Certificates: []tls.Certificate{cert}} | 
|  | listener, err := tls.Listen("tcp", ":2000", cfg) | 
|  | if err != nil { | 
|  | log.Fatal(err) | 
|  | } | 
|  | _ = listener | 
|  | } | 
|  |  | 
|  | func ExampleX509KeyPair() { | 
|  | certPem := []byte(`-----BEGIN CERTIFICATE----- | 
|  | MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw | 
|  | DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow | 
|  | EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d | 
|  | 7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B | 
|  | 5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr | 
|  | BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1 | 
|  | NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l | 
|  | Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc | 
|  | 6MF9+Yw1Yy0t | 
|  | -----END CERTIFICATE-----`) | 
|  | keyPem := []byte(`-----BEGIN EC PRIVATE KEY----- | 
|  | MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49 | 
|  | AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q | 
|  | EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA== | 
|  | -----END EC PRIVATE KEY-----`) | 
|  | cert, err := tls.X509KeyPair(certPem, keyPem) | 
|  | if err != nil { | 
|  | log.Fatal(err) | 
|  | } | 
|  | cfg := &tls.Config{Certificates: []tls.Certificate{cert}} | 
|  | listener, err := tls.Listen("tcp", ":2000", cfg) | 
|  | if err != nil { | 
|  | log.Fatal(err) | 
|  | } | 
|  | _ = listener | 
|  | } | 
|  |  | 
|  | func ExampleX509KeyPair_httpServer() { | 
|  | certPem := []byte(`-----BEGIN CERTIFICATE----- | 
|  | MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw | 
|  | DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow | 
|  | EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d | 
|  | 7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B | 
|  | 5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr | 
|  | BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1 | 
|  | NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l | 
|  | Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc | 
|  | 6MF9+Yw1Yy0t | 
|  | -----END CERTIFICATE-----`) | 
|  | keyPem := []byte(`-----BEGIN EC PRIVATE KEY----- | 
|  | MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49 | 
|  | AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q | 
|  | EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA== | 
|  | -----END EC PRIVATE KEY-----`) | 
|  | cert, err := tls.X509KeyPair(certPem, keyPem) | 
|  | if err != nil { | 
|  | log.Fatal(err) | 
|  | } | 
|  | cfg := &tls.Config{Certificates: []tls.Certificate{cert}} | 
|  | srv := &http.Server{ | 
|  | TLSConfig:    cfg, | 
|  | ReadTimeout:  time.Minute, | 
|  | WriteTimeout: time.Minute, | 
|  | } | 
|  | log.Fatal(srv.ListenAndServeTLS("", "")) | 
|  | } | 
|  |  | 
|  | func ExampleConfig_verifyPeerCertificate() { | 
|  | // VerifyPeerCertificate can be used to replace and customize certificate | 
|  | // verification. This example shows a VerifyPeerCertificate implementation | 
|  | // that will be approximately equivalent to what crypto/tls does normally. | 
|  |  | 
|  | config := &tls.Config{ | 
|  | // Set InsecureSkipVerify to skip the default validation we are | 
|  | // replacing. This will not disable VerifyPeerCertificate. | 
|  | InsecureSkipVerify: true, | 
|  |  | 
|  | // While packages like net/http will implicitly set ServerName, the | 
|  | // VerifyPeerCertificate callback can't access that value, so it has to be set | 
|  | // explicitly here or in VerifyPeerCertificate on the client side. If in | 
|  | // an http.Transport DialTLS callback, this can be obtained by passing | 
|  | // the addr argument to net.SplitHostPort. | 
|  | ServerName: "example.com", | 
|  |  | 
|  | // On the server side, set ClientAuth to require client certificates (or | 
|  | // VerifyPeerCertificate will run anyway and panic accessing certs[0]) | 
|  | // but not verify them with the default verifier. | 
|  | // ClientAuth: tls.RequireAnyClientCert, | 
|  | } | 
|  |  | 
|  | config.VerifyPeerCertificate = func(certificates [][]byte, _ [][]*x509.Certificate) error { | 
|  | certs := make([]*x509.Certificate, len(certificates)) | 
|  | for i, asn1Data := range certificates { | 
|  | cert, err := x509.ParseCertificate(asn1Data) | 
|  | if err != nil { | 
|  | return errors.New("tls: failed to parse certificate from server: " + err.Error()) | 
|  | } | 
|  | certs[i] = cert | 
|  | } | 
|  |  | 
|  | opts := x509.VerifyOptions{ | 
|  | Roots:         config.RootCAs, // On the server side, use config.ClientCAs. | 
|  | DNSName:       config.ServerName, | 
|  | Intermediates: x509.NewCertPool(), | 
|  | // On the server side, set KeyUsages to ExtKeyUsageClientAuth. The | 
|  | // default value is appropriate for clients side verification. | 
|  | // KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, | 
|  | } | 
|  | for _, cert := range certs[1:] { | 
|  | opts.Intermediates.AddCert(cert) | 
|  | } | 
|  | _, err := certs[0].Verify(opts) | 
|  | return err | 
|  | } | 
|  |  | 
|  | // Note that when InsecureSkipVerify and VerifyPeerCertificate are in use, | 
|  | // ConnectionState.VerifiedChains will be nil. | 
|  | } |