Skip to content

Instantly share code, notes, and snippets.

@shaneutt
Forked from ncw/README.txt
Created March 9, 2022 19:17
Show Gist options
  • Save shaneutt/2ca973903cfd5a318ddd6fc7e296c52f to your computer and use it in GitHub Desktop.
Save shaneutt/2ca973903cfd5a318ddd6fc7e296c52f to your computer and use it in GitHub Desktop.

Revisions

  1. @ncw ncw revised this gist Mar 5, 2014. 1 changed file with 1 addition and 64 deletions.
    65 changes: 1 addition & 64 deletions README.txt
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    This demonstrates a bug in Go
    This demonstrates how to make client side certificates with go

    First generate the certificates with

    @@ -12,66 +12,3 @@ Run the client in the other

    go run client.go

    You'll see an SSL negotiation failure

    The Server says

    2014/02/27 16:33:51 server: listening
    2014/02/27 16:33:53 server: accepted from 127.0.0.1:43700
    2014/02/27 16:33:53 server: conn: type assert to TLS succeedded
    2014/02/27 16:33:53 server: handshake failed: tls: client's certificate's extended key usage doesn't permit it to be used for client authentication
    exit status 1

    And the Client says

    2014/02/27 16:33:53 client: dial: remote error: handshake failure
    exit status 1

    If you then try to add the extended usage to the certificate with the -addtrust clientAuth (uncomment in makecert.sh) you get this from the Client

    2014/02/27 16:36:58 server: loadkeys: crypto/tls: failed to parse certificate PEM data
    exit status 1

    Because the client can no longer read the certificate which now starts with

    -----BEGIN TRUSTED CERTIFICATE-----
    MIIDizCCAnMCAQEwDQYJKoZIhvcNAQEFBQAwgZExCzAJBgNVBAYTAkRFMQwwCgYD

    The relevant code is in crypo/tls/handshake_server.go

    ok := false
    for _, ku := range certs[0].ExtKeyUsage {
    if ku == x509.ExtKeyUsageClientAuth {
    ok = true
    break
    }
    }
    if !ok {
    c.sendAlert(alertHandshakeFailure)
    return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
    }

    I think Go is making a mistake in assuming that client certificates
    without the extended usage attributes (ie most client certificates)
    should be denied use as a client authentication.

    So removing this code would fix the problem or possibly Go should
    assume certificates without the extended trust attributes should be
    allowed rather than rejected.

    From the OpenSSL docs

    http://www.openssl.org/docs/apps/x509.html

    > Trust settings currently are only used with a root CA. They allow a
    > finer control over the purposes the root CA can be used for. For
    > example a CA may be trusted for SSL client but not SSL server use.
    >
    > See the description of the verify utility for more information on
    > the meaning of trust settings.
    >
    > Future versions of OpenSSL will recognize trust settings on any
    > certificate: not just root CAs.

    Indicating that OpenSSL doesn't use these trust settings at all
    (confirmed with my experiments with Apache).
  2. @ncw ncw revised this gist Mar 5, 2014. 1 changed file with 0 additions and 3 deletions.
    3 changes: 0 additions & 3 deletions openssl.conf
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,2 @@
    [ ssl_client ]
    basicConstraints = CA:FALSE
    nsCertType = client
    keyUsage = digitalSignature, keyEncipherment
    extendedKeyUsage = clientAuth
  3. @ncw ncw revised this gist Mar 5, 2014. 2 changed files with 7 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions makecert.sh
    Original file line number Diff line number Diff line change
    @@ -29,3 +29,5 @@ echo "00" > ca.srl
    openssl req -sha1 -key client.key -new -out client.req -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=client.com/emailAddress=${EMAIL}"
    # Adding -addtrust clientAuth makes certificates Go can't read
    openssl x509 -req -days 365 -in client.req -CA ca.pem -CAkey ca.key -passin pass:$PRIVKEY -out client.pem # -addtrust clientAuth

    openssl x509 -extfile ../openssl.conf -extensions ssl_client -req -days 365 -in client.req -CA ca.pem -CAkey ca.key -passin pass:$PRIVKEY -out client.pem
    5 changes: 5 additions & 0 deletions openssl.conf
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    [ ssl_client ]
    basicConstraints = CA:FALSE
    nsCertType = client
    keyUsage = digitalSignature, keyEncipherment
    extendedKeyUsage = clientAuth
  4. @ncw ncw revised this gist Feb 27, 2014. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions README.txt
    Original file line number Diff line number Diff line change
    @@ -51,9 +51,9 @@ The relevant code is in crypo/tls/handshake_server.go
    return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
    }

    I think Go is making a mistake in assuming that clients without the
    extended usage attributes (ie most client certificates) should be
    denied use as a client certificate.
    I think Go is making a mistake in assuming that client certificates
    without the extended usage attributes (ie most client certificates)
    should be denied use as a client authentication.

    So removing this code would fix the problem or possibly Go should
    assume certificates without the extended trust attributes should be
  5. @ncw ncw revised this gist Feb 27, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion makecert.sh
    Original file line number Diff line number Diff line change
    @@ -28,4 +28,4 @@ openssl genrsa -out client.key 2048
    echo "00" > ca.srl
    openssl req -sha1 -key client.key -new -out client.req -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=client.com/emailAddress=${EMAIL}"
    # Adding -addtrust clientAuth makes certificates Go can't read
    openssl x509 -req -days 365 -in client.req -CA ca.pem -CAkey ca.key -passin pass:$PRIVKEY -out client.pem -addtrust clientAuth
    openssl x509 -req -days 365 -in client.req -CA ca.pem -CAkey ca.key -passin pass:$PRIVKEY -out client.pem # -addtrust clientAuth
  6. @ncw ncw revised this gist Feb 27, 2014. 6 changed files with 210 additions and 120 deletions.
    77 changes: 77 additions & 0 deletions README.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,77 @@
    This demonstrates a bug in Go

    First generate the certificates with

    ./makecert.sh [email protected]

    Run the server in one terminal

    go run server.go

    Run the client in the other

    go run client.go

    You'll see an SSL negotiation failure

    The Server says

    2014/02/27 16:33:51 server: listening
    2014/02/27 16:33:53 server: accepted from 127.0.0.1:43700
    2014/02/27 16:33:53 server: conn: type assert to TLS succeedded
    2014/02/27 16:33:53 server: handshake failed: tls: client's certificate's extended key usage doesn't permit it to be used for client authentication
    exit status 1

    And the Client says

    2014/02/27 16:33:53 client: dial: remote error: handshake failure
    exit status 1

    If you then try to add the extended usage to the certificate with the -addtrust clientAuth (uncomment in makecert.sh) you get this from the Client

    2014/02/27 16:36:58 server: loadkeys: crypto/tls: failed to parse certificate PEM data
    exit status 1

    Because the client can no longer read the certificate which now starts with

    -----BEGIN TRUSTED CERTIFICATE-----
    MIIDizCCAnMCAQEwDQYJKoZIhvcNAQEFBQAwgZExCzAJBgNVBAYTAkRFMQwwCgYD

    The relevant code is in crypo/tls/handshake_server.go

    ok := false
    for _, ku := range certs[0].ExtKeyUsage {
    if ku == x509.ExtKeyUsageClientAuth {
    ok = true
    break
    }
    }
    if !ok {
    c.sendAlert(alertHandshakeFailure)
    return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
    }

    I think Go is making a mistake in assuming that clients without the
    extended usage attributes (ie most client certificates) should be
    denied use as a client certificate.

    So removing this code would fix the problem or possibly Go should
    assume certificates without the extended trust attributes should be
    allowed rather than rejected.

    From the OpenSSL docs

    http://www.openssl.org/docs/apps/x509.html

    > Trust settings currently are only used with a root CA. They allow a
    > finer control over the purposes the root CA can be used for. For
    > example a CA may be trusted for SSL client but not SSL server use.
    >
    > See the description of the verify utility for more information on
    > the meaning of trust settings.
    >
    > Future versions of OpenSSL will recognize trust settings on any
    > certificate: not just root CAs.

    Indicating that OpenSSL doesn't use these trust settings at all
    (confirmed with my experiments with Apache).
    10 changes: 0 additions & 10 deletions client output
    Original file line number Diff line number Diff line change
    @@ -1,10 +0,0 @@
    $ go run client.go
    2012/03/28 22:30:21 client: connected to: 127.0.0.1:8000
    Client: Server public key is:
    [48 129 159 48 13 6 9 42 134 72 134 247 13 1 1 1 5 0 3 129 141 0 48 129 137 2 129 129 0 188 73 207 11 137 150 106 118 45 27 12 18 76 183 252 31 22 193 109 43 118 130 188 244 197 136 26 55 239 51 225 67 171 20 87 35 107 190 16 158 181 84 225 159 112 70 131 173 136 181 130 151 156 4 142 141 218 100 116 219 228 211 136 155 179 220 50 21 181 134 211 72 22 38 226 51 170 165 39 65 231 3 15 26 54 193 142 242 28 66 96 88 138 237 217 65 144 89 231 177 179 200 116 30 45 148 174 56 57 244 29 17 8 22 86 54 215 14 207 55 223 164 216 184 21 46 29 233 2 3 1 0 1] <nil>
    2012/03/28 22:30:21 client: handshake: true
    2012/03/28 22:30:21 client: mutual: true
    2012/03/28 22:30:21 client: wrote "Hello\n" (6 bytes)
    2012/03/28 22:30:21 client: read "Hello\n" (6 bytes)
    2012/03/28 22:30:21 client: exiting
    $
    66 changes: 33 additions & 33 deletions client.go
    Original file line number Diff line number Diff line change
    @@ -1,40 +1,40 @@
    package main

    import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "io"
    "log"
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "io"
    "log"
    )

    func main() {
    cert, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key")
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
    conn, err := tls.Dial("tcp", "127.0.0.1:8000", &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("Client: Server public key is:")
    fmt.Println(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    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")
    cert, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key")
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
    conn, err := tls.Dial("tcp", "127.0.0.1:8000", &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("Client: Server public key is:")
    fmt.Println(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    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")
    }
    27 changes: 24 additions & 3 deletions makecert.sh
    100644 → 100755
    Original file line number Diff line number Diff line change
    @@ -2,9 +2,30 @@
    # call this script with an email address (valid or not).
    # like:
    # ./makecert.sh [email protected]

    if [ "$1" == "" ]; then
    echo "Need email as argument"
    exit 1
    fi

    EMAIL=$1

    rm -rf certs
    mkdir certs
    rm certs/*
    cd certs

    echo "make CA"
    PRIVKEY="test"
    openssl req -new -x509 -days 365 -keyout ca.key -out ca.pem -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=www.random.com/[email protected]" -passout pass:$PRIVKEY

    echo "make server cert"
    openssl req -new -nodes -x509 -out certs/server.pem -keyout certs/server.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=www.random.com/emailAddress=$1"
    openssl req -new -nodes -x509 -out server.pem -keyout server.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=www.random.com/emailAddress=${EMAIL}"

    echo "make client cert"
    openssl req -new -nodes -x509 -out certs/client.pem -keyout certs/client.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=www.random.com/emailAddress=$1"
    #openssl req -new -nodes -x509 -out client.pem -keyout client.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=www.random.com/emailAddress=${EMAIL}"

    openssl genrsa -out client.key 2048
    echo "00" > ca.srl
    openssl req -sha1 -key client.key -new -out client.req -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=client.com/emailAddress=${EMAIL}"
    # Adding -addtrust clientAuth makes certificates Go can't read
    openssl x509 -req -days 365 -in client.req -CA ca.pem -CAkey ca.key -passin pass:$PRIVKEY -out client.pem -addtrust clientAuth
    13 changes: 0 additions & 13 deletions server output
    Original file line number Diff line number Diff line change
    @@ -1,13 +0,0 @@
    $ go run server.go
    2012/03/28 22:30:17 server: listening
    2012/03/28 22:30:21 server: accepted from 127.0.0.1:38020
    2012/03/28 22:30:21 server: conn: type assert to TLS succeedded
    2012/03/28 22:30:21 server: conn: Handshake completed
    2012/03/28 22:30:21 Server: client public key is:
    2012/03/28 22:30:21 [48 129 159 48 13 6 9 42 134 72 134 247 13 1 1 1 5 0 3 129 141 0 48 129 137 2 129 129 0 204 185 196 229 49 15 70 253 60 159 47 189 29 191 186 227 79 255 65 205 234 251 13 21 2 185 57 145 54 67 148 140 183 135 146 159 86 19 214 193 143 173 197 143 14 129 165 79 164 255 170 208 21 79 148 6 211 115 54 18 244 61 136 231 86 157 84 192 125 62 56 210 150 103 110 8 95 241 167 39 67 119 95 64 135 60 74 62 184 20 100 162 81 180 177 124 39 236 140 133 137 215 246 184 244 244 74 120 1 18 196 153 228 235 208 173 53 247 148 41 5 166 68 133 160 153 152 231 2 3 1 0 1] <nil>
    2012/03/28 22:30:21 server: conn: waiting
    2012/03/28 22:30:21 server: conn: echo "Hello\n"
    2012/03/28 22:30:21 server: conn: wrote 6 bytes
    2012/03/28 22:30:21 server: conn: waiting
    2012/03/28 22:30:21 server: conn: read: EOF
    2012/03/28 22:30:21 server: conn: closed
    137 changes: 76 additions & 61 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -1,72 +1,87 @@
    package main

    import (
    "crypto/rand"
    "crypto/tls"
    "crypto/x509"
    "log"
    "net"
    "crypto/rand"
    "crypto/tls"
    "crypto/x509"
    "io/ioutil"
    "log"
    "net"
    )

    func main() {
    cert, err := tls.LoadX509KeyPair("certs/server.pem", "certs/server.key")
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{Certificates: []tls.Certificate{cert}, ClientAuth: tls.RequireAnyClientCert}
    config.Rand = rand.Reader
    service := "0.0.0.0:8000"
    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
    }
    log.Printf("server: accepted from %s", conn.RemoteAddr())
    go handleClient(conn)
    }
    cert, err := tls.LoadX509KeyPair("certs/server.pem", "certs/server.key")
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)

    }
    certpool := x509.NewCertPool()
    pem, err := ioutil.ReadFile("certs/ca.pem")
    if err != nil {
    log.Fatalf("Failed to read client certificate authority: %v", err)
    }
    if !certpool.AppendCertsFromPEM(pem) {
    log.Fatalf("Can't parse client certificate authority")
    }

    config := tls.Config{
    Certificates: []tls.Certificate{cert},
    ClientAuth: tls.RequireAndVerifyClientCert,
    ClientCAs: certpool,
    }
    config.Rand = rand.Reader
    service := "0.0.0.0:8000"
    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
    }
    log.Printf("server: accepted from %s", conn.RemoteAddr())
    go handleClient(conn)
    }
    }

    func handleClient(conn net.Conn) {
    defer conn.Close()
    tlscon, ok := conn.(*tls.Conn)
    if ok {
    log.Print("server: conn: type assert to TLS succeedded")
    err := tlscon.Handshake()
    if err != nil {
    log.Fatalf("server: handshake failed: %s", err)
    } else {
    log.Print("server: conn: Handshake completed")
    }
    state := tlscon.ConnectionState()
    log.Println("Server: client public key is:")
    for _, v := range state.PeerCertificates {
    log.Print(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    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
    defer conn.Close()
    tlscon, ok := conn.(*tls.Conn)
    if ok {
    log.Print("server: conn: type assert to TLS succeedded")
    err := tlscon.Handshake()
    if err != nil {
    log.Fatalf("server: handshake failed: %s", err)
    } else {
    log.Print("server: conn: Handshake completed")
    }
    state := tlscon.ConnectionState()
    log.Println("Server: client public key is:")
    for _, v := range state.PeerCertificates {
    log.Print(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    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

    }
    log.Printf("server: conn: echo %q\n", string(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")
    }
    log.Printf("server: conn: echo %q\n", string(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")
    }
  7. @spikebike spikebike revised this gist Mar 29, 2012. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion client.go
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,6 @@ func main() {
    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)
  8. @spikebike spikebike revised this gist Mar 29, 2012. 1 changed file with 0 additions and 11 deletions.
    11 changes: 0 additions & 11 deletions output of server
    Original file line number Diff line number Diff line change
    @@ -1,11 +0,0 @@
    $ go run server.go
    2012/03/28 20:58:03 server: listening
    2012/03/28 20:58:07 server: accepted from 127.0.0.1:37635
    2012/03/28 20:58:07 server: conn: type assert to TLS succeedded
    2012/03/28 20:58:07 server: conn: Handshake completed
    2012/03/28 20:58:07 server: conn: waiting
    2012/03/28 20:58:07 server: conn: echo "Hello\n"
    2012/03/28 20:58:07 server: conn: wrote 6 bytes
    2012/03/28 20:58:07 server: conn: waiting
    2012/03/28 20:58:07 server: conn: read: EOF
    2012/03/28 20:58:07 server: conn: closed
  9. @spikebike spikebike revised this gist Mar 29, 2012. 5 changed files with 42 additions and 28 deletions.
    17 changes: 9 additions & 8 deletions client output
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,10 @@
    $ go run client.go
    2012/03/28 20:58:07 client: connected to: 127.0.0.1:8000
    [48 129 159 48 13 6 9 42 134 72 134 247 13 1 1 1 5 0 3 129 141 0 48 129 137 2 129 129 0 184 227 73 69 247 234 77 230 32 214 208 53 61 231 223 9 161 111 222 104 102 15 23 72 219 65 209 42 76 255 7 127 149 180 123 75 124 154 143 78 190 237 223 65 255 217 149 176 191 49 18 85 253 133 215 99 112 64 195 156 244 72 245 209 23 222 78 219 13 188 174 117 209 140 35 19 251 95 209 186 37 200 61 246 16 68 165 215 65 15 172 195 201 29 198 78 101 178 95 222 182 161 1 74 231 103 88 25 175 138 180 156 163 91 52 250 61 198 104 162 83 123 14 103 95 251 81 129 2 3 1 0 1] <nil>
    {[DE] [Random Company] [IT] [Earth] [NRW] [] [] www.random.com [{[2 5 4 6] DE} {[2 5 4 8] NRW} {[2 5 4 7] Earth} {[2 5 4 10] Random Company} {[2 5 4 11] IT} {[2 5 4 3] www.random.com} {[1 2 840 113549 1 9 1] [email protected]}]}
    2012/03/28 20:58:07 client: handshake: true
    2012/03/28 20:58:07 client: mutual: true
    2012/03/28 20:58:07 client: wrote "Hello\n" (6 bytes)
    2012/03/28 20:58:07 client: read "Hello\n" (6 bytes)
    2012/03/28 20:58:07 client: exiting
    2012/03/28 22:30:21 client: connected to: 127.0.0.1:8000
    Client: Server public key is:
    [48 129 159 48 13 6 9 42 134 72 134 247 13 1 1 1 5 0 3 129 141 0 48 129 137 2 129 129 0 188 73 207 11 137 150 106 118 45 27 12 18 76 183 252 31 22 193 109 43 118 130 188 244 197 136 26 55 239 51 225 67 171 20 87 35 107 190 16 158 181 84 225 159 112 70 131 173 136 181 130 151 156 4 142 141 218 100 116 219 228 211 136 155 179 220 50 21 181 134 211 72 22 38 226 51 170 165 39 65 231 3 15 26 54 193 142 242 28 66 96 88 138 237 217 65 144 89 231 177 179 200 116 30 45 148 174 56 57 244 29 17 8 22 86 54 215 14 207 55 223 164 216 184 21 46 29 233 2 3 1 0 1] <nil>
    2012/03/28 22:30:21 client: handshake: true
    2012/03/28 22:30:21 client: mutual: true
    2012/03/28 22:30:21 client: wrote "Hello\n" (6 bytes)
    2012/03/28 22:30:21 client: read "Hello\n" (6 bytes)
    2012/03/28 22:30:21 client: exiting
    $
    4 changes: 1 addition & 3 deletions client.go
    Original file line number Diff line number Diff line change
    @@ -20,15 +20,13 @@ func main() {
    }
    defer conn.Close()
    log.Println("client: connected to: ", conn.RemoteAddr())

    state := conn.ConnectionState()
    for _, v := range state.PeerCertificates {
    fmt.Println("Client: Server public key is:")
    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 {
    2 changes: 1 addition & 1 deletion makecert.sh
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    #!/bin/bash
    # call this script with an email address (valid or not).
    # like:
    # ./makecert.sh joe@random.com
    # ./makecert.sh foo@foo.com
    mkdir certs
    rm certs/*
    echo "make server cert"
    13 changes: 13 additions & 0 deletions server output
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    $ go run server.go
    2012/03/28 22:30:17 server: listening
    2012/03/28 22:30:21 server: accepted from 127.0.0.1:38020
    2012/03/28 22:30:21 server: conn: type assert to TLS succeedded
    2012/03/28 22:30:21 server: conn: Handshake completed
    2012/03/28 22:30:21 Server: client public key is:
    2012/03/28 22:30:21 [48 129 159 48 13 6 9 42 134 72 134 247 13 1 1 1 5 0 3 129 141 0 48 129 137 2 129 129 0 204 185 196 229 49 15 70 253 60 159 47 189 29 191 186 227 79 255 65 205 234 251 13 21 2 185 57 145 54 67 148 140 183 135 146 159 86 19 214 193 143 173 197 143 14 129 165 79 164 255 170 208 21 79 148 6 211 115 54 18 244 61 136 231 86 157 84 192 125 62 56 210 150 103 110 8 95 241 167 39 67 119 95 64 135 60 74 62 184 20 100 162 81 180 177 124 39 236 140 133 137 215 246 184 244 244 74 120 1 18 196 153 228 235 208 173 53 247 148 41 5 166 68 133 160 153 152 231 2 3 1 0 1] <nil>
    2012/03/28 22:30:21 server: conn: waiting
    2012/03/28 22:30:21 server: conn: echo "Hello\n"
    2012/03/28 22:30:21 server: conn: wrote 6 bytes
    2012/03/28 22:30:21 server: conn: waiting
    2012/03/28 22:30:21 server: conn: read: EOF
    2012/03/28 22:30:21 server: conn: closed
    34 changes: 18 additions & 16 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,7 @@ func main() {
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{Certificates: []tls.Certificate{cert}}
    config := tls.Config{Certificates: []tls.Certificate{cert}, ClientAuth: tls.RequireAnyClientCert}
    config.Rand = rand.Reader
    service := "0.0.0.0:8000"
    listener, err := tls.Listen("tcp", service, &config)
    @@ -44,26 +44,28 @@ func handleClient(conn net.Conn) {
    log.Print("server: conn: Handshake completed")
    }
    state := tlscon.ConnectionState()
    log.Println("Server: client public key is:")
    for _, v := range state.PeerCertificates {
    log.Print(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    }
    buf := make([]byte, 512)
    for {
    log.Print("server: conn: waiting")
    n, err := conn.Read(buf)
    if err != nil {
    buf := make([]byte, 512)
    for {
    log.Print("server: conn: waiting")
    n, err := conn.Read(buf)
    if err != nil {
    log.Printf("server: conn: read: %s", err)
    }
    break
    }
    log.Printf("server: conn: echo %q\n", string(buf[:n]))
    n, err = conn.Write(buf[:n])
    if err != nil {
    log.Printf("server: conn: read: %s", err)
    }
    break

    if err != nil {
    log.Printf("server: write: %s", err)
    break
    }
    log.Printf("server: conn: echo %q\n", string(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")
  10. @spikebike spikebike revised this gist Mar 29, 2012. 1 changed file with 9 additions and 0 deletions.
    9 changes: 9 additions & 0 deletions client output
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    $ go run client.go
    2012/03/28 20:58:07 client: connected to: 127.0.0.1:8000
    [48 129 159 48 13 6 9 42 134 72 134 247 13 1 1 1 5 0 3 129 141 0 48 129 137 2 129 129 0 184 227 73 69 247 234 77 230 32 214 208 53 61 231 223 9 161 111 222 104 102 15 23 72 219 65 209 42 76 255 7 127 149 180 123 75 124 154 143 78 190 237 223 65 255 217 149 176 191 49 18 85 253 133 215 99 112 64 195 156 244 72 245 209 23 222 78 219 13 188 174 117 209 140 35 19 251 95 209 186 37 200 61 246 16 68 165 215 65 15 172 195 201 29 198 78 101 178 95 222 182 161 1 74 231 103 88 25 175 138 180 156 163 91 52 250 61 198 104 162 83 123 14 103 95 251 81 129 2 3 1 0 1] <nil>
    {[DE] [Random Company] [IT] [Earth] [NRW] [] [] www.random.com [{[2 5 4 6] DE} {[2 5 4 8] NRW} {[2 5 4 7] Earth} {[2 5 4 10] Random Company} {[2 5 4 11] IT} {[2 5 4 3] www.random.com} {[1 2 840 113549 1 9 1] [email protected]}]}
    2012/03/28 20:58:07 client: handshake: true
    2012/03/28 20:58:07 client: mutual: true
    2012/03/28 20:58:07 client: wrote "Hello\n" (6 bytes)
    2012/03/28 20:58:07 client: read "Hello\n" (6 bytes)
    2012/03/28 20:58:07 client: exiting
  11. @spikebike spikebike revised this gist Mar 29, 2012. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions output of server
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    $ go run server.go
    2012/03/28 20:58:03 server: listening
    2012/03/28 20:58:07 server: accepted from 127.0.0.1:37635
    2012/03/28 20:58:07 server: conn: type assert to TLS succeedded
    2012/03/28 20:58:07 server: conn: Handshake completed
    2012/03/28 20:58:07 server: conn: waiting
    2012/03/28 20:58:07 server: conn: echo "Hello\n"
    2012/03/28 20:58:07 server: conn: wrote 6 bytes
    2012/03/28 20:58:07 server: conn: waiting
    2012/03/28 20:58:07 server: conn: read: EOF
    2012/03/28 20:58:07 server: conn: closed
  12. @spikebike spikebike revised this gist Mar 29, 2012. 1 changed file with 14 additions and 15 deletions.
    29 changes: 14 additions & 15 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -27,26 +27,27 @@ func main() {
    log.Printf("server: accept: %s", err)
    break
    }
    defer conn.Close()
    log.Printf("server: accepted from %s", conn.RemoteAddr())
    tlscon, ok := conn.(*tls.Conn)
    err = tlscon.Handshake()
    if err != nil {
    break
    }
    if ok {
    log.Print("ok=true")
    state := tlscon.ConnectionState()
    for _, v := range state.PeerCertificates {
    log.Print(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    }
    go handleClient(conn)
    }
    }

    func handleClient(conn net.Conn) {
    defer conn.Close()
    tlscon, ok := conn.(*tls.Conn)
    if ok {
    log.Print("server: conn: type assert to TLS succeedded")
    err := tlscon.Handshake()
    if err != nil {
    log.Fatalf("server: handshake failed: %s", err)
    } else {
    log.Print("server: conn: Handshake completed")
    }
    state := tlscon.ConnectionState()
    for _, v := range state.PeerCertificates {
    log.Print(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    }
    buf := make([]byte, 512)
    for {
    log.Print("server: conn: waiting")
    @@ -60,8 +61,6 @@ func handleClient(conn net.Conn) {
    log.Printf("server: conn: echo %q\n", string(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
  13. @spikebike spikebike revised this gist Mar 29, 2012. 1 changed file with 0 additions and 3 deletions.
    3 changes: 0 additions & 3 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -60,9 +60,6 @@ func handleClient(conn net.Conn) {
    log.Printf("server: conn: echo %q\n", string(buf[:n]))
    n, err = conn.Write(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 {
  14. @spikebike spikebike revised this gist Mar 29, 2012. 1 changed file with 7 additions and 1 deletion.
    8 changes: 7 additions & 1 deletion server.go
    Original file line number Diff line number Diff line change
    @@ -3,9 +3,9 @@ package main
    import (
    "crypto/rand"
    "crypto/tls"
    "crypto/x509"
    "log"
    "net"
    "crypto/x509"
    )

    func main() {
    @@ -30,6 +30,10 @@ func main() {
    defer conn.Close()
    log.Printf("server: accepted from %s", conn.RemoteAddr())
    tlscon, ok := conn.(*tls.Conn)
    err = tlscon.Handshake()
    if err != nil {
    break
    }
    if ok {
    log.Print("ok=true")
    state := tlscon.ConnectionState()
    @@ -56,6 +60,8 @@ func handleClient(conn net.Conn) {
    log.Printf("server: conn: echo %q\n", string(buf[:n]))
    n, err = conn.Write(buf[:n])

    n, err = conn.Write(buf[:n])

    n, err = conn.Write(buf[:n])
    log.Printf("server: conn: wrote %d bytes", n)

  15. @invalid-email-address Anonymous revised this gist Mar 29, 2012. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions makecert.sh
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    #!/bin/bash
    # call this script with an email address (valid or not).
    # like:
    # ./makecert.sh [email protected]
    mkdir certs
    rm certs/*
    echo "make server cert"
  16. @invalid-email-address Anonymous revised this gist Mar 29, 2012. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions makecert.sh
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    #!/bin/bash
    # call this script with an email address (valid or not).
    mkdir certs
    rm certs/*
    echo "make server cert"
  17. @invalid-email-address Anonymous revised this gist Mar 29, 2012. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -32,11 +32,11 @@ func main() {
    tlscon, ok := conn.(*tls.Conn)
    if ok {
    log.Print("ok=true")
    state := tlscon.ConnectionState()
    for _, v := range state.PeerCertificates {
    log.Print(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    }
    state := tlscon.ConnectionState()
    for _, v := range state.PeerCertificates {
    log.Print(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    go handleClient(conn)
    }
    }
  18. @invalid-email-address Anonymous revised this gist Mar 29, 2012. 2 changed files with 44 additions and 49 deletions.
    69 changes: 33 additions & 36 deletions client.go
    Original file line number Diff line number Diff line change
    @@ -1,46 +1,43 @@
    package main

    import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "io"
    "log"
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "io"
    "log"
    )

    func main() {
    cert, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key")
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
    conn, err := tls.Dial("tcp", "127.0.0.1:8000", &config)
    if err != nil {
    log.Fatalf("client: dial: %s", err)
    }
    defer conn.Close()
    log.Println("client: connected to: ", conn.RemoteAddr())
    cert, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key")
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
    conn, err := tls.Dial("tcp", "127.0.0.1:8000", &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.EmailAddresses)
    fmt.Println(v.DNSNames)
    fmt.Println("subject")
    fmt.Println(v.Subject)
    }
    log.Println("client: handshake: ", state.HandshakeComplete)
    log.Println("client: mutual: ", state.NegotiatedProtocolIsMutual)
    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)
    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")
    reply := make([]byte, 256)
    n, err = conn.Read(reply)
    log.Printf("client: read %q (%d bytes)", string(reply[:n]), n)
    log.Print("client: exiting")
    }
    24 changes: 11 additions & 13 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -5,47 +5,44 @@ import (
    "crypto/tls"
    "log"
    "net"
    "crypto/x509"
    )

    func main() {

    cert, err := tls.LoadX509KeyPair("certs/server.pem", "certs/server.key")
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{Certificates: []tls.Certificate{cert}}

    config.Rand = rand.Reader

    service := "0.0.0.0:8000"

    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())
    tlscon, ok := conn.(tls.Conn)
    if ok == true {
    state := tlscon.ConnectionState()
    tlscon, ok := conn.(*tls.Conn)
    if ok {
    log.Print("ok=true")
    }

    state := tlscon.ConnectionState()
    for _, v := range state.PeerCertificates {
    log.Print(x509.MarshalPKIXPublicKey(v.PublicKey))
    }
    go handleClient(conn)
    }
    }

    func handleClient(conn net.Conn) {
    defer conn.Close()

    buf := make([]byte, 512)
    for {
    log.Print("server: conn: waiting")
    @@ -55,9 +52,10 @@ func handleClient(conn net.Conn) {
    log.Printf("server: conn: read: %s", err)
    }
    break

    }
    }
    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)

  19. @invalid-email-address Anonymous created this gist Mar 29, 2012.
    46 changes: 46 additions & 0 deletions client.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    package main

    import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "io"
    "log"
    )

    func main() {
    cert, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key")
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
    conn, err := tls.Dial("tcp", "127.0.0.1:8000", &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.EmailAddresses)
    fmt.Println(v.DNSNames)
    fmt.Println("subject")
    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")
    }
    7 changes: 7 additions & 0 deletions makecert.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    #!/bin/bash
    mkdir certs
    rm certs/*
    echo "make server cert"
    openssl req -new -nodes -x509 -out certs/server.pem -keyout certs/server.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=www.random.com/emailAddress=$1"
    echo "make client cert"
    openssl req -new -nodes -x509 -out certs/client.pem -keyout certs/client.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=www.random.com/emailAddress=$1"
    70 changes: 70 additions & 0 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,70 @@
    package main

    import (
    "crypto/rand"
    "crypto/tls"
    "log"
    "net"
    )

    func main() {

    cert, err := tls.LoadX509KeyPair("certs/server.pem", "certs/server.key")
    if err != nil {
    log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{Certificates: []tls.Certificate{cert}}

    config.Rand = rand.Reader

    service := "0.0.0.0:8000"

    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())
    tlscon, ok := conn.(tls.Conn)
    if ok == true {
    state := tlscon.ConnectionState()
    }

    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

    }
    log.Printf("server: conn: echo %q\n", string(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")
    }