signer.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package goproxy
  2. import (
  3. "crypto"
  4. "crypto/ecdsa"
  5. "crypto/elliptic"
  6. "crypto/rsa"
  7. "crypto/sha1"
  8. "crypto/tls"
  9. "crypto/x509"
  10. "crypto/x509/pkix"
  11. "fmt"
  12. "math/big"
  13. "math/rand"
  14. "net"
  15. "runtime"
  16. "sort"
  17. "time"
  18. )
  19. func hashSorted(lst []string) []byte {
  20. c := make([]string, len(lst))
  21. copy(c, lst)
  22. sort.Strings(c)
  23. h := sha1.New()
  24. for _, s := range c {
  25. h.Write([]byte(s + ","))
  26. }
  27. return h.Sum(nil)
  28. }
  29. func hashSortedBigInt(lst []string) *big.Int {
  30. rv := new(big.Int)
  31. rv.SetBytes(hashSorted(lst))
  32. return rv
  33. }
  34. var goproxySignerVersion = ":goroxy1"
  35. func signHost(ca tls.Certificate, hosts []string) (cert *tls.Certificate, err error) {
  36. var x509ca *x509.Certificate
  37. // Use the provided ca and not the global GoproxyCa for certificate generation.
  38. if x509ca, err = x509.ParseCertificate(ca.Certificate[0]); err != nil {
  39. return
  40. }
  41. start := time.Unix(0, 0)
  42. end, err := time.Parse("2006-01-02", "2049-12-31")
  43. if err != nil {
  44. panic(err)
  45. }
  46. serial := big.NewInt(rand.Int63())
  47. template := x509.Certificate{
  48. // TODO(elazar): instead of this ugly hack, just encode the certificate and hash the binary form.
  49. SerialNumber: serial,
  50. Issuer: x509ca.Subject,
  51. Subject: pkix.Name{
  52. Organization: []string{"GoProxy untrusted MITM proxy Inc"},
  53. },
  54. NotBefore: start,
  55. NotAfter: end,
  56. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  57. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  58. BasicConstraintsValid: true,
  59. }
  60. for _, h := range hosts {
  61. if ip := net.ParseIP(h); ip != nil {
  62. template.IPAddresses = append(template.IPAddresses, ip)
  63. } else {
  64. template.DNSNames = append(template.DNSNames, h)
  65. template.Subject.CommonName = h
  66. }
  67. }
  68. hash := hashSorted(append(hosts, goproxySignerVersion, ":"+runtime.Version()))
  69. var csprng CounterEncryptorRand
  70. if csprng, err = NewCounterEncryptorRandFromKey(ca.PrivateKey, hash); err != nil {
  71. return
  72. }
  73. var certpriv crypto.Signer
  74. switch ca.PrivateKey.(type) {
  75. case *rsa.PrivateKey:
  76. if certpriv, err = rsa.GenerateKey(&csprng, 2048); err != nil {
  77. return
  78. }
  79. case *ecdsa.PrivateKey:
  80. if certpriv, err = ecdsa.GenerateKey(elliptic.P256(), &csprng); err != nil {
  81. return
  82. }
  83. default:
  84. err = fmt.Errorf("unsupported key type %T", ca.PrivateKey)
  85. }
  86. var derBytes []byte
  87. if derBytes, err = x509.CreateCertificate(&csprng, &template, x509ca, certpriv.Public(), ca.PrivateKey); err != nil {
  88. return
  89. }
  90. return &tls.Certificate{
  91. Certificate: [][]byte{derBytes, ca.Certificate[0]},
  92. PrivateKey: certpriv,
  93. }, nil
  94. }
  95. func init() {
  96. // Avoid deterministic random numbers
  97. rand.Seed(time.Now().UnixNano())
  98. }