Correctly identify PEM files generated from PKCS12 files in oauth2client.
Reviewed in https://codereview.appspot.com/19380043/.
Fixes issue #249.
diff --git a/oauth2client/crypt.py b/oauth2client/crypt.py
index 2d31815..d2d7a3b 100644
--- a/oauth2client/crypt.py
+++ b/oauth2client/crypt.py
@@ -38,7 +38,6 @@
try:
from OpenSSL import crypto
-
class OpenSSLVerifier(object):
"""Verifies the signature on a message."""
@@ -125,8 +124,9 @@
Raises:
OpenSSL.crypto.Error if the key can't be parsed.
"""
- if key.startswith('-----BEGIN '):
- pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, key)
+ parsed_pem_key = _parse_pem_key(key)
+ if parsed_pem_key:
+ pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, parsed_pem_key)
else:
pkey = crypto.load_pkcs12(key, password).get_privatekey()
return OpenSSLSigner(pkey)
@@ -230,8 +230,9 @@
Raises:
NotImplementedError if they key isn't in PEM format.
"""
- if key.startswith('-----BEGIN '):
- pkey = RSA.importKey(key)
+ parsed_pem_key = _parse_pem_key(key)
+ if parsed_pem_key:
+ pkey = RSA.importKey(parsed_pem_key)
else:
raise NotImplementedError(
'PKCS12 format is not supported by the PyCrpto library. '
@@ -256,6 +257,24 @@
'PyOpenSSL, or PyCrypto 2.6 or later')
+def _parse_pem_key(raw_key_input):
+ """Identify and extract PEM keys.
+
+ Determines whether the given key is in the format of PEM key, and extracts
+ the relevant part of the key if it is.
+
+ Args:
+ raw_key_input: The contents of a private key file (either PEM or PKCS12).
+
+ Returns:
+ string, The actual key if the contents are from a PEM file, or else None.
+ """
+ offset = raw_key_input.find('-----BEGIN ')
+ if offset != -1:
+ return raw_key_input[offset:]
+ else:
+ return None
+
def _urlsafe_b64encode(raw_bytes):
return base64.urlsafe_b64encode(raw_bytes).rstrip('=')
diff --git a/tests/data/create-private-keys.sh b/tests/data/create-private-keys.sh
old mode 100644
new mode 100755
index b21cbdb..aaec580
--- a/tests/data/create-private-keys.sh
+++ b/tests/data/create-private-keys.sh
@@ -7,3 +7,7 @@
openssl pkcs12 -export -out privatekey.p12 \
-inkey privatekey.pem -in publickey.pem \
-name "key" -passout pass:notasecret
+
+openssl pkcs12 -in privatekey.p12 \
+ -nodes -nocerts -passout pass:notasecret \
+ -passin pass:notasecret > pem_from_pkcs12.pem
\ No newline at end of file
diff --git a/tests/data/pem_from_pkcs12.pem b/tests/data/pem_from_pkcs12.pem
new file mode 100644
index 0000000..2d77e10
--- /dev/null
+++ b/tests/data/pem_from_pkcs12.pem
@@ -0,0 +1,32 @@
+Bag Attributes
+ friendlyName: key
+ localKeyID: 22 7E 04 FC 64 48 20 83 1E C1 BD E3 F5 2F 44 7D EA 99 A5 BC
+Key Attributes: <No Attributes>
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDh6PSnttDsv+vi
+tUZTP1E3hVBah6PUGDWZhYgNiyW8quTWCmPvBmCR2YzuhUrY5+CtKP8UJOQico+p
+oJHSAPsrzSr6YsGs3c9SQOslBmm9Fkh9/f/GZVTVZ6u5AsUmOcVvZ2q7Sz8Vj/aR
+aIm0EJqRe9cQ5vvN9sg25rIv4xKwIZJ1VixKWJLmpCmDINqn7xvl+ldlUmSr3aGt
+w21uSDuEJhQlzO3yf2FwJMkJ9SkCm9oVDXyl77OnKXj5bOQ/rojbyGeIxDJSUDWE
+GKyRPuqKi6rSbwg6h2G/Z9qBJkqM5NNTbGRIFz/9/LdmmwvtaqCxlLtD7RVEryAp
++qTGDk5hAgMBAAECggEBAMYYfNDEYpf4A2SdCLne/9zrrfZ0kphdUkL48MDPj5vN
+TzTRj6f9s5ixZ/+QKn3hdwbguCx13QbH5mocP0IjUhyqoFFHYAWxyyaZfpjM8tO4
+QoEYxby3BpjLe62UXESUzChQSytJZFwIDXKcdIPNO3zvVzufEJcfG5no2b9cIvsG
+Dy6J1FNILWxCtDIqBM+G1B1is9DhZnUDgn0iKzINiZmh1I1l7k/4tMnozVIKAfwo
+f1kYjG/d2IzDM02mTeTElz3IKeNriaOIYTZgI26xLJxTkiFnBV4JOWFAZw15X+yR
++DrjGSIkTfhzbLa20Vt3AFM+LFK0ZoXT2dRnjbYPjQECgYEA+9XJFGwLcEX6pl1p
+IwXAjXKJdju9DDn4lmHTW0Pbw25h1EXONwm/NPafwsWmPll9kW9IwsxUQVUyBC9a
+c3Q7rF1e8ai/qqVFRIZof275MI82ciV2Mw8Hz7FPAUyoju5CvnjAEH4+irt1VE/7
+SgdvQ1gDBQFegS69ijdz+cOhFxkCgYEA5aVoseMy/gIlsCvNPyw9+Jz/zBpKItX0
+jGzdF7lhERRO2cursujKaoHntRckHcE3P/Z4K565bvVq+VaVG0T/BcBKPmPHrLmY
+iuVXidltW7Jh9/RCVwb5+BvqlwlC470PEwhqoUatY/fPJ74srztrqJHvp1L29FT5
+sdmlJW8YwokCgYAUa3dMgp5C0knKp5RY1KSSU5E11w4zKZgwiWob4lq1dAPWtHpO
+GCo63yyBHImoUJVP75gUw4Cpc4EEudo5tlkIVuHV8nroGVKOhd9/Rb5K47Hke4kk
+Brn5a0Ues9qPDF65Fw1ryPDFSwHufjXAAO5SpZZJF51UGDgiNvDedbBgMQKBgHSk
+t7DjPhtW69234eCckD2fQS5ijBV1p2lMQmCygGM0dXiawvN02puOsCqDPoz+fxm2
+DwPY80cw0M0k9UeMnBxHt25JMDrDan/iTbxu++T/jlNrdebOXFlxlI5y3c7fULDS
+LZcNVzTXwhjlt7yp6d0NgzTyJw2ju9BiREfnTiRBAoGBAOPHrTOnPyjO+bVcCPTB
+WGLsbBd77mVPGIuL0XGrvbVYPE8yIcNbZcthd8VXL/38Ygy8SIZh2ZqsrU1b5WFa
+XUMLnGEODSS8x/GmW3i3KeirW5OxBNjfUzEF4XkJP8m41iTdsQEXQf9DdUY7X+CB
+VL5h7N0VstYhGgycuPpcIUQa
+-----END PRIVATE KEY-----
diff --git a/tests/test_oauth2client_jwt.py b/tests/test_oauth2client_jwt.py
index 4af0030..8038520 100644
--- a/tests/test_oauth2client_jwt.py
+++ b/tests/test_oauth2client_jwt.py
@@ -61,7 +61,15 @@
self.verifier = crypt.OpenSSLVerifier
def test_sign_and_verify(self):
- private_key = datafile('privatekey.%s' % self.format)
+ self._check_sign_and_verify('privatekey.%s' % self.format)
+
+ def test_sign_and_verify_from_converted_pkcs12(self):
+ """Tests that following instructions to convert from PKCS12 to PEM works."""
+ if self.format == 'pem':
+ self._check_sign_and_verify('pem_from_pkcs12.pem')
+
+ def _check_sign_and_verify(self, private_key_file):
+ private_key = datafile(private_key_file)
public_key = datafile('publickey.pem')
signer = self.signer.from_string(private_key)