Skip to content

Instantly share code, notes, and snippets.

@starius
Created July 1, 2021 11:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save starius/ef3a7953577ff91221baa1b99c2dd100 to your computer and use it in GitHub Desktop.
Save starius/ef3a7953577ff91221baa1b99c2dd100 to your computer and use it in GitHub Desktop.
TLS server and client built on known ed25519 public key
package main
// See https://golang.org/src/crypto/tls/generate_cert.go
// See https://gist.github.com/denji/12b3a568f092ab951456
import (
"bytes"
"crypto/ed25519"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net"
"net/http"
"time"
)
func main() {
pk, sk, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
panic(err)
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Acme Co"},
},
NotBefore: time.Now().Add(-time.Hour * 24 * 360 * 10),
NotAfter: time.Now().Add(time.Hour * 24 * 360 * 10),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
}
template.IPAddresses = append(template.IPAddresses, net.ParseIP("127.0.0.1"))
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, pk, sk)
if err != nil {
panic(err)
}
var certBuffer, keyBuffer bytes.Buffer
if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
panic(err)
}
privBytes, err := x509.MarshalPKCS8PrivateKey(sk)
if err != nil {
panic(err)
}
if err := pem.Encode(&keyBuffer, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
panic(err)
}
cert, err := tls.X509KeyPair(certBuffer.Bytes(), keyBuffer.Bytes())
if err != nil {
panic(err)
}
server := &http.Server{
TLSConfig: &tls.Config{
Certificates: []tls.Certificate{cert},
},
Addr: "127.0.0.1:4433",
Handler: http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}),
}
go server.ListenAndServeTLS("", "")
time.Sleep(time.Second)
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, // Not to require root CA signature.
VerifyConnection: func(state tls.ConnectionState) error {
if len(state.PeerCertificates) != 1 {
return fmt.Errorf("want 1 cert")
}
if !pk.Equal(state.PeerCertificates[0].PublicKey) {
return fmt.Errorf("wrong cert")
}
return nil
},
},
},
}
res, err := client.Get("https://127.0.0.1:4433/")
if err != nil {
panic(err)
}
fmt.Println(res.Status)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment