Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

certs.go 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // Copyright (c) 2016 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package mkcerts
  4. import (
  5. "crypto/ecdsa"
  6. "crypto/elliptic"
  7. "crypto/rand"
  8. "crypto/x509"
  9. "crypto/x509/pkix"
  10. "encoding/pem"
  11. "fmt"
  12. "math/big"
  13. "net"
  14. "os"
  15. "time"
  16. )
  17. // CreateCertBytes creates a testing ECDSA certificate, returning the cert and key bytes.
  18. func CreateCertBytes(orgName string, host string) (certBytes []byte, keyBytes []byte, err error) {
  19. validFrom := time.Now()
  20. validFor := 365 * 24 * time.Hour
  21. notAfter := validFrom.Add(validFor)
  22. priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
  23. serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
  24. serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
  25. if err != nil {
  26. return nil, nil, fmt.Errorf("failed to generate serial number: %s", err)
  27. }
  28. template := x509.Certificate{
  29. SerialNumber: serialNumber,
  30. Subject: pkix.Name{
  31. Organization: []string{orgName},
  32. },
  33. NotBefore: validFrom,
  34. NotAfter: notAfter,
  35. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  36. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  37. BasicConstraintsValid: true,
  38. }
  39. // TODO: allow explicitly listing allowed addresses/names
  40. template.IPAddresses = append(template.IPAddresses, net.ParseIP("127.0.0.1"))
  41. template.IPAddresses = append(template.IPAddresses, net.ParseIP("::1"))
  42. if host != "" {
  43. template.DNSNames = append(template.DNSNames, host)
  44. }
  45. template.DNSNames = append(template.DNSNames, "localhost")
  46. derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
  47. if err != nil {
  48. return nil, nil, fmt.Errorf("Failed to create certificate: %s", err.Error())
  49. }
  50. certBytes = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
  51. b, err := x509.MarshalECPrivateKey(priv)
  52. if err != nil {
  53. return nil, nil, fmt.Errorf("Unable to marshal ECDSA private key: %v", err.Error())
  54. }
  55. pemBlock := pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
  56. keyBytes = pem.EncodeToMemory(&pemBlock)
  57. return certBytes, keyBytes, nil
  58. }
  59. // CreateCert creates a testing ECDSA certificate, outputting the cert and key at the given filenames.
  60. func CreateCert(orgName string, host string, certFilename string, keyFilename string) error {
  61. certBytes, keyBytes, err := CreateCertBytes(orgName, host)
  62. if err != nil {
  63. return err
  64. }
  65. certOut, err := os.Create(certFilename)
  66. if err != nil {
  67. return fmt.Errorf("failed to open %s for writing: %s", certFilename, err.Error())
  68. }
  69. defer certOut.Close()
  70. _, err = certOut.Write(certBytes)
  71. if err != nil {
  72. return fmt.Errorf("failed to write out cert file %s: %s", certFilename, err.Error())
  73. }
  74. keyOut, err := os.OpenFile(keyFilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
  75. if err != nil {
  76. return fmt.Errorf("failed to open %s for writing: %s", keyFilename, err.Error())
  77. }
  78. defer keyOut.Close()
  79. _, err = keyOut.Write(keyBytes)
  80. if err != nil {
  81. return fmt.Errorf("failed to write out key file %s: %s", keyFilename, err.Error())
  82. }
  83. return nil
  84. }