├── .gitignore ├── README.md ├── client.go ├── gen.go └── server.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.key 2 | *.pem 3 | *.swp 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tls-example 2 | =========== 3 | 4 | Golang TLS example. x509 certificate create and sign. 5 | 6 | Usage: 7 | 8 | 9 | go run gen.go 10 | 2013/11/25 14:47:48 write to ca.pem 11 | 2013/11/25 14:47:48 write to ca.key 12 | 2013/11/25 14:47:49 write to cert2.pem 13 | 2013/11/25 14:47:49 write to cert2.key 14 | 2013/11/25 14:47:49 check signature true 15 | 16 | go run server.go 17 | 2013/11/25 14:49:48 server: listening 18 | 2013/11/25 14:49:54 server: accepted from 127.0.0.1:50207 19 | 2013/11/25 14:49:54 server: conn: waiting 20 | 2013/11/25 14:49:54 {[China] [Fuck] [FuckU] [] [] [] [] [{[2 5 4 6] China} {[2 5 4 10] Fuck} {[2 5 4 11] FuckU}]} 21 | 2013/11/25 14:49:54 server: conn: echo "Hello\n" 22 | 2013/11/25 14:49:54 server: conn: wrote 6 bytes 23 | 2013/11/25 14:49:54 server: conn: waiting 24 | 2013/11/25 14:49:54 server: conn: read: EOF 25 | 2013/11/25 14:49:54 server: conn: closed 26 | 27 | go run client.go 28 | 2013/11/25 14:49:21 client: connected to: 127.0.0.1:443 29 | 2013/11/25 14:49:21 client: handshake: true 30 | 2013/11/25 14:49:21 client: mutual: true 31 | 2013/11/25 14:49:21 client: wrote "Hello\n" (6 bytes) 32 | 2013/11/25 14:49:21 client: read "Hello\n" (6 bytes) 33 | 2013/11/25 14:49:21 client: exiting 34 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "log" 10 | ) 11 | 12 | func main() { 13 | cert2_b, _ := ioutil.ReadFile("cert2.pem") 14 | priv2_b, _ := ioutil.ReadFile("cert2.key") 15 | priv2, _ := x509.ParsePKCS1PrivateKey(priv2_b) 16 | 17 | cert := tls.Certificate{ 18 | Certificate: [][]byte{ cert2_b }, 19 | PrivateKey: priv2, 20 | } 21 | 22 | config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true} 23 | conn, err := tls.Dial("tcp", "127.0.0.1:443", &config) 24 | if err != nil { 25 | log.Fatalf("client: dial: %s", err) 26 | } 27 | defer conn.Close() 28 | log.Println("client: connected to: ", conn.RemoteAddr()) 29 | 30 | state := conn.ConnectionState() 31 | for _, v := range state.PeerCertificates { 32 | fmt.Println(x509.MarshalPKIXPublicKey(v.PublicKey)) 33 | fmt.Println(v.Subject) 34 | } 35 | log.Println("client: handshake: ", state.HandshakeComplete) 36 | log.Println("client: mutual: ", state.NegotiatedProtocolIsMutual) 37 | 38 | message := "Hello\n" 39 | n, err := io.WriteString(conn, message) 40 | if err != nil { 41 | log.Fatalf("client: write: %s", err) 42 | } 43 | log.Printf("client: wrote %q (%d bytes)", message, n) 44 | 45 | reply := make([]byte, 256) 46 | n, err = conn.Read(reply) 47 | log.Printf("client: read %q (%d bytes)", string(reply[:n]), n) 48 | log.Print("client: exiting") 49 | } 50 | 51 | -------------------------------------------------------------------------------- /gen.go: -------------------------------------------------------------------------------- 1 | 2 | package main 3 | 4 | import ( 5 | "crypto/x509" 6 | "crypto/x509/pkix" 7 | "crypto/rsa" 8 | "crypto/rand" 9 | "math/big" 10 | "io/ioutil" 11 | "log" 12 | "time" 13 | ) 14 | 15 | func main() { 16 | ca := &x509.Certificate{ 17 | SerialNumber: big.NewInt(1653), 18 | Subject: pkix.Name{ 19 | Country: []string{"China"}, 20 | Organization: []string{"Yjwt"}, 21 | OrganizationalUnit: []string{"YjwtU"}, 22 | }, 23 | NotBefore: time.Now(), 24 | NotAfter: time.Now().AddDate(10,0,0), 25 | SubjectKeyId: []byte{1,2,3,4,5}, 26 | BasicConstraintsValid: true, 27 | IsCA: true, 28 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, 29 | KeyUsage: x509.KeyUsageDigitalSignature|x509.KeyUsageCertSign, 30 | } 31 | 32 | priv, _ := rsa.GenerateKey(rand.Reader, 1024) 33 | pub := &priv.PublicKey 34 | ca_b, err := x509.CreateCertificate(rand.Reader, ca, ca, pub, priv) 35 | if err != nil { 36 | log.Println("create ca failed", err) 37 | return 38 | } 39 | ca_f := "ca.pem" 40 | log.Println("write to", ca_f) 41 | ioutil.WriteFile(ca_f, ca_b, 0777) 42 | 43 | priv_f := "ca.key" 44 | priv_b := x509.MarshalPKCS1PrivateKey(priv) 45 | log.Println("write to", priv_f) 46 | ioutil.WriteFile(priv_f, priv_b, 0777) 47 | 48 | cert2 := &x509.Certificate{ 49 | SerialNumber: big.NewInt(1658), 50 | Subject: pkix.Name{ 51 | Country: []string{"China"}, 52 | Organization: []string{"Fuck"}, 53 | OrganizationalUnit: []string{"FuckU"}, 54 | }, 55 | NotBefore: time.Now(), 56 | NotAfter: time.Now().AddDate(10,0,0), 57 | SubjectKeyId: []byte{1,2,3,4,6}, 58 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, 59 | KeyUsage: x509.KeyUsageDigitalSignature|x509.KeyUsageCertSign, 60 | } 61 | priv2, _ := rsa.GenerateKey(rand.Reader, 1024) 62 | pub2 := &priv2.PublicKey 63 | cert2_b, err2 := x509.CreateCertificate(rand.Reader, cert2, ca, pub2, priv) 64 | if err2 != nil { 65 | log.Println("create cert2 failed", err2) 66 | return 67 | } 68 | 69 | cert2_f := "cert2.pem" 70 | log.Println("write to", cert2_f) 71 | ioutil.WriteFile(cert2_f, cert2_b, 0777) 72 | 73 | priv2_f := "cert2.key" 74 | priv2_b := x509.MarshalPKCS1PrivateKey(priv2) 75 | log.Println("write to", priv2_f) 76 | ioutil.WriteFile(priv2_f, priv2_b, 0777) 77 | 78 | ca_c, _ := x509.ParseCertificate(ca_b) 79 | cert2_c, _ := x509.ParseCertificate(cert2_b) 80 | 81 | err3 := cert2_c.CheckSignatureFrom(ca_c) 82 | log.Println("check signature", err3 == nil) 83 | } 84 | 85 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/tls" 6 | "log" 7 | "net" 8 | "crypto/x509" 9 | "io/ioutil" 10 | ) 11 | 12 | func main() { 13 | 14 | ca_b, _ := ioutil.ReadFile("ca.pem") 15 | ca, _ := x509.ParseCertificate(ca_b) 16 | priv_b, _ := ioutil.ReadFile("ca.key") 17 | priv, _ := x509.ParsePKCS1PrivateKey(priv_b) 18 | 19 | pool := x509.NewCertPool() 20 | pool.AddCert(ca) 21 | 22 | cert := tls.Certificate{ 23 | Certificate: [][]byte{ ca_b }, 24 | PrivateKey: priv, 25 | } 26 | 27 | config := tls.Config{ 28 | ClientAuth: tls.RequireAndVerifyClientCert, 29 | Certificates: []tls.Certificate{cert}, 30 | ClientCAs: pool, 31 | } 32 | config.Rand = rand.Reader 33 | service := "0.0.0.0:443" 34 | listener, err := tls.Listen("tcp", service, &config) 35 | if err != nil { 36 | log.Fatalf("server: listen: %s", err) 37 | } 38 | log.Print("server: listening") 39 | 40 | for { 41 | conn, err := listener.Accept() 42 | if err != nil { 43 | log.Printf("server: accept: %s", err) 44 | break 45 | } 46 | defer conn.Close() 47 | log.Printf("server: accepted from %s", conn.RemoteAddr()) 48 | go handleClient(conn) 49 | } 50 | } 51 | 52 | func handleClient(conn net.Conn) { 53 | defer conn.Close() 54 | buf := make([]byte, 512) 55 | for { 56 | log.Print("server: conn: waiting") 57 | n, err := conn.Read(buf) 58 | if err != nil { 59 | if err != nil { 60 | log.Printf("server: conn: read: %s", err) 61 | } 62 | break 63 | } 64 | 65 | tlscon, ok := conn.(*tls.Conn) 66 | if ok { 67 | state := tlscon.ConnectionState() 68 | sub := state.PeerCertificates[0].Subject 69 | log.Println(sub) 70 | } 71 | 72 | log.Printf("server: conn: echo %q\n", string(buf[:n])) 73 | n, err = conn.Write(buf[:n]) 74 | 75 | n, err = conn.Write(buf[:n]) 76 | log.Printf("server: conn: wrote %d bytes", n) 77 | 78 | if err != nil { 79 | log.Printf("server: write: %s", err) 80 | break 81 | } 82 | } 83 | log.Println("server: conn: closed") 84 | } 85 | 86 | --------------------------------------------------------------------------------