Skip to content

Commit

Permalink
Fix private key parsing issue #33
Browse files Browse the repository at this point in the history
  • Loading branch information
sideshow committed Aug 2, 2016
1 parent eacc6af commit 9469e01
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 8 deletions.
56 changes: 56 additions & 0 deletions certificate/_fixtures/certificate-valid-pkcs8-key.pem
@@ -0,0 +1,56 @@
Bag Attributes
localKeyID: 8C 1A 9F 00 66 BD 24 42 B9 5D 1E EB FE 5E 8B CA 04 3D 73 83
friendlyName: APNS/2 Private Key
subject=/C=NZ/ST=Wellington/L=Wellington/O=Internet Widgits Pty Ltd/OU=9ZEH62KRVV/CN=APNS/2 Development IOS Push Services: com.sideshow.Apns2
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
-----BEGIN CERTIFICATE-----
MIID6zCCAtMCAQIwDQYJKoZIhvcNAQELBQAwgcMxCzAJBgNVBAYTAk5aMRMwEQYD
VQQIEwpXZWxsaW5ndG9uMRMwEQYDVQQHEwpXZWxsaW5ndG9uMRQwEgYDVQQKEwtB
UE5TLzIgSW5jLjEtMCsGA1UECxMkQVBOUy8yIFdvcmxkd2lkZSBEZXZlbG9wZXIg
UmVsYXRpb25zMUUwQwYDVQQDEzxBUE5TLzIgV29ybGR3aWRlIERldmVsb3BlciBS
ZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTYwMTA4MDgzNDMw
WhcNMjYwMTA1MDgzNDMwWjCBsjELMAkGA1UEBhMCTloxEzARBgNVBAgTCldlbGxp
bmd0b24xEzARBgNVBAcTCldlbGxpbmd0b24xITAfBgNVBAoTGEludGVybmV0IFdp
ZGdpdHMgUHR5IEx0ZDETMBEGA1UECxMKOVpFSDYyS1JWVjFBMD8GA1UEAxM4QVBO
Uy8yIERldmVsb3BtZW50IElPUyBQdXNoIFNlcnZpY2VzOiBjb20uc2lkZXNob3cu
QXBuczIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDY0c1TKB5oZPwQ
7t1CwMIrvqB6GIU3tPy6RhckZXTkOB8YeBWJ7UKfCz8HGHFVomBP0T5OUbeqQzqW
YJbQzZ8a6ZMszbL0lO4X9++3Oi5/TtAwOUOK8rOFN25m2KfsayHQZ/4vWStK2Fwm
5aJbGLlpH/b/7z1D4vhmMgoBuT1IuyhGiyFxlZ9EtTloFvsqM1E5fYZOSZACyXTa
K4vdgbQMgUVsI714FAgLTlK0UeiRkmKm3pdbtfVbrthzI+IHXKItUIy+Fn20PRMh
dSnaztSz7tgBWCIx22qvcYogHWiOgUYIM772zE2y8UVOr8DsiRlsOHSA7EI4MJcQ
G2FUq2Z/AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGyfyO2HMgcdeBcz3bt5BILX
f7RA2/UmVIwcKR1qotTsF+PnBmcILeyOQgDe9tGU5cRc79kDt3JRmMYROFIMgFRf
Wf22uOKtho7GQQaKvG+bkgMVdYFRlBHnF+KeqKH81qb9p+CT4Iw0GehIL1DijFLR
VIAIBYpz4oBPCIE1ISVT+Fgaf3JAh59kbPbNw9AIDxaBtP8EuzSTNwfbxoGbCobS
Wi1U8IsCwQFt8tM1m4ZXD1CcZIrGdryeAhVkvKIJRiU5QYWI2nqZN+JqQucm9ad0
mYO5mJkIobUa4+ZJhCPKEdmgpFbRGk0wVuaDM9Cv6P2srsYAjaO4y3VP0GvNKRI=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDY0c1TKB5oZPwQ
7t1CwMIrvqB6GIU3tPy6RhckZXTkOB8YeBWJ7UKfCz8HGHFVomBP0T5OUbeqQzqW
YJbQzZ8a6ZMszbL0lO4X9++3Oi5/TtAwOUOK8rOFN25m2KfsayHQZ/4vWStK2Fwm
5aJbGLlpH/b/7z1D4vhmMgoBuT1IuyhGiyFxlZ9EtTloFvsqM1E5fYZOSZACyXTa
K4vdgbQMgUVsI714FAgLTlK0UeiRkmKm3pdbtfVbrthzI+IHXKItUIy+Fn20PRMh
dSnaztSz7tgBWCIx22qvcYogHWiOgUYIM772zE2y8UVOr8DsiRlsOHSA7EI4MJcQ
G2FUq2Z/AgMBAAECggEBAJbxkIj44Bp7W0SKln0XZtY/csctdOjwVhV0ID5VZ4hO
Tc+iIhSQmZXRpYJSEOy2C2jl2gN6PmwJO6te+P/Kdp6sx6okVhaR7CPBlyAvIBm/
C47W/t+n0TTH/1MYN+eOOc815q6d3FbRw23M5jeXQdUezL0ml7dANwAmi/LhO/n6
EVjiQPFQEazKO+FJxWAqDm0uQlyWbew678sbIuqnA0jc4kB0wi5UPg3YFnVo4Rqn
qanbLwh7T9HhhZxpnkDg/DvFQ+XpJdz265r/vxBMRG08Lp6PIIGITTlrybdDeK53
de2eXLCzYrCGAEB8TozjNH9/c5AHtkhcyHJmmZlnDnECgYEA9ifzgiuUhB61ZB+8
90zsrOCHpQMcK6CeUIOCHBilEkaLyEx+5lXE0itgAnMtgNDTWUUlEmBZdNxurP00
HPWeGD5w07PX8pj7fx65157oM1ibO0/uMM/aOdpL522MLyEBc5ucWob42KUwMsu7
ppGasloiZuNKt/IuITqa8nu7zWcCgYEA4X2D3fBnSYvWuTazlbAcZM1T8do62ZZL
jPuQDt/hBpG5v4zCmlmaYNk8emJlfsE9xnOI49CH7GfsipEahBYEvKQFW3zNkWgt
kmgJHefreV7HkDin/Q+nWAVmtH7Ffw9hWizfJ56JbI8qxdc1zSzlDAdlxfpZvwQd
OFNcYIF61ykCgYAx5AkL0g9o89xp7bDcIsA5jcyQWmAES6qqwOzHCwux95BvSWnS
/4FD47yy4mtPl4OurUAFSHf5IpBgCXXdhL7FRSqTDflv1yfqLO0X0cJYXdYgoGOz
iv09Coyl3GM0TilAKEL5ai/XoStysC5ZZVuIWJJubhT/0VseKwWqrf9zcwKBgH6/
NK4+AXDfv7SgQNW1BmDK4ZKink3MI299v/38bdppc0Vuc7ya/SHPOiV4xaA4Mucn
7hxQDPcfe2BwK71vOv5mG/TO9CX1rxgKjoVW5Y91bStuDU87y064yoBOeejv1kL/
0ffNL2XsG5jVXZKU17KpPdXI4UVzpJESmmxMm6XxAoGADGdAHwwDvM9Qu7VyXJok
t20R1E+QpY3uUpim1zR79Ud9KwrGx5aR+qLOBdnnWRBOtPplvodhF/ALWYxcdZEp
HJiMCcLFWKbphB34pVPj2JEMMCIgWgwYDiK+9wiWd6o5lk8MigonrQiM78NkdaTD
mYuNoitP6pDdcAZ0kDXeFyY=
-----END PRIVATE KEY-----
25 changes: 17 additions & 8 deletions certificate/certificate.go
Expand Up @@ -4,6 +4,8 @@ package certificate

import (
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
Expand All @@ -16,11 +18,11 @@ import (

// Possible errors when parsing a certificate.
var (
ErrFailedToDecryptKey = errors.New("failed to decrypt private key")
ErrFailedToParsePKCS1PrivateKey = errors.New("failed to parse PKCS1 private key")
ErrFailedToParseCertificate = errors.New("failed to parse certificate PEM data")
ErrNoPrivateKey = errors.New("no private key")
ErrNoCertificate = errors.New("no certificate")
ErrFailedToDecryptKey = errors.New("failed to decrypt private key")
ErrFailedToParsePKCS1PrivateKey = errors.New("failed to parse PKCS1 private key")
ErrUnknownPrivateKeyType = errors.New("unknown private key type in PKCS#8 wrapping")
)

// FromP12File loads a PKCS#12 certificate from a local file and returns a
Expand Down Expand Up @@ -119,10 +121,17 @@ func unencryptPrivateKey(block *pem.Block, password string) (crypto.PrivateKey,
return parsePrivateKey(block.Bytes)
}

func parsePrivateKey(bytes []byte) (crypto.PrivateKey, error) {
key, err := x509.ParsePKCS1PrivateKey(bytes)
if err != nil {
return nil, ErrFailedToParsePKCS1PrivateKey
func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
return key, nil
}
if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
switch key := key.(type) {
case *rsa.PrivateKey, *ecdsa.PrivateKey:
return key, nil
default:
return nil, ErrUnknownPrivateKeyType
}
}
return key, nil
return nil, ErrFailedToParsePKCS1PrivateKey
}
13 changes: 13 additions & 0 deletions certificate/certificate_test.go
Expand Up @@ -58,6 +58,19 @@ func TestValidCertificateFromPemBytes(t *testing.T) {
assert.Nil(t, verifyHostname(cer))
}

func TestValidCertificateWithPKCS8KeyFromPemFile(t *testing.T) {
cer, err := certificate.FromPemFile("_fixtures/certificate-valid-pkcs8-key.pem", "")
assert.NoError(t, err)
assert.Nil(t, verifyHostname(cer))
}

func TestValidCertificateWithPKCS8KeyFromPemBytes(t *testing.T) {
bytes, _ := ioutil.ReadFile("_fixtures/certificate-valid-pkcs8-key.pem")
cer, err := certificate.FromPemBytes(bytes, "")
assert.NoError(t, err)
assert.Nil(t, verifyHostname(cer))
}

func TestEncryptedValidCertificateFromPemFile(t *testing.T) {
cer, err := certificate.FromPemFile("_fixtures/certificate-valid-encrypted.pem", "password")
assert.NoError(t, err)
Expand Down

0 comments on commit 9469e01

Please sign in to comment.