Run gen.go:
# go run gen.go
package main
import (
"crypto/x509"
"crypto/x509/pkix"
"crypto/rsa"
"crypto/rand"
"math/big"
"io/ioutil"
"log"
"time"
)
func main() {
ca := &x509.Certificate{
SerialNumber: big.NewInt(1653),
Subject: pkix.Name{
Country: []string{"China"},
Organization: []string{"Yjwt"},
OrganizationalUnit: []string{"YjwtU"},
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10,0,0),
SubjectKeyId: []byte{1,2,3,4,5},
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature|x509.KeyUsageCertSign,
}
priv, _ := rsa.GenerateKey(rand.Reader, 1024)
pub := &priv.PublicKey
ca_b, err := x509.CreateCertificate(rand.Reader, ca, ca, pub, priv)
if err != nil {
log.Println("create ca failed", err)
return
}
ca_f := "ca.pem"
log.Println("write to", ca_f)
ioutil.WriteFile(ca_f, ca_b, 0777)
priv_f := "ca.key"
priv_b := x509.MarshalPKCS1PrivateKey(priv)
log.Println("write to", priv_f)
ioutil.WriteFile(priv_f, priv_b, 0777)
cert2 := &x509.Certificate{
SerialNumber: big.NewInt(1658),
Subject: pkix.Name{
Country: []string{"China"},
Organization: []string{"Fuck"},
OrganizationalUnit: []string{"FuckU"},
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10,0,0),
SubjectKeyId: []byte{1,2,3,4,6},
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature|x509.KeyUsageCertSign,
}
priv2, _ := rsa.GenerateKey(rand.Reader, 1024)
pub2 := &priv2.PublicKey
cert2_b, err2 := x509.CreateCertificate(rand.Reader, cert2, ca, pub2, priv)
if err2 != nil {
log.Println("create cert2 failed", err2)
return
}
cert2_f := "cert2.pem"
log.Println("write to", cert2_f)
ioutil.WriteFile(cert2_f, cert2_b, 0777)
priv2_f := "cert2.key"
priv2_b := x509.MarshalPKCS1PrivateKey(priv2)
log.Println("write to", priv2_f)
ioutil.WriteFile(priv2_f, priv2_b, 0777)
ca_c, _ := x509.ParseCertificate(ca_b)
cert2_c, _ := x509.ParseCertificate(cert2_b)
err3 := cert2_c.CheckSignatureFrom(ca_c)
log.Println("check signature", err3 == nil)
}
server.go:
package main
import (
"crypto/rand"
"crypto/tls"
"log"
"net"
"crypto/x509"
"io/ioutil"
)
func main() {
ca_b, _ := ioutil.ReadFile("ca.pem")
ca, _ := x509.ParseCertificate(ca_b)
priv_b, _ := ioutil.ReadFile("ca.key")
priv, _ := x509.ParsePKCS1PrivateKey(priv_b)
pool := x509.NewCertPool()
pool.AddCert(ca)
cert := tls.Certificate{
Certificate: [][]byte{ ca_b },
PrivateKey: priv,
}
config := tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{cert},
ClientCAs: pool,
}
config.Rand = rand.Reader
service := "0.0.0.0:443"
listener, err := tls.Listen("tcp", service, &config)
if err != nil {
log.Fatalf("server: listen: %s", err)
}
log.Print("server: listening")
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("server: accept: %s", err)
break
}
defer conn.Close()
log.Printf("server: accepted from %s", conn.RemoteAddr())
go handleClient(conn)
}
}
func handleClient(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 512)
for {
log.Print("server: conn: waiting")
n, err := conn.Read(buf)
if err != nil {
if err != nil {
log.Printf("server: conn: read: %s", err)
}
break
}
tlscon, ok := conn.(*tls.Conn)
if ok {
state := tlscon.ConnectionState()
sub := state.PeerCertificates[0].Subject
log.Println(sub)
}
log.Printf("server: conn: echo %q\n", string(buf[:n]))
n, err = conn.Write(buf[:n])
n, err = conn.Write(buf[:n])
log.Printf("server: conn: wrote %d bytes", n)
if err != nil {
log.Printf("server: write: %s", err)
break
}
}
log.Println("server: conn: closed")
}
client.go:
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"io/ioutil"
"log"
)
func main() {
cert2_b, _ := ioutil.ReadFile("cert2.pem")
priv2_b, _ := ioutil.ReadFile("cert2.key")
priv2, _ := x509.ParsePKCS1PrivateKey(priv2_b)
cert := tls.Certificate{
Certificate: [][]byte{ cert2_b },
PrivateKey: priv2,
}
config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
conn, err := tls.Dial("tcp", "127.0.0.1:443", &config)
if err != nil {
log.Fatalf("client: dial: %s", err)
}
defer conn.Close()
log.Println("client: connected to: ", conn.RemoteAddr())
state := conn.ConnectionState()
for _, v := range state.PeerCertificates {
fmt.Println(x509.MarshalPKIXPublicKey(v.PublicKey))
fmt.Println(v.Subject)
}
log.Println("client: handshake: ", state.HandshakeComplete)
log.Println("client: mutual: ", state.NegotiatedProtocolIsMutual)
message := "Hello\n"
n, err := io.WriteString(conn, message)
if err != nil {
log.Fatalf("client: write: %s", err)
}
log.Printf("client: wrote %q (%d bytes)", message, n)
reply := make([]byte, 256)
n, err = conn.Read(reply)
log.Printf("client: read %q (%d bytes)", string(reply[:n]), n)
log.Print("client: exiting")
}
Reference:
https://github.com/nareix/tls-example/blob/master/gen.go
No comments:
Post a Comment