Go实战--golang中使用HTTPS以及TSL(.crt、.key、.pem区别以及cry
生命不止,继续go go go!!! HTTP与HTTPS在WWDC 2016上,苹果在发布iOS 9的同时也向开发者传递了一个消息,那就是到2017年1月1日时App Store中所有应用都必须启用 App Transport Security应用程序安全传输协议,从而提升应用和系统安全性。 HTTPS是Hyper Text Transfer Protocol Secure的缩写,相比http,多了一个secure,这一个secure是怎么来的呢?这是由TLS(SSL)提供的。 https和http都属于应用层,基于TCP(以及UDP)协议。但是不同的是: 通俗一句话:相比http,https对于大部分人来说,意味着比较安全。 TLS安全传输层协议(TLS)用于在两个通信应用程序之间提供保密性和数据完整性。 TLS与SSL的差异 SSLv2 and SSLv3 are completely different (and both are now considered insecure). SSLv3 and TLSv1.0 are very similar,but have a few differences. You could consider TLSv1.0 as SSLv3.1
openssl 插曲: crt、key以及pem的区别以及生成crt — Alternate synonymous most common among *nix systems .pem (pubkey). csr — Certficate Signing Requests (synonymous most common among *nix systems). cer — Microsoft alternate form of .crt,you can use MS to convert .crt to .cer (DER encoded .cer,or base64[PEM] encoded cer). pem = The PEM extension is used for different types of X.509v3 files which contain ASCII (Base64) armored data prefixed with a ?—– BEGIN …? line. These files may also bear the cer or the crt extension. der — The DER extension is used for binary DER encoded certificates. 证书(Certificate) PEM - Privacy Enhanced Mail,打开看文本格式,以”—–BEGIN…”开头,“—–END…”结尾,内容是BASE64编码. DER - Distinguished Encoding Rules,打开看是二进制格式,不可读. x509 x509证书一般会用到三类文,key,csr,crt。 生成.key openssl genrsa -out server.key 2048
ECDSA算法: openssl ecparam -genkey -name secp384r1 -out server.key 生成.crt openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
需要输入一些信息: openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,If you enter '.',the field will be left blank.
-----
Country Name (2 letter code) [AU]:cn
State or Province Name (full name) [Some-State]:Beijing
Locality Name (eg,city) []:Beijing
Organization Name (eg,company) [Internet Widgits Pty Ltd]:wangshubo
Organizational Unit Name (eg,section) []:wangshubo
Common Name (e.g. server FQDN or YOUR name) []:wangshubo
Email Address []:wangshubo1989@126.com
生成pem和key 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=wangshubo1989@126.com"
crypto/tls包介绍golang中为我们提供了tls包: func LoadX509KeyPair func LoadX509KeyPair(certFile,keyFile string) (Certificate,error)
LoadX509KeyPair reads and parses a public/private key pair from a pair of files. The files must contain PEM encoded data. The certificate file may contain intermediate certificates following the leaf certificate to form a certificate chain. On successful return,Certificate.Leaf will be nil because the parsed form of the certificate is not retained. type Config type Config struct {
Rand io.Reader
Time func() time.Time
Certificates []Certificate
NameToCertificate map[string]*Certificate
GetCertificate func(*ClientHelloInfo) (*Certificate,error)
GetClientCertificate func(*CertificateRequestInfo) (*Certificate,error)
GetConfigForClient func(*ClientHelloInfo) (*Config,error)
VerifyPeerCertificate func(rawCerts [][]byte,verifiedChains [][]*x509.Certificate) error
RootCAs *x509.CertPool
NextProtos []string
ServerName string
ClientAuth ClientAuthType
ClientCAs *x509.CertPool
InsecureSkipVerify bool
CipherSuites []uint16
PreferServerCipherSuites bool
SessionTicketsDisabled bool
SessionTicketKey [32]byte
ClientSessionCache ClientSessionCache
MinVersion uint16
MaxVersion uint16
CurvePreferences []CurveID
DynamicRecordSizingDisabled bool
Renegotiation RenegotiationSupport
KeyLogWriter io.Writer
}
这里主要关注一下Certificates,是我们要用到的。 func Listen func Listen(network,laddr string,config *Config) (net.Listener,error)
Listen creates a TLS listener accepting connections on the given network address using net.Listen. The configuration config must be non-nil and must include at least one certificate or else set GetCertificate. func Dial func Dial(network,addr string,config *Config) (*Conn,error)
Dial connects to the given network address using net.Dial and then initiates a TLS handshake,returning the resulting TLS connection. Dial interprets a nil configuration as equivalent to the zero configuration; see the documentation of Config for the defaults. 应用通过golang生成pem // Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Generate a self-signed X.509 certificate for a TLS server. Outputs to
// 'cert.pem' and 'key.pem' and will overwrite existing files.
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"log"
"math/big"
"os"
"time"
)
var (
emailAddress = flag.String("email-address","","The email address of the user you wish to create the certificate for")
validFrom = flag.String("start-date","Creation date formatted as Jan 1 15:04:05 2011")
validFor = flag.Duration("duration", 365*24*time.Hour,"Duration that certificate is valid for")
isCA = flag.Bool("ca",false,"whether this cert should be its own Certificate Authority")
rsaBits = flag.Int("rsa-bits", 2048,"Size of RSA key to generate. Ignored if --ecdsa-curve is set")
ecdsaCurve = flag.String("ecdsa-curve","ECDSA curve to use to generate a key. Valid values are P224,P256,P384,P521")
)
func publicKey(priv interface{}) interface{} {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &k.PublicKey
case *ecdsa.PrivateKey:
return &k.PublicKey
default:
return nil
}
}
func pemBlockForKey(priv interface{}) *pem.Block {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &pem.Block{Type: "RSA PRIVATE KEY",Bytes: x509.MarshalPKCS1PrivateKey(k)}
case *ecdsa.PrivateKey:
b,err := x509.MarshalECPrivateKey(k)
if err != nil {
fmt.Fprintf(os.Stderr,"Unable to marshal ECDSA private key: %v",err)
os.Exit(2)
}
return &pem.Block{Type: "EC PRIVATE KEY",Bytes: b}
default:
return nil
}
}
func main() {
flag.Parse()
if len(*emailAddress) == 0 {
log.Fatalf("Missing required --email-address parameter")
}
var priv interface{}
var err error
switch *ecdsaCurve {
case "":
priv,err = rsa.GenerateKey(rand.Reader,*rsaBits)
case "P224":
priv,err = ecdsa.GenerateKey(elliptic.P224(),rand.Reader)
case "P256":
priv,err = ecdsa.GenerateKey(elliptic.P256(),rand.Reader)
case "P384":
priv,err = ecdsa.GenerateKey(elliptic.P384(),rand.Reader)
case "P521":
priv,err = ecdsa.GenerateKey(elliptic.P521(),rand.Reader)
default:
fmt.Fprintf(os.Stderr,"Unrecognized elliptic curve: %q",*ecdsaCurve)
os.Exit(1)
}
if err != nil {
log.Fatalf("failed to generate private key: %s",err)
}
var notBefore time.Time
if len(*validFrom) == 0 {
notBefore = time.Now()
} else {
notBefore,err = time.Parse("Jan 2 15:04:05 2006",*validFrom)
if err != nil {
fmt.Fprintf(os.Stderr,"Failed to parse creation date: %sn",err)
os.Exit(1)
}
}
notAfter := notBefore.Add(*validFor)
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber,err := rand.Int(rand.Reader,serialNumberLimit)
if err != nil {
log.Fatalf("failed to generate serial number: %s",err)
}
template := x509.Certificate{
SerialNumber: serialNumber,Subject: pkix.Name{
Organization: []string{"Acme Co"},},NotBefore: notBefore,NotAfter: notAfter,KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth,x509.ExtKeyUsageClientAuth},BasicConstraintsValid: true,}
template.DNSNames = append(template.DNSNames,"localhost")
template.EmailAddresses = append(template.EmailAddresses,*emailAddress)
if *isCA {
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign
}
derBytes,err := x509.CreateCertificate(rand.Reader,&template,publicKey(priv),priv)
if err != nil {
log.Fatalf("Failed to create certificate: %s",err)
}
certOut,err := os.Create("cert.pem")
if err != nil {
log.Fatalf("failed to open cert.pem for writing: %s",err)
}
pem.Encode(certOut,&pem.Block{Type: "CERTIFICATE",Bytes: derBytes})
certOut.Close()
log.Print("written cert.pemn")
keyOut,err := os.OpenFile("key.pem",os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Print("failed to open key.pem for writing:",err)
return
}
pem.Encode(keyOut,pemBlockForKey(priv))
keyOut.Close()
log.Print("written key.pemn")
}
golang中使用HTTPS package main
import (
"log"
"net/http"
)
func HelloServer(w http.ResponseWriter,req *http.Request) {
w.Header().Set("Content-Type","text/plain")
w.Write([]byte("This is an example using https in golang.n"))
}
func main() {
http.HandleFunc("/hello",HelloServer)
err := http.ListenAndServeTLS(":443","server.crt","server.key",nil)
if err != nil {
log.Fatal("ListenAndServe: ",err)
}
}
浏览器访问: golang中使用tls package main
import (
"bufio"
"crypto/tls"
"log"
"net"
)
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("juden"))
if err != nil {
log.Println(n,err)
return
}
}
}
client.go package main
import (
"crypto/tls"
"log"
)
func main() {
log.SetFlags(log.Lshortfile)
conf := &tls.Config{
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("hin"))
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]))
}
这里编写client代码时候需要注意:InsecureSkipVerify: true (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |