This is a creation in Article, where the information may have evolved or changed.
The Transport Layer Security Protocol (TRANSPORT layer safety, abbreviation: TLS), and its predecessor, Secure Sockets Layer (secure Sockets layer, abbreviation: SSL) is a security protocol designed to provide security and data integrity assurance for Internet communications.
SSL contains the record layer and the transport layer, and the recording layer protocol determines the encapsulation format of the transport layer data. The Transport Layer Security protocol uses the authentication of the certificate, then uses the asymmetric encryption algorithm to authenticate the communication party, and then switches the symmetric key as the Session key. This meeting key is used to encrypt the data exchanged between the two sides of the communication, to ensure the confidentiality and reliability of communication between the two applications, so that communication between client and server application is not bugged by attackers.
This article does not provide a in-depth tutorial for TLS, but rather provides a simple example of two go application TLS to demonstrate the fast development of secure network transmission using the Go language.
TLS history
In the early 1994, Netscape company designed the 1.0 version of the SSL protocol (Secure Sockets Layer), but it was not released.
In November 1994, Netscape released SSL version 2.0 and soon found a serious loophole.
In November 1996, the SSL 3.0 version was introduced, and was widely used.
January 1999, the Internet Standardization organization ISOC replaced Netscape Company, released the SSL upgrade version of TLS version 1.0.
In April 2006 and August 2008, TLS was upgraded two times, respectively, for TLS version 1.1 and TLS 1.2. The latest change is the 2011 revision of the TLS 1.2.
TLS 1.3 is now being developed.
Certificate generation
First we create the private key and the certificate.
Server-side certificate generation
Server-side certificates are used to ensure that the servers are not counterfeit.
1. Generate server-side private key
2. Generate server-side certificates
1 |
OpenSSL req-new -x509-key server. Key 3650 |
Certificate Generation for clients
In addition to "server-side Certificates", "Client certificates" are also involved in some scenarios. The so-called "client certificate" is used to prove the identity of the client visitor.
For example, in some financial companies ' intranet, you must deploy a "client certificate" on your computer to open the pages of important servers.
I will demonstrate the use of the "client certificate" in the following example.
3. Generate the client's private key
4. Generate a certificate for the client
1 |
OpenSSL req-new -x509-key client. Key 3650 |
or use the following script:
12345678910 |
#!/bin/bash # call this script with an email Address (valid or not). # like: #./makecert.sh demo@random.com mkdir certsrm certs/*echo "Make server cert" OpenSSL req-new-nodes-x509-out certs/server.pem-keyout certs/s Erver.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/c Lient.key-days 3650 -subj "/c=de/st=nrw/l=earth/o=random Company/ Ou=it/cn=www.random.com/emailaddress=$1 " |
Golang Example
The Go Package TLS section implements the TLS 1.2 functionality to meet our everyday applications. Package crypto/x509 provides the relevant operations for certificate management.
Use of server certificates
This section of the Code provides examples of server use certificates.
The following code is an example of a server:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253 |
PackageMainImport("Bufio""Crypto/tls""Log""NET")funcMain () {cert, err: = TLS. Loadx509keypair ("Server.pem","Server.key")ifErr! =Nil{log. PRINTLN (ERR)return}config: = &tls. Config{certificates: []tls. CERTIFICATE{CERT}}LN, err: = TLS. Listen ("TCP",": 443", config)ifErr! =Nil{log. PRINTLN (ERR)return}deferln. Close () for{conn, err: = ln. Accept ()ifErr! =Nil{log. PRINTLN (ERR)Continue}GoHANDLECONN (conn)}}funcHANDLECONN (Conn net. Conn) {deferConn. Close () r: = Bufio. Newreader (conn) for{msg, err: = R.readstring (' \ n ')ifErr! =Nil{log. PRINTLN (ERR)return}println(msg) n, err: = conn. Write ([]byte("world\n"))ifErr! =Nil{log. PRINTLN (n, err)return}}} |
First get the certificate from the server private key and Pem file we created above cert
, and generate a TLS. Config object. This object has more than one field to set, in this case we use its default value.
Then tls.Listen
you start listening to the client connection and receive a net after accept. Conn, subsequent processing is the same as for normal TCP programs.
Then, let's look at how the client is implemented:
12345678910111213141516171819202122232425262728293031323334 |
PackageMainImport("Crypto/tls""Log")funcMain () {conf: = &tls. Config{insecureskipverify:true,}conn, err: = TLS. Dial ("TCP","127.0.0.1:443", conf)ifErr! =Nil{log. PRINTLN (ERR)return}deferConn. Close () n, err: = conn. Write ([]byte("hello\n"))ifErr! =Nil{log. PRINTLN (n, err)return}buf: = Make([]byte, -) N, err = conn. Read (BUF)ifErr! =Nil{log. PRINTLN (n, err)return}println(string(Buf[:n])} |
InsecureSkipVerify
Used to control whether the client is a certificate and server hostname. If set to True, the certificate is not validated and the host name and server hostname are consistent.
Because the self-signed certificate is used in our example, it is set to true for testing purposes only.
As can be seen, the whole program is written and ordinary TCP programs are poorly written, but initially need to do some TLS configuration.
You can go run server.go
and go run client.go
test this example.
Use of client certificates
In some cases, two-way authentication is required, and the server needs to verify the authenticity of the client. In this case, we need a little extra configuration from the server and the client.
Server-side:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 66676869 |
PackageMainImport("Bufio""Crypto/tls""crypto/x509""Io/ioutil""Log""NET")funcMain () {cert, err: = TLS. Loadx509keypair ("Server.pem","Server.key")ifErr! =Nil{log. PRINTLN (ERR)return}certbytes, err: = Ioutil. ReadFile ("Client.pem")ifErr! =Nil{Panic("Unable to read CERT.PEM")}clientcertpool: = X509. Newcertpool () OK: = Clientcertpool.appendcertsfrompem (certbytes)if!ok {Panic("Failed to parse root certificate")}config: = &tls. Config{certificates: []tls. Certificate{cert},clientauth:tls. REQUIREANDVERIFYCLIENTCERT,CLIENTCAS:CLIENTCERTPOOL,}LN, err: = TLS. Listen ("TCP",": 443", config)ifErr! =Nil{log. PRINTLN (ERR)return}deferln. Close () for{conn, err: = ln. Accept ()ifErr! =Nil{log. PRINTLN (ERR)Continue}GoHANDLECONN (conn)}}funcHANDLECONN (Conn net. Conn) {deferConn. Close () r: = Bufio. Newreader (conn) for{msg, err: = R.readstring (' \ n ')ifErr! =Nil{log. PRINTLN (ERR)return}println(msg) n, err: = conn. Write ([]byte("world\n"))ifErr! =Nil{log. PRINTLN (n, err)return}}} |
Because the client needs to be validated, we need to configure the following two additional fields:
12 |
ClientAuth: TLS. Requireandverifyclientcert,clientcas: Clientcertpool, |
The client then configures this as well clientCertPool
:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
PackageMainImport("Crypto/tls""crypto/x509""Io/ioutil""Log")funcMain () {cert, err: = TLS. Loadx509keypair ("Client.pem","Client.key")ifErr! =Nil{log. PRINTLN (ERR)return}certbytes, err: = Ioutil. ReadFile ("Client.pem")ifErr! =Nil{Panic("Unable to read CERT.PEM")}clientcertpool: = X509. Newcertpool () OK: = Clientcertpool.appendcertsfrompem (certbytes)if!ok {Panic("Failed to parse root certificate")}conf: = &tls. Config{rootcas:clientcertpool,certificates: []tls. Certificate{cert},insecureskipverify:true,}conn, err: = TLS. Dial ("TCP","127.0.0.1:443", conf)ifErr! =Nil{log. PRINTLN (ERR)return}deferConn. Close () n, err: = conn. Write ([]byte("hello\n"))ifErr! =Nil{log. PRINTLN (n, err)return}buf: = Make([]byte, -) N, err = conn. Read (BUF)ifErr! =Nil{log. PRINTLN (n, err)return}println(string(Buf[:n])} |
Run both code go run server2.go
and go run client2.go
you can see that both can communicate properly, if using the previous client go run client.go
, cannot communicate normally, because the front client does not provide a client certificate.
Reference documentation and code
- Https://zh.wikipedia.org/wiki/%E5%82%B3%E8%BC%B8%E5%B1%A4%E5%AE%89%E5%85%A8%E5%8D%94%E8%AD%B0
- http://drops.wooyun.org/tips/6002
- http://www.levigross.com/2015/11/21/mutual-tls-authentication-in-go/
- Https://github.com/nareix/blog/blob/master/posts/golang-tls-guide.md
- Http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
- https://gist.github.com/spikebike/2232102
- Https://github.com/nareix/tls-example
- http://seanlook.com/2015/01/07/tls-ssl/
- https://golang.org/pkg/crypto/tls/