forked from hbldh/pybankid
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Better certificate splitting methods. More extensive tests with mock. Documentation updated. Removed unnecessary Python 3 text conversions.
- Loading branch information
Showing
11 changed files
with
232 additions
and
166 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
""" | ||
:mod:`bankid.certutils` -- Certificate Utilities | ||
================================================ | ||
Created by hbldh <[email protected]> | ||
Created on 2016-04-10 | ||
""" | ||
|
||
from __future__ import division | ||
from __future__ import print_function | ||
from __future__ import unicode_literals | ||
from __future__ import absolute_import | ||
|
||
import os | ||
import tempfile | ||
import subprocess | ||
import requests | ||
|
||
_TEST_CERT_PASSWORD = 'qwerty123' | ||
_TEST_CERT_URL = "https://www.bankid.com/assets/bankid/rp/FPTestcert2_20150818_102329.pfx" | ||
|
||
|
||
def create_bankid_test_server_cert_and_key(destination_path): | ||
"""Fetch the P12 certificate from BankID servers, split it into | ||
a certificate part and a key part and save them as separate files, | ||
stored in PEM format. | ||
:param destination_path: The directory to save certificate and key files to. | ||
:type destination_path: str | ||
:returns: The path tuple ``(cert_path, key_path)``. | ||
:rtype: tuple | ||
""" | ||
|
||
# Fetch P12 certificate and store in temporary folder. | ||
cert_tmp_path = os.path.join(tempfile.gettempdir(), | ||
os.path.basename(_TEST_CERT_URL)) | ||
r = requests.get(_TEST_CERT_URL) | ||
with open(cert_tmp_path, 'wb') as f: | ||
f.write(r.content) | ||
|
||
certificate, key = split_certificate(cert_tmp_path, | ||
destination_path, | ||
password=_TEST_CERT_PASSWORD) | ||
# Try to remove temporary file. | ||
try: | ||
os.remove(cert_tmp_path) | ||
except: | ||
pass | ||
|
||
# Return path tuples. | ||
return certificate, key | ||
|
||
|
||
def split_certificate(certificate_path, destination_folder, password=None): | ||
"""Splits a PKCS12 certificate into Base64-encoded DER certificate and key. | ||
This method splits a potentially password-protected | ||
`PKCS12 <https://en.wikipedia.org/wiki/PKCS_12>`_ certificate | ||
(format ``.p12`` or ``.pfx``) into one certificate and one key part, both in | ||
`pem <https://en.wikipedia.org/wiki/X.509#Certificate_filename_extensions>`_ | ||
format. | ||
:returns: Tuple of certificate and key string data. | ||
:rtype: tuple | ||
""" | ||
try: | ||
p = subprocess.Popen(["openssl", 'version'], stdout=subprocess.PIPE) | ||
sout, serr = p.communicate() | ||
if not sout.decode().lower().startswith('openssl'): | ||
raise NotImplementedError( | ||
"OpenSSL executable could not be found. " | ||
"Splitting cannot be performed.") | ||
except: | ||
raise NotImplementedError( | ||
"OpenSSL executable could not be found. " | ||
"Splitting cannot be performed.") | ||
|
||
# Paths to output files. | ||
out_cert_path = os.path.join(os.path.abspath( | ||
os.path.expanduser(destination_folder)), 'certificate.pem') | ||
out_key_path = os.path.join(os.path.abspath( | ||
os.path.expanduser(destination_folder)), 'key.pem') | ||
|
||
# Use openssl for converting to pem format. | ||
pipeline_1 = [ | ||
'openssl', 'pkcs12', | ||
'-in', "{0}".format(certificate_path), | ||
'-passin' if password is not None else '', | ||
'pass:{0}'.format(password) if password is not None else '', | ||
'-out', "{0}".format(out_cert_path), | ||
'-clcerts', '-nokeys' | ||
] | ||
p = subprocess.Popen(list(filter(None, pipeline_1)), | ||
stdout=subprocess.PIPE, | ||
stderr=subprocess.PIPE) | ||
p.communicate() | ||
pipeline_2 = [ | ||
'openssl', 'pkcs12', | ||
'-in', "{0}".format(certificate_path), | ||
'-passin' if password is not None else '', | ||
'pass:{0}'.format(password) if password is not None else '', | ||
'-out', "{0}".format(out_key_path), | ||
'-nocerts', '-nodes' | ||
] | ||
p = subprocess.Popen(list(filter(None, pipeline_2)), | ||
stdout=subprocess.PIPE, | ||
stderr=subprocess.PIPE) | ||
p.communicate() | ||
|
||
# Return path tuples. | ||
return out_cert_path, out_key_path | ||
|
||
|
||
def main(): | ||
paths = create_bankid_test_server_cert_and_key(os.path.expanduser('~')) | ||
print('Saved certificate as {0}'.format(paths[0])) | ||
print('Saved key as {0}'.format(paths[1])) | ||
return paths | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
===================================== | ||
.. moduleauthor:: hbldh <[email protected]> | ||
Created on 2014-09-09, 16:55 | ||
""" | ||
|
@@ -106,7 +107,6 @@ def sign(self, user_visible_data, personal_number=None, **kwargs): | |
warnings.warn("Requirement Alternatives option is not tested.", BankIDWarning) | ||
|
||
try: | ||
|
||
out = self.client.service.Sign( | ||
userVisibleData=six.text_type(base64.b64encode(six.b(user_visible_data)), encoding='utf-8'), | ||
personalNumber=personal_number, **kwargs) | ||
|
@@ -197,7 +197,7 @@ def open(self, request): | |
resp = self.requests_session.get(request.url, | ||
data=request.message, | ||
headers=request.headers) | ||
result = six.BytesIO(six.b(resp.content.decode('utf-8'))) | ||
result = six.BytesIO(resp.content) | ||
return result | ||
|
||
def send(self, request): | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
=============================================== | ||
.. moduleauthor:: hbldh <[email protected]> | ||
Created on 2014-09-10, 08:29 | ||
""" | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
.. _certutils: | ||
|
||
Certificate methods | ||
=================== | ||
|
||
Converting/splitting certificates | ||
--------------------------------- | ||
|
||
To convert your production certificate from PKCS_12 format to two ``pem``, | ||
ready to be used by PyBankID, one can do the following: | ||
|
||
.. code-block:: python | ||
In [1]: from bankid.certutils import split_certificate | ||
In [2]: split_certificate('/path/to/certificate.p12', | ||
'/destination/folder/', | ||
'password_for_certificate_p12') | ||
Out [2]: ('/destination/folder/certificate.pem', | ||
'/destination/folder/key.pem') | ||
It can also be done via regular OpenSSL terminal calls: | ||
|
||
.. code-block:: bash | ||
openssl pkcs12 -in /path/to/certificate.p12 -passin pass:password_for_certificate_p12 -out /destination/folder/certificate.pem -clcerts -nokeys | ||
openssl pkcs12 -in /path/to/certificate.p12 -passin pass:password_for_certificate_p12 -out /destination/folder/key.pem -nocerts -nodes | ||
.. note:: | ||
This also removes the password from the private key in the certificate, | ||
which is a requirement for using the PyBankID package in an automated way. | ||
|
||
Test server certificate | ||
----------------------- | ||
|
||
There is a test certificate available on `BankID Technical Information webpage | ||
<https://www.bankid.com/bankid-i-dina-tjanster/rp-info>`_, which can be used for | ||
testing authorization and signing. The | ||
:py:func:`bankid.certutils.create_bankid_test_server_cert_and_key` in the | ||
:py:mod:`bankid.certutils` module fetches that test certificate, splits it | ||
into one certificate and one key part and converts it from | ||
`.p12 or .pfx <https://en.wikipedia.org/wiki/PKCS_12>`_ format to | ||
`pem <https://en.wikipedia.org/wiki/X.509#Certificate_filename_extensions>`_. | ||
These can then be used for testing purposes, by sending in ``test_server=True`` | ||
keyword in the :py:class:`~BankIDClient`. | ||
|
||
|
||
API | ||
--- | ||
|
||
.. automodule:: bankid.certutils | ||
:members: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,7 +33,7 @@ the BankID servers. | |
usage | ||
client | ||
exceptions | ||
testcert | ||
certutils | ||
|
||
|
||
Indices and tables | ||
|
Oops, something went wrong.