Skip to content

Commit 89d832a

Browse files
committed
Correctly identify PEM files generated from PKCS12 files in oauth2client.
Reviewed in https://codereview.appspot.com/19380043/. Fixes issue googleapis#249.
1 parent 4d50cd6 commit 89d832a

File tree

4 files changed

+69
-6
lines changed

4 files changed

+69
-6
lines changed

oauth2client/crypt.py

+24-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class AppIdentityError(Exception):
3838
try:
3939
from OpenSSL import crypto
4040

41-
4241
class OpenSSLVerifier(object):
4342
"""Verifies the signature on a message."""
4443

@@ -125,8 +124,9 @@ def from_string(key, password='notasecret'):
125124
Raises:
126125
OpenSSL.crypto.Error if the key can't be parsed.
127126
"""
128-
if key.startswith('-----BEGIN '):
129-
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, key)
127+
parsed_pem_key = _parse_pem_key(key)
128+
if parsed_pem_key:
129+
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, parsed_pem_key)
130130
else:
131131
pkey = crypto.load_pkcs12(key, password).get_privatekey()
132132
return OpenSSLSigner(pkey)
@@ -230,8 +230,9 @@ def from_string(key, password='notasecret'):
230230
Raises:
231231
NotImplementedError if they key isn't in PEM format.
232232
"""
233-
if key.startswith('-----BEGIN '):
234-
pkey = RSA.importKey(key)
233+
parsed_pem_key = _parse_pem_key(key)
234+
if parsed_pem_key:
235+
pkey = RSA.importKey(parsed_pem_key)
235236
else:
236237
raise NotImplementedError(
237238
'PKCS12 format is not supported by the PyCrpto library. '
@@ -256,6 +257,24 @@ def from_string(key, password='notasecret'):
256257
'PyOpenSSL, or PyCrypto 2.6 or later')
257258

258259

260+
def _parse_pem_key(raw_key_input):
261+
"""Identify and extract PEM keys.
262+
263+
Determines whether the given key is in the format of PEM key, and extracts
264+
the relevant part of the key if it is.
265+
266+
Args:
267+
raw_key_input: The contents of a private key file (either PEM or PKCS12).
268+
269+
Returns:
270+
string, The actual key if the contents are from a PEM file, or else None.
271+
"""
272+
offset = raw_key_input.find('-----BEGIN ')
273+
if offset != -1:
274+
return raw_key_input[offset:]
275+
else:
276+
return None
277+
259278
def _urlsafe_b64encode(raw_bytes):
260279
return base64.urlsafe_b64encode(raw_bytes).rstrip('=')
261280

tests/data/create-private-keys.sh

100644100755
+4
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
77
openssl pkcs12 -export -out privatekey.p12 \
88
-inkey privatekey.pem -in publickey.pem \
99
-name "key" -passout pass:notasecret
10+
11+
openssl pkcs12 -in privatekey.p12 \
12+
-nodes -nocerts -passout pass:notasecret \
13+
-passin pass:notasecret > pem_from_pkcs12.pem

tests/data/pem_from_pkcs12.pem

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
Bag Attributes
2+
friendlyName: key
3+
localKeyID: 22 7E 04 FC 64 48 20 83 1E C1 BD E3 F5 2F 44 7D EA 99 A5 BC
4+
Key Attributes: <No Attributes>
5+
-----BEGIN PRIVATE KEY-----
6+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDh6PSnttDsv+vi
7+
tUZTP1E3hVBah6PUGDWZhYgNiyW8quTWCmPvBmCR2YzuhUrY5+CtKP8UJOQico+p
8+
oJHSAPsrzSr6YsGs3c9SQOslBmm9Fkh9/f/GZVTVZ6u5AsUmOcVvZ2q7Sz8Vj/aR
9+
aIm0EJqRe9cQ5vvN9sg25rIv4xKwIZJ1VixKWJLmpCmDINqn7xvl+ldlUmSr3aGt
10+
w21uSDuEJhQlzO3yf2FwJMkJ9SkCm9oVDXyl77OnKXj5bOQ/rojbyGeIxDJSUDWE
11+
GKyRPuqKi6rSbwg6h2G/Z9qBJkqM5NNTbGRIFz/9/LdmmwvtaqCxlLtD7RVEryAp
12+
+qTGDk5hAgMBAAECggEBAMYYfNDEYpf4A2SdCLne/9zrrfZ0kphdUkL48MDPj5vN
13+
TzTRj6f9s5ixZ/+QKn3hdwbguCx13QbH5mocP0IjUhyqoFFHYAWxyyaZfpjM8tO4
14+
QoEYxby3BpjLe62UXESUzChQSytJZFwIDXKcdIPNO3zvVzufEJcfG5no2b9cIvsG
15+
Dy6J1FNILWxCtDIqBM+G1B1is9DhZnUDgn0iKzINiZmh1I1l7k/4tMnozVIKAfwo
16+
f1kYjG/d2IzDM02mTeTElz3IKeNriaOIYTZgI26xLJxTkiFnBV4JOWFAZw15X+yR
17+
+DrjGSIkTfhzbLa20Vt3AFM+LFK0ZoXT2dRnjbYPjQECgYEA+9XJFGwLcEX6pl1p
18+
IwXAjXKJdju9DDn4lmHTW0Pbw25h1EXONwm/NPafwsWmPll9kW9IwsxUQVUyBC9a
19+
c3Q7rF1e8ai/qqVFRIZof275MI82ciV2Mw8Hz7FPAUyoju5CvnjAEH4+irt1VE/7
20+
SgdvQ1gDBQFegS69ijdz+cOhFxkCgYEA5aVoseMy/gIlsCvNPyw9+Jz/zBpKItX0
21+
jGzdF7lhERRO2cursujKaoHntRckHcE3P/Z4K565bvVq+VaVG0T/BcBKPmPHrLmY
22+
iuVXidltW7Jh9/RCVwb5+BvqlwlC470PEwhqoUatY/fPJ74srztrqJHvp1L29FT5
23+
sdmlJW8YwokCgYAUa3dMgp5C0knKp5RY1KSSU5E11w4zKZgwiWob4lq1dAPWtHpO
24+
GCo63yyBHImoUJVP75gUw4Cpc4EEudo5tlkIVuHV8nroGVKOhd9/Rb5K47Hke4kk
25+
Brn5a0Ues9qPDF65Fw1ryPDFSwHufjXAAO5SpZZJF51UGDgiNvDedbBgMQKBgHSk
26+
t7DjPhtW69234eCckD2fQS5ijBV1p2lMQmCygGM0dXiawvN02puOsCqDPoz+fxm2
27+
DwPY80cw0M0k9UeMnBxHt25JMDrDan/iTbxu++T/jlNrdebOXFlxlI5y3c7fULDS
28+
LZcNVzTXwhjlt7yp6d0NgzTyJw2ju9BiREfnTiRBAoGBAOPHrTOnPyjO+bVcCPTB
29+
WGLsbBd77mVPGIuL0XGrvbVYPE8yIcNbZcthd8VXL/38Ygy8SIZh2ZqsrU1b5WFa
30+
XUMLnGEODSS8x/GmW3i3KeirW5OxBNjfUzEF4XkJP8m41iTdsQEXQf9DdUY7X+CB
31+
VL5h7N0VstYhGgycuPpcIUQa
32+
-----END PRIVATE KEY-----

tests/test_oauth2client_jwt.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,15 @@ def setUp(self):
6161
self.verifier = crypt.OpenSSLVerifier
6262

6363
def test_sign_and_verify(self):
64-
private_key = datafile('privatekey.%s' % self.format)
64+
self._check_sign_and_verify('privatekey.%s' % self.format)
65+
66+
def test_sign_and_verify_from_converted_pkcs12(self):
67+
"""Tests that following instructions to convert from PKCS12 to PEM works."""
68+
if self.format == 'pem':
69+
self._check_sign_and_verify('pem_from_pkcs12.pem')
70+
71+
def _check_sign_and_verify(self, private_key_file):
72+
private_key = datafile(private_key_file)
6573
public_key = datafile('publickey.pem')
6674

6775
signer = self.signer.from_string(private_key)

0 commit comments

Comments
 (0)