1
0

pki.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Package pki contains bits and pieces to work with OpenVPN PKI related operations.
  2. package pki
  3. import (
  4. "crypto/rand"
  5. "crypto/rsa"
  6. "crypto/x509"
  7. "crypto/x509/pkix"
  8. "encoding/asn1"
  9. //"github.com/sirupsen/logrus"
  10. "bytes"
  11. "encoding/pem"
  12. "fmt"
  13. "math/big"
  14. "time"
  15. )
  16. const (
  17. _CrtExpireYears = 10
  18. _CrtKeyLength = 2024
  19. )
  20. // CertHolder encapsulates a public certificate and the corresponding private key.
  21. type CertHolder struct {
  22. Cert string // PEM Encoded Certificate
  23. Key string // PEM Encoded Private Key
  24. }
  25. // CA is a special type of CertHolder that also has a CSR in it.
  26. type CA struct {
  27. CertHolder
  28. CSR string
  29. }
  30. // NewCA returns a newly generated CA.
  31. //
  32. // This will generate a public/private RSA keypair and a authority certificate signed by itself.
  33. func NewCA() (*CA, error) {
  34. type basicConstraints struct {
  35. IsCA bool `asn1:"optional"`
  36. MaxPathLen int `asn1:"optional,default:-1"`
  37. }
  38. key, err := rsa.GenerateKey(rand.Reader, _CrtKeyLength)
  39. if err != nil {
  40. return nil, fmt.Errorf("private key cannot be created: %s", err)
  41. }
  42. val, err := asn1.Marshal(basicConstraints{true, 0})
  43. if err != nil {
  44. return nil, fmt.Errorf("can not marshal basic constraints: %s", err)
  45. }
  46. names := pkix.Name{CommonName: "CA"}
  47. var csrTemplate = x509.CertificateRequest{
  48. Subject: names,
  49. SignatureAlgorithm: x509.SHA512WithRSA,
  50. ExtraExtensions: []pkix.Extension{
  51. {
  52. Id: asn1.ObjectIdentifier{2, 5, 29, 19},
  53. Value: val,
  54. Critical: true,
  55. },
  56. },
  57. }
  58. csrCertificate, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, key)
  59. if err != nil {
  60. return nil, fmt.Errorf("can not create certificate request: %s", err)
  61. }
  62. csr := pem.EncodeToMemory(&pem.Block{
  63. Type: PEMCSRBlockType, Bytes: csrCertificate,
  64. })
  65. // Serial number
  66. serial, err := rand.Int(rand.Reader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil))
  67. if err != nil {
  68. return nil, err
  69. }
  70. now := time.Now()
  71. // Create the request template
  72. template := x509.Certificate{
  73. SerialNumber: serial,
  74. Subject: names,
  75. NotBefore: now.Add(-10 * time.Minute).UTC(),
  76. NotAfter: now.Add(time.Duration(24*365*_CrtExpireYears) * time.Hour).UTC(),
  77. BasicConstraintsValid: true,
  78. IsCA: true,
  79. KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
  80. //ExtKeyUsage: []x509.ExtKeyUsage{x509.KeyUsageCertSign, x509.ExtKeyUsageClientAuth},
  81. }
  82. // Sign the certificate authority
  83. certificate, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
  84. if err != nil {
  85. return nil, fmt.Errorf("failed to generate certificate error: %s", err)
  86. }
  87. var request bytes.Buffer
  88. var privateKey bytes.Buffer
  89. if err := pem.Encode(&request, &pem.Block{Type: PEMCertificateBlockType, Bytes: certificate}); err != nil {
  90. return nil, err
  91. }
  92. if err := pem.Encode(&privateKey, &pem.Block{Type: PEMRSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(key)}); err != nil {
  93. return nil, err
  94. }
  95. return &CA{
  96. CertHolder: CertHolder{
  97. Key: privateKey.String(),
  98. Cert: request.String(),
  99. },
  100. CSR: string(csr),
  101. }, nil
  102. }
  103. // NewServerCertHolder generates a RSA key-pair and a x509 certificate signed by the CA for the server.
  104. func NewServerCertHolder(ca *CA) (*CertHolder, error) {
  105. return newCert(ca, true, "localhost")
  106. }
  107. // NewClientCertHolder generates a RSA key-pair and a x509 certificate signed by the CA for the client.
  108. func NewClientCertHolder(ca *CA, username string) (*CertHolder, error) {
  109. return newCert(ca, false, username)
  110. }
  111. // newCert generates a RSA key-pair and a x509 certificate signed by the CA.
  112. func newCert(ca *CA, server bool, cn string) (*CertHolder, error) {
  113. // Get CA private key
  114. block, _ := pem.Decode([]byte(ca.Key))
  115. if block == nil {
  116. return nil, fmt.Errorf("failed to parse ca private key")
  117. }
  118. caKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  119. if err != nil {
  120. return nil, fmt.Errorf("failed to parse ca private key: %s", err)
  121. }
  122. caCert, err := ReadCertFromPEM(ca.Cert)
  123. if err != nil {
  124. return nil, fmt.Errorf("failed to parse ca cert: %v", err)
  125. }
  126. // Create new cert's key
  127. key, err := rsa.GenerateKey(rand.Reader, 2048)
  128. if err != nil {
  129. return nil, fmt.Errorf("private key cannot be created: %s", err)
  130. }
  131. serial, err := rand.Int(rand.Reader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil))
  132. if err != nil {
  133. return nil, err
  134. }
  135. val, err := asn1.Marshal(asn1.BitString{Bytes: []byte{0x80}, BitLength: 2}) // setting nsCertType to Client Type
  136. if err != nil {
  137. return nil, fmt.Errorf("can not marshal nsCertType: %v", err)
  138. }
  139. now := time.Now()
  140. tml := x509.Certificate{
  141. NotBefore: now.Add(-10 * time.Minute).UTC(),
  142. NotAfter: now.Add(time.Duration(24*365*_CrtExpireYears) * time.Hour).UTC(),
  143. SerialNumber: serial,
  144. Subject: pkix.Name{
  145. CommonName: cn,
  146. Organization: []string{"OVPM"},
  147. },
  148. KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement,
  149. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
  150. BasicConstraintsValid: true,
  151. ExtraExtensions: []pkix.Extension{
  152. {
  153. Id: asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 1, 1},
  154. Value: val,
  155. },
  156. },
  157. }
  158. if server {
  159. tml.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement | x509.KeyUsageKeyEncipherment
  160. tml.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}
  161. val, err := asn1.Marshal(asn1.BitString{Bytes: []byte{0x40}, BitLength: 2}) // setting nsCertType to Server Type
  162. if err != nil {
  163. return nil, fmt.Errorf("can not marshal nsCertType: %v", err)
  164. }
  165. tml.ExtraExtensions[0].Id = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 1, 1}
  166. tml.ExtraExtensions[0].Value = val
  167. }
  168. // Sign with CA's private key
  169. cert, err := x509.CreateCertificate(rand.Reader, &tml, caCert, &key.PublicKey, caKey)
  170. if err != nil {
  171. return nil, fmt.Errorf("certificate cannot be created: %s", err)
  172. }
  173. priKeyPem := pem.EncodeToMemory(&pem.Block{
  174. Type: PEMRSAPrivateKeyBlockType,
  175. Bytes: x509.MarshalPKCS1PrivateKey(key),
  176. })
  177. certPem := pem.EncodeToMemory(&pem.Block{
  178. Type: PEMCertificateBlockType,
  179. Bytes: cert,
  180. })
  181. return &CertHolder{
  182. Key: string(priKeyPem[:]),
  183. Cert: string(certPem[:]),
  184. }, nil
  185. }
  186. // NewCRL takes in a list of certificate serial numbers to-be-revoked and a CA then makes a PEM encoded CRL and returns it as a string.
  187. func NewCRL(ca *CA, serials ...*big.Int) (string, error) {
  188. caCrt, err := ReadCertFromPEM(ca.Cert)
  189. if err != nil {
  190. return "", err
  191. }
  192. block, _ := pem.Decode([]byte(ca.Key))
  193. if block == nil {
  194. return "", fmt.Errorf("failed to parse ca private key")
  195. }
  196. priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  197. if err != nil {
  198. return "", fmt.Errorf("failed to parse ca private key: %s", err)
  199. }
  200. var revokedCertList []pkix.RevokedCertificate
  201. for _, serial := range serials {
  202. revokedCert := pkix.RevokedCertificate{
  203. SerialNumber: serial,
  204. RevocationTime: time.Now().UTC(),
  205. }
  206. revokedCertList = append(revokedCertList, revokedCert)
  207. }
  208. crl, err := caCrt.CreateCRL(rand.Reader, priv, revokedCertList, time.Now().UTC(), time.Now().Add(365*24*60*time.Minute).UTC())
  209. if err != nil {
  210. return "", err
  211. }
  212. crlPem := pem.EncodeToMemory(&pem.Block{
  213. Type: PEMx509CRLBlockType,
  214. Bytes: crl,
  215. })
  216. return string(crlPem[:]), nil
  217. }
  218. // ReadCertFromPEM decodes a PEM encoded string into a x509.Certificate.
  219. func ReadCertFromPEM(s string) (*x509.Certificate, error) {
  220. block, _ := pem.Decode([]byte(s))
  221. var cert *x509.Certificate
  222. cert, _ = x509.ParseCertificate(block.Bytes)
  223. return cert, nil
  224. }