Skip to content

Commit df275e5

Browse files
jameshfishersideshow
authored andcommitted
Allow PKCS#8 private keys in .pem files (#101)
* Allow PKCS#8 private keys in .pem files * Fix tests and test new behavior
1 parent cf826c6 commit df275e5

File tree

3 files changed

+87
-9
lines changed

3 files changed

+87
-9
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
Bag Attributes
2+
localKeyID: 8C 1A 9F 00 66 BD 24 42 B9 5D 1E EB FE 5E 8B CA 04 3D 73 83
3+
friendlyName: APNS/2 Private Key
4+
subject=/C=NZ/ST=Wellington/L=Wellington/O=Internet Widgits Pty Ltd/OU=9ZEH62KRVV/CN=APNS/2 Development IOS Push Services: com.sideshow.Apns2
5+
issuer=/C=NZ/ST=Wellington/L=Wellington/O=APNS/2 Inc./OU=APNS/2 Worldwide Developer Relations/CN=APNS/2 Worldwide Developer Relations Certification Authority
6+
-----BEGIN CERTIFICATE-----
7+
MIID6zCCAtMCAQIwDQYJKoZIhvcNAQELBQAwgcMxCzAJBgNVBAYTAk5aMRMwEQYD
8+
VQQIEwpXZWxsaW5ndG9uMRMwEQYDVQQHEwpXZWxsaW5ndG9uMRQwEgYDVQQKEwtB
9+
UE5TLzIgSW5jLjEtMCsGA1UECxMkQVBOUy8yIFdvcmxkd2lkZSBEZXZlbG9wZXIg
10+
UmVsYXRpb25zMUUwQwYDVQQDEzxBUE5TLzIgV29ybGR3aWRlIERldmVsb3BlciBS
11+
ZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTYwMTA4MDgzNDMw
12+
WhcNMjYwMTA1MDgzNDMwWjCBsjELMAkGA1UEBhMCTloxEzARBgNVBAgTCldlbGxp
13+
bmd0b24xEzARBgNVBAcTCldlbGxpbmd0b24xITAfBgNVBAoTGEludGVybmV0IFdp
14+
ZGdpdHMgUHR5IEx0ZDETMBEGA1UECxMKOVpFSDYyS1JWVjFBMD8GA1UEAxM4QVBO
15+
Uy8yIERldmVsb3BtZW50IElPUyBQdXNoIFNlcnZpY2VzOiBjb20uc2lkZXNob3cu
16+
QXBuczIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDY0c1TKB5oZPwQ
17+
7t1CwMIrvqB6GIU3tPy6RhckZXTkOB8YeBWJ7UKfCz8HGHFVomBP0T5OUbeqQzqW
18+
YJbQzZ8a6ZMszbL0lO4X9++3Oi5/TtAwOUOK8rOFN25m2KfsayHQZ/4vWStK2Fwm
19+
5aJbGLlpH/b/7z1D4vhmMgoBuT1IuyhGiyFxlZ9EtTloFvsqM1E5fYZOSZACyXTa
20+
K4vdgbQMgUVsI714FAgLTlK0UeiRkmKm3pdbtfVbrthzI+IHXKItUIy+Fn20PRMh
21+
dSnaztSz7tgBWCIx22qvcYogHWiOgUYIM772zE2y8UVOr8DsiRlsOHSA7EI4MJcQ
22+
G2FUq2Z/AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGyfyO2HMgcdeBcz3bt5BILX
23+
f7RA2/UmVIwcKR1qotTsF+PnBmcILeyOQgDe9tGU5cRc79kDt3JRmMYROFIMgFRf
24+
Wf22uOKtho7GQQaKvG+bkgMVdYFRlBHnF+KeqKH81qb9p+CT4Iw0GehIL1DijFLR
25+
VIAIBYpz4oBPCIE1ISVT+Fgaf3JAh59kbPbNw9AIDxaBtP8EuzSTNwfbxoGbCobS
26+
Wi1U8IsCwQFt8tM1m4ZXD1CcZIrGdryeAhVkvKIJRiU5QYWI2nqZN+JqQucm9ad0
27+
mYO5mJkIobUa4+ZJhCPKEdmgpFbRGk0wVuaDM9Cv6P2srsYAjaO4y3VP0GvNKRI=
28+
-----END CERTIFICATE-----
29+
Bag Attributes
30+
localKeyID: 8C 1A 9F 00 66 BD 24 42 B9 5D 1E EB FE 5E 8B CA 04 3D 73 83
31+
friendlyName: APNS/2 Private Key
32+
Key Attributes: <No Attributes>
33+
-----BEGIN PRIVATE KEY-----
34+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDY0c1TKB5oZPwQ
35+
7t1CwMIrvqB6GIU3tPy6RhckZXTkOB8YeBWJ7UKfCz8HGHFVomBP0T5OUbeqQzqW
36+
YJbQzZ8a6ZMszbL0lO4X9++3Oi5/TtAwOUOK8rOFN25m2KfsayHQZ/4vWStK2Fwm
37+
5aJbGLlpH/b/7z1D4vhmMgoBuT1IuyhGiyFxlZ9EtTloFvsqM1E5fYZOSZACyXTa
38+
K4vdgbQMgUVsI714FAgLTlK0UeiRkmKm3pdbtfVbrthzI+IHXKItUIy+Fn20PRMh
39+
dSnaztSz7tgBWCIx22qvcYogHWiOgUYIM772zE2y8UVOr8DsiRlsOHSA7EI4MJcQ
40+
G2FUq2Z/AgMBAAECggEBAJbxkIj44Bp7W0SKln0XZtY/csctdOjwVhV0ID5VZ4hO
41+
Tc+iIhSQmZXRpYJSEOy2C2jl2gN6PmwJO6te+P/Kdp6sx6okVhaR7CPBlyAvIBm/
42+
C47W/t+n0TTH/1MYN+eOOc815q6d3FbRw23M5jeXQdUezL0ml7dANwAmi/LhO/n6
43+
EVjiQPFQEazKO+FJxWAqDm0uQlyWbew678sbIuqnA0jc4kB0wi5UPg3YFnVo4Rqn
44+
qanbLwh7T9HhhZxpnkDg/DvFQ+XpJdz265r/vxBMRG08Lp6PIIGITTlrybdDeK53
45+
de2eXLCzYrCGAEB8TozjNH9/c5AHtkhcyHJmmZlnDnECgYEA9ifzgiuUhB61ZB+8
46+
90zsrOCHpQMcK6CeUIOCHBilEkaLyEx+5lXE0itgAnMtgNDTWUUlEmBZdNxurP00
47+
HPWeGD5w07PX8pj7fx65157oM1ibO0/uMM/aOdpL522MLyEBc5ucWob42KUwMsu7
48+
ppGasloiZuNKt/IuITqa8nu7zWcCgYEA4X2D3fBnSYvWuTazlbAcZM1T8do62ZZL
49+
jPuQDt/hBpG5v4zCmlmaYNk8emJlfsE9xnOI49CH7GfsipEahBYEvKQFW3zNkWgt
50+
kmgJHefreV7HkDin/Q+nWAVmtH7Ffw9hWizfJ56JbI8qxdc1zSzlDAdlxfpZvwQd
51+
OFNcYIF61ykCgYAx5AkL0g9o89xp7bDcIsA5jcyQWmAES6qqwOzHCwux95BvSWnS
52+
/4FD47yy4mtPl4OurUAFSHf5IpBgCXXdhL7FRSqTDflv1yfqLO0X0cJYXdYgoGOz
53+
iv09Coyl3GM0TilAKEL5ai/XoStysC5ZZVuIWJJubhT/0VseKwWqrf9zcwKBgH6/
54+
NK4+AXDfv7SgQNW1BmDK4ZKink3MI299v/38bdppc0Vuc7ya/SHPOiV4xaA4Mucn
55+
7hxQDPcfe2BwK71vOv5mG/TO9CX1rxgKjoVW5Y91bStuDU87y064yoBOeejv1kL/
56+
0ffNL2XsG5jVXZKU17KpPdXI4UVzpJESmmxMm6XxAoGADGdAHwwDvM9Qu7VyXJok
57+
t20R1E+QpY3uUpim1zR79Ud9KwrGx5aR+qLOBdnnWRBOtPplvodhF/ALWYxcdZEp
58+
HJiMCcLFWKbphB34pVPj2JEMMCIgWgwYDiK+9wiWd6o5lk8MigonrQiM78NkdaTD
59+
mYuNoitP6pDdcAZ0kDXeFyY=
60+
-----END PRIVATE KEY-----

certificate/certificate.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ import (
1616

1717
// Possible errors when parsing a certificate.
1818
var (
19-
ErrFailedToDecryptKey = errors.New("failed to decrypt private key")
20-
ErrFailedToParsePKCS1PrivateKey = errors.New("failed to parse PKCS1 private key")
21-
ErrFailedToParseCertificate = errors.New("failed to parse certificate PEM data")
22-
ErrNoPrivateKey = errors.New("no private key")
23-
ErrNoCertificate = errors.New("no certificate")
19+
ErrFailedToDecryptKey = errors.New("failed to decrypt private key")
20+
ErrFailedToParsePrivateKey = errors.New("failed to parse private key")
21+
ErrFailedToParseCertificate = errors.New("failed to parse certificate PEM data")
22+
ErrNoPrivateKey = errors.New("no private key")
23+
ErrNoCertificate = errors.New("no certificate")
2424
)
2525

2626
// FromP12File loads a PKCS#12 certificate from a local file and returns a
@@ -120,9 +120,14 @@ func unencryptPrivateKey(block *pem.Block, password string) (crypto.PrivateKey,
120120
}
121121

122122
func parsePrivateKey(bytes []byte) (crypto.PrivateKey, error) {
123+
var key crypto.PrivateKey
123124
key, err := x509.ParsePKCS1PrivateKey(bytes)
124-
if err != nil {
125-
return nil, ErrFailedToParsePKCS1PrivateKey
125+
if err == nil {
126+
return key, nil
127+
}
128+
key, err = x509.ParsePKCS8PrivateKey(bytes)
129+
if err == nil {
130+
return key, nil
126131
}
127-
return key, nil
132+
return nil, ErrFailedToParsePrivateKey
128133
}

certificate/certificate_test.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ func TestValidCertificateFromPemBytes(t *testing.T) {
5858
assert.Nil(t, verifyHostname(cer))
5959
}
6060

61+
func TestValidCertificateFromPemFileWithPKCS8PrivateKey(t *testing.T) {
62+
cer, err := certificate.FromPemFile("_fixtures/certificate-valid-pkcs8.pem", "")
63+
assert.NoError(t, err)
64+
assert.Nil(t, verifyHostname(cer))
65+
}
66+
67+
func TestValidCertificateFromPemBytesWithPKCS8PrivateKey(t *testing.T) {
68+
bytes, _ := ioutil.ReadFile("_fixtures/certificate-valid-pkcs8.pem")
69+
cer, err := certificate.FromPemBytes(bytes, "")
70+
assert.NoError(t, err)
71+
assert.Nil(t, verifyHostname(cer))
72+
}
73+
6174
func TestEncryptedValidCertificateFromPemFile(t *testing.T) {
6275
cer, err := certificate.FromPemFile("_fixtures/certificate-valid-encrypted.pem", "password")
6376
assert.NoError(t, err)
@@ -79,7 +92,7 @@ func TestBadPasswordPemFile(t *testing.T) {
7992
func TestBadKeyPemFile(t *testing.T) {
8093
cer, err := certificate.FromPemFile("_fixtures/certificate-bad-key.pem", "")
8194
assert.Equal(t, tls.Certificate{}, cer)
82-
assert.Equal(t, certificate.ErrFailedToParsePKCS1PrivateKey, err)
95+
assert.Equal(t, certificate.ErrFailedToParsePrivateKey, err)
8396
}
8497

8598
func TestNoKeyPemFile(t *testing.T) {

0 commit comments

Comments
 (0)