pkcs12.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package template
  13. import (
  14. "bytes"
  15. "crypto/x509"
  16. "encoding/base64"
  17. "encoding/pem"
  18. "fmt"
  19. "golang.org/x/crypto/pkcs12"
  20. gopkcs12 "software.sslmate.com/src/go-pkcs12"
  21. )
  22. func pkcs12keyPass(pass, input string) (string, error) {
  23. blocks, err := pkcs12.ToPEM([]byte(input), pass)
  24. if err != nil {
  25. return "", fmt.Errorf(errDecodePKCS12WithPass, err)
  26. }
  27. var pemData []byte
  28. for _, block := range blocks {
  29. // remove bag attributes like localKeyID, friendlyName
  30. block.Headers = nil
  31. if block.Type == pemTypeCertificate {
  32. continue
  33. }
  34. key, err := parsePrivateKey(block.Bytes)
  35. if err != nil {
  36. return "", err
  37. }
  38. // we use pkcs8 because it supports more key types (ecdsa, ed25519), not just RSA
  39. block.Bytes, err = x509.MarshalPKCS8PrivateKey(key)
  40. if err != nil {
  41. return "", err
  42. }
  43. // report error if encode fails
  44. var buf bytes.Buffer
  45. if err := pem.Encode(&buf, block); err != nil {
  46. return "", err
  47. }
  48. pemData = append(pemData, buf.Bytes()...)
  49. }
  50. return string(pemData), nil
  51. }
  52. func parsePrivateKey(block []byte) (any, error) {
  53. if k, err := x509.ParsePKCS1PrivateKey(block); err == nil {
  54. return k, nil
  55. }
  56. if k, err := x509.ParsePKCS8PrivateKey(block); err == nil {
  57. return k, nil
  58. }
  59. if k, err := x509.ParseECPrivateKey(block); err == nil {
  60. return k, nil
  61. }
  62. return nil, fmt.Errorf(errParsePrivKey)
  63. }
  64. func pkcs12key(input string) (string, error) {
  65. return pkcs12keyPass("", input)
  66. }
  67. func pkcs12certPass(pass, input string) (string, error) {
  68. blocks, err := pkcs12.ToPEM([]byte(input), pass)
  69. if err != nil {
  70. return "", fmt.Errorf(errDecodeCertWithPass, err)
  71. }
  72. var pemData []byte
  73. for _, block := range blocks {
  74. if block.Type != pemTypeCertificate {
  75. continue
  76. }
  77. // remove bag attributes like localKeyID, friendlyName
  78. block.Headers = nil
  79. // report error if encode fails
  80. var buf bytes.Buffer
  81. if err := pem.Encode(&buf, block); err != nil {
  82. return "", err
  83. }
  84. pemData = append(pemData, buf.Bytes()...)
  85. }
  86. // try to order certificate chain. If it fails we return
  87. // the unordered raw pem data.
  88. // This fails if multiple leaf or disjunct certs are provided.
  89. ordered, err := fetchCertChains(pemData)
  90. if err != nil {
  91. return string(pemData), nil
  92. }
  93. return string(ordered), nil
  94. }
  95. func pkcs12cert(input string) (string, error) {
  96. return pkcs12certPass("", input)
  97. }
  98. func pemToPkcs12(cert, key string) (string, error) {
  99. return pemToPkcs12Pass(cert, key, "")
  100. }
  101. func pemToPkcs12Pass(cert, key, pass string) (string, error) {
  102. certPem, _ := pem.Decode([]byte(cert))
  103. parsedCert, err := x509.ParseCertificate(certPem.Bytes)
  104. if err != nil {
  105. return "", err
  106. }
  107. return certsToPkcs12(parsedCert, key, nil, pass)
  108. }
  109. func fullPemToPkcs12(cert, key string) (string, error) {
  110. return fullPemToPkcs12Pass(cert, key, "")
  111. }
  112. func fullPemToPkcs12Pass(cert, key, pass string) (string, error) {
  113. certPem, rest := pem.Decode([]byte(cert))
  114. parsedCert, err := x509.ParseCertificate(certPem.Bytes)
  115. if err != nil {
  116. return "", err
  117. }
  118. caCerts := make([]*x509.Certificate, 0)
  119. for len(rest) > 0 {
  120. caPem, restBytes := pem.Decode(rest)
  121. rest = restBytes
  122. caCert, err := x509.ParseCertificate(caPem.Bytes)
  123. if err != nil {
  124. return "", err
  125. }
  126. caCerts = append(caCerts, caCert)
  127. }
  128. return certsToPkcs12(parsedCert, key, caCerts, pass)
  129. }
  130. func certsToPkcs12(cert *x509.Certificate, key string, caCerts []*x509.Certificate, password string) (string, error) {
  131. keyPem, _ := pem.Decode([]byte(key))
  132. parsedKey, err := parsePrivateKey(keyPem.Bytes)
  133. if err != nil {
  134. return "", err
  135. }
  136. pfx, err := gopkcs12.Modern.Encode(parsedKey, cert, caCerts, password)
  137. if err != nil {
  138. return "", err
  139. }
  140. return base64.StdEncoding.EncodeToString(pfx), nil
  141. }