| // 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 = ` | |
| -- GlobalSign Root R2, valid until Dec 15, 2021 | |
| -----BEGIN CERTIFICATE----- | |
| MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G | |
| A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp | |
| Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 | |
| MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG | |
| A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI | |
| hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL | |
| v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 | |
| eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq | |
| tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd | |
| C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa | |
| zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB | |
| mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH | |
| V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n | |
| bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG | |
| 3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs | |
| J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO | |
| 291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS | |
| ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd | |
| AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 | |
| TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== | |
| -----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. | |
| } |