util.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Package util provides auxiliary utilities used in examples
  2. package util
  3. import (
  4. "bufio"
  5. "crypto"
  6. "crypto/ecdsa"
  7. "crypto/rsa"
  8. "crypto/tls"
  9. "crypto/x509"
  10. "encoding/pem"
  11. "errors"
  12. "fmt"
  13. "io"
  14. "io/ioutil"
  15. "net"
  16. "os"
  17. "path/filepath"
  18. "strings"
  19. )
  20. const bufSize = 8192
  21. var (
  22. errBlockIsNotPrivateKey = errors.New("block is not a private key, unable to load key")
  23. errUnknownKeyTime = errors.New("unknown key time in PKCS#8 wrapping, unable to load key")
  24. errNoPrivateKeyFound = errors.New("no private key found, unable to load key")
  25. errBlockIsNotCertificate = errors.New("block is not a certificate, unable to load certificates")
  26. errNoCertificateFound = errors.New("no certificate found, unable to load certificates")
  27. )
  28. // Chat simulates a simple text chat session over the connection
  29. func Chat(conn io.ReadWriter) {
  30. go func() {
  31. b := make([]byte, bufSize)
  32. for {
  33. n, err := conn.Read(b)
  34. Check(err)
  35. fmt.Printf("Got message: %s\n", string(b[:n]))
  36. }
  37. }()
  38. reader := bufio.NewReader(os.Stdin)
  39. for {
  40. text, err := reader.ReadString('\n')
  41. Check(err)
  42. if strings.TrimSpace(text) == "exit" {
  43. return
  44. }
  45. _, err = conn.Write([]byte(text))
  46. Check(err)
  47. }
  48. }
  49. // Check is a helper to throw errors in the examples
  50. func Check(err error) {
  51. switch e := err.(type) {
  52. case nil:
  53. case (net.Error):
  54. if e.Temporary() {
  55. fmt.Printf("Warning: %v\n", err)
  56. return
  57. }
  58. fmt.Printf("net.Error: %v\n", err)
  59. panic(err)
  60. default:
  61. fmt.Printf("error: %v\n", err)
  62. panic(err)
  63. }
  64. }
  65. // LoadKeyAndCertificate reads certificates or key from file
  66. func LoadKeyAndCertificate(keyPath string, certificatePath string) (*tls.Certificate, error) {
  67. privateKey, err := LoadKey(keyPath)
  68. if err != nil {
  69. return nil, err
  70. }
  71. certificate, err := LoadCertificate(certificatePath)
  72. if err != nil {
  73. return nil, err
  74. }
  75. certificate.PrivateKey = privateKey
  76. return certificate, nil
  77. }
  78. // LoadKey Load/read key from file
  79. func LoadKey(path string) (crypto.PrivateKey, error) {
  80. rawData, err := ioutil.ReadFile(filepath.Clean(path))
  81. if err != nil {
  82. return nil, err
  83. }
  84. block, _ := pem.Decode(rawData)
  85. if block == nil || !strings.HasSuffix(block.Type, "PRIVATE KEY") {
  86. return nil, errBlockIsNotPrivateKey
  87. }
  88. if key, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
  89. return key, nil
  90. }
  91. if key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {
  92. switch key := key.(type) {
  93. case *rsa.PrivateKey, *ecdsa.PrivateKey:
  94. return key, nil
  95. default:
  96. return nil, errUnknownKeyTime
  97. }
  98. }
  99. if key, err := x509.ParseECPrivateKey(block.Bytes); err == nil {
  100. return key, nil
  101. }
  102. return nil, errNoPrivateKeyFound
  103. }
  104. // LoadCertificate Load/read certificate(s) from file
  105. func LoadCertificate(path string) (*tls.Certificate, error) {
  106. rawData, err := ioutil.ReadFile(filepath.Clean(path))
  107. if err != nil {
  108. return nil, err
  109. }
  110. var certificate tls.Certificate
  111. for {
  112. block, rest := pem.Decode(rawData)
  113. if block == nil {
  114. break
  115. }
  116. if block.Type != "CERTIFICATE" {
  117. return nil, errBlockIsNotCertificate
  118. }
  119. certificate.Certificate = append(certificate.Certificate, block.Bytes)
  120. rawData = rest
  121. }
  122. if len(certificate.Certificate) == 0 {
  123. return nil, errNoCertificateFound
  124. }
  125. return &certificate, nil
  126. }