Get RSA Public Private Keys
There are two ways to get RSA public and private keys. One is to generate self-signed key pairs, the other is get keys from a CA.
Generate Self-signed Keys
private key
$ openssl genrsa -out server.key 2048
Generation of self-signed(x509) public key (PEM-encodings .pem|.crt) based on the private (.key)
$ openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
Get a Free Certificate from CA
Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. It is a service provided by the Internet Security Research Group (ISRG).
TLS(Transport Layer Security)
Server
TLS server means to encrypt TCP connection with RSA algorithm.
package main
import (
"log"
"crypto/tls"
"net"
"bufio"
)
func main() {
log.SetFlags(log.Lshortfile)
cer, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
log.Println(err)
return
}
config := &tls.Config{Certificates: []tls.Certificate{cer}}
ln, err := tls.Listen("tcp", ":443", config)
if err != nil {
log.Println(err)
return
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
r := bufio.NewReader(conn)
for {
msg, err := r.ReadString('\n')
if err != nil {
log.Println(err)
return
}
println(msg)
n, err := conn.Write([]byte("world\n"))
if err != nil {
log.Println(n, err)
return
}
}
}
Client
package main
import (
"log"
"crypto/tls"
)
func main() {
log.SetFlags(log.Lshortfile)
conf := &tls.Config{
// if self-signed certificate is used,
// this should set to ture.
InsecureSkipVerify: true,
}
conn, err := tls.Dial("tcp", "127.0.0.1:443", conf)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
n, err := conn.Write([]byte("hello\n"))
if err != nil {
log.Println(n, err)
return
}
buf := make([]byte, 100)
n, err = conn.Read(buf)
if err != nil {
log.Println(n, err)
return
}
println(string(buf[:n]))
}
HTTPS Server
HTTPS Server means HTTP over TLS.
Server
package main
import (
// "fmt"
// "io"
"net/http"
"log"
)
func HelloServer(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte("This is an example server.\n"))
// fmt.Fprintf(w, "This is an example server.\n")
// io.WriteString(w, "This is an example server.\n")
}
func main() {
http.HandleFunc("/hello", HelloServer)
err := http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Client Test
$ curl -sL https://localhost:443
Other Way to Deploy TLS/HTTPS
TLS can also be implemented through reverse proxy server, such as Nginx. That means we can deploy certificate at Nginx side, and only use HTTP in backend server(Go/Ruby).