...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package certloader
18
19 import (
20 "bytes"
21 "crypto"
22 "crypto/x509"
23 "encoding/pem"
24 "errors"
25 "fmt"
26 "io"
27 "os"
28 "strings"
29
30 "github.com/sassoftware/relic/lib/passprompt"
31 "golang.org/x/crypto/openpgp"
32 "golang.org/x/crypto/openpgp/armor"
33 "golang.org/x/crypto/openpgp/packet"
34 )
35
36
37
38
39
40 func ParseAnyPrivateKey(blob []byte, prompt passprompt.PasswordGetter) (crypto.PrivateKey, error) {
41 if bytes.HasPrefix(blob, []byte("-----BEGIN PGP")) {
42 return parsePgpPrivateKey(blob, prompt)
43 } else if bytes.HasPrefix(blob, []byte("-----BEGIN")) {
44 var block *pem.Block
45 for {
46 block, blob = pem.Decode(blob)
47 if block == nil {
48 break
49 } else if block.Type == "PRIVATE KEY" || strings.HasSuffix(block.Type, " PRIVATE KEY") {
50 return parsePemPrivateKey(block, prompt)
51 }
52 }
53 return nil, errors.New("failed to find any private keys in PEM data")
54 } else if blob[0] == asn1Magic {
55 return parsePrivateKey(blob)
56 } else if blob[0]&0x80 != 0 {
57 return parsePgpPrivateKey(blob, prompt)
58 } else {
59 return nil, errors.New("unrecognized private key format")
60 }
61 }
62
63 func parsePemPrivateKey(block *pem.Block, prompt passprompt.PasswordGetter) (crypto.PrivateKey, error) {
64 if !x509.IsEncryptedPEMBlock(block) {
65 return parsePrivateKey(block.Bytes)
66 }
67 if prompt == nil {
68 return nil, errors.New("private key is encrypted and no password was provided")
69 }
70 for {
71 password, err := prompt.GetPasswd("Password for private key: ")
72 if err != nil {
73 return nil, err
74 } else if password == "" {
75 return nil, errors.New("aborted")
76 }
77 keyblob, err := x509.DecryptPEMBlock(block, []byte(password))
78 if err == x509.IncorrectPasswordError {
79 continue
80 } else if err != nil {
81 return nil, err
82 } else {
83 return parsePrivateKey(keyblob)
84 }
85 }
86 }
87
88 func parsePgpPrivateKey(blob []byte, prompt passprompt.PasswordGetter) (crypto.PrivateKey, error) {
89 var reader io.Reader = bytes.NewReader(blob)
90 if blob[0] == '-' {
91 block, err := armor.Decode(reader)
92 if err != nil {
93 return nil, err
94 }
95 reader = block.Body
96 }
97 entity, err := openpgp.ReadEntity(packet.NewReader(reader))
98 if err != nil {
99 return nil, err
100 }
101 if entity.PrivateKey == nil {
102 return nil, errors.New("file does not contain a private key")
103 }
104 if entity.PrivateKey.Encrypted {
105 fmt.Fprintln(os.Stderr, "Key fingerprint:", entity.PrimaryKey.KeyIdString())
106 for name := range entity.Identities {
107 fmt.Fprintln(os.Stderr, "UID:", name)
108 }
109 fmt.Fprintln(os.Stderr)
110 for {
111 password, err := prompt.GetPasswd("Passphrase for key: ")
112 if err != nil {
113 return nil, err
114 } else if password == "" {
115 return nil, errors.New("Aborted")
116 }
117 err = entity.PrivateKey.Decrypt([]byte(password))
118 if err == nil {
119 break
120 }
121 }
122 }
123 return entity.PrivateKey.PrivateKey, nil
124 }
125
View as plain text