cert.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package cert
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "encoding/pem"
  7. "math/big"
  8. "time"
  9. )
  10. //go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg cert -path Protocol,TLS,Cert
  11. type Certificate struct {
  12. // Cerificate in x509 format
  13. Certificate []byte
  14. // Private key in x509 format
  15. PrivateKey []byte
  16. }
  17. type Option func(*x509.Certificate)
  18. func Authority(isCA bool) Option {
  19. return func(cert *x509.Certificate) {
  20. cert.IsCA = isCA
  21. }
  22. }
  23. func NotBefore(t time.Time) Option {
  24. return func(c *x509.Certificate) {
  25. c.NotBefore = t
  26. }
  27. }
  28. func NotAfter(t time.Time) Option {
  29. return func(c *x509.Certificate) {
  30. c.NotAfter = t
  31. }
  32. }
  33. func DNSNames(names ...string) Option {
  34. return func(c *x509.Certificate) {
  35. c.DNSNames = names
  36. }
  37. }
  38. func CommonName(name string) Option {
  39. return func(c *x509.Certificate) {
  40. c.Subject.CommonName = name
  41. }
  42. }
  43. func Generate(parent *x509.Certificate, opts ...Option) (*Certificate, error) {
  44. priv, err := rsa.GenerateKey(rand.Reader, 2048)
  45. if err != nil {
  46. return nil, newError("failed to generate RSA private key").Base(err)
  47. }
  48. serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
  49. serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
  50. if err != nil {
  51. return nil, newError("failed to generate serial number").Base(err)
  52. }
  53. template := &x509.Certificate{
  54. SerialNumber: serialNumber,
  55. NotBefore: time.Now().Add(time.Hour * -1),
  56. NotAfter: time.Now().Add(time.Hour),
  57. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  58. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  59. BasicConstraintsValid: true,
  60. }
  61. for _, opt := range opts {
  62. opt(template)
  63. }
  64. if parent == nil {
  65. parent = template
  66. }
  67. derBytes, err := x509.CreateCertificate(rand.Reader, template, parent, priv.Public(), priv)
  68. if err != nil {
  69. return nil, newError("failed to create certificate").Base(err)
  70. }
  71. certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
  72. keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
  73. return &Certificate{
  74. Certificate: certPEM,
  75. PrivateKey: keyPEM,
  76. }, nil
  77. }