| // 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. |
| } |