pkcs12.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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/pem"
  17. "fmt"
  18. "golang.org/x/crypto/pkcs12"
  19. )
  20. func pkcs12keyPass(pass, input string) (string, error) {
  21. blocks, err := pkcs12.ToPEM([]byte(input), pass)
  22. if err != nil {
  23. return "", fmt.Errorf(errDecodePKCS12WithPass, err)
  24. }
  25. var pemData []byte
  26. for _, block := range blocks {
  27. // remove bag attributes like localKeyID, friendlyName
  28. block.Headers = nil
  29. if block.Type == pemTypeCertificate {
  30. continue
  31. }
  32. key, err := parsePrivateKey(block.Bytes)
  33. if err != nil {
  34. return "", err
  35. }
  36. // we use pkcs8 because it supports more key types (ecdsa, ed25519), not just RSA
  37. block.Bytes, err = x509.MarshalPKCS8PrivateKey(key)
  38. if err != nil {
  39. return "", err
  40. }
  41. // report error if encode fails
  42. var buf bytes.Buffer
  43. if err := pem.Encode(&buf, block); err != nil {
  44. return "", err
  45. }
  46. pemData = append(pemData, buf.Bytes()...)
  47. }
  48. return string(pemData), nil
  49. }
  50. func parsePrivateKey(block []byte) (interface{}, error) {
  51. if k, err := x509.ParsePKCS1PrivateKey(block); err == nil {
  52. return k, nil
  53. }
  54. if k, err := x509.ParsePKCS8PrivateKey(block); err == nil {
  55. return k, nil
  56. }
  57. if k, err := x509.ParseECPrivateKey(block); err == nil {
  58. return k, nil
  59. }
  60. return nil, fmt.Errorf(errParsePrivKey)
  61. }
  62. func pkcs12key(input string) (string, error) {
  63. return pkcs12keyPass("", input)
  64. }
  65. func pkcs12certPass(pass, input string) (string, error) {
  66. blocks, err := pkcs12.ToPEM([]byte(input), pass)
  67. if err != nil {
  68. return "", fmt.Errorf(errDecodeCertWithPass, err)
  69. }
  70. var pemData []byte
  71. for _, block := range blocks {
  72. if block.Type != pemTypeCertificate {
  73. continue
  74. }
  75. // remove bag attributes like localKeyID, friendlyName
  76. block.Headers = nil
  77. // report error if encode fails
  78. var buf bytes.Buffer
  79. if err := pem.Encode(&buf, block); err != nil {
  80. return "", err
  81. }
  82. pemData = append(pemData, buf.Bytes()...)
  83. }
  84. // try to order certificate chain. If it fails we return
  85. // the unordered raw pem data.
  86. // This fails if multiple leaf or disjunct certs are provided.
  87. ordered, err := fetchCertChains(pemData)
  88. if err != nil {
  89. return string(pemData), nil
  90. }
  91. return string(ordered), nil
  92. }
  93. func pkcs12cert(input string) (string, error) {
  94. return pkcs12certPass("", input)
  95. }