This page describes the Python3 interface to the core CryptoSys PKI Pro library. Latest version 22.0.0 released 2023-10-23.
Introduction | Installation | System requirements | Using in the Python REPL | Documentation | Classes and methods X-ref | Test files and examples | Another example | A further example | Running the tests | Revision history | Contact
We really like using Python because you can easily do calculations in its REPL environment (read-eval-print loop) without having to compile each time.
For a handy quick guide to the methods available see the Python CryptoSys PKI Cross Reference.
> pip install cryptosyspki Collecting cryptosyspki Installing collected packages: cryptosyspki Successfully installed cryptosyspki-22.0.0
Note: You can safely ignore the message "Using legacy 'setup.py install' for cryptosyspki, since package 'wheel' is not installed". The pypi/pip people are getting their knickers in a twist about this. We'll look into it further when the situation is clearer.
To upgrade if an older version is already installed:
> pip install --upgrade cryptosyspki
cryptosyspki-x.x.x.zip
from the Python Package Index (PyPi).pip install cryptosyspki-22.0.0.zipwhere "x.x.x" is the current version number.
Windows only. Python 3 must be installed on your system. CryptoSys PKI Pro v22.0.0 or above must also be installed. This is available from https://www.cryptosys.net/pki/.
Here are some simple examples calling CryptoSys PKI Pro functions from the Python REPL.
>>> from cryptosyspki import * >>> Gen.version() # "hello world!" for CryptoSys PKI 220000 >>> Hash.hex_from_data(b'abc') # compute SHA-1 hash in hex of 'abc' as bytes 'a9993e364706816aba3e25717850c26c9cd0d89d' >>> Hash.hex_from_string('abc', Hash.Alg.SHA256) # same but over a string and using SHA-256 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad' >>> h = Hash.data(b'abc') # h is a byte array (bytes->bytes) >>> print(Cnv.tohex(h)) # display the byte array in hex A9993E364706816ABA3E25717850C26C9CD0D89D
If you don't like import *
and find cryptosyspki
a bit long to type each time, try
>>> import cryptosyspki as pki >>> pki.Gen.version() # Underlying core PKI dll 220000 >>> pki.__version__ # cryptosyspki.py package '22.0.0.0000'
Note that pki.Gen.version()
gives the version number of the underlying core CryptoSys PKI DLL, and
pki.__version__
gives the version of the Python cryptosyspki package.
>>> Hash.hex_from_data('abc') # Woops! String type is not a bytes array in py 3 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python38\lib\site-packages\cryptosyspki.py", line 1876, in hex_from_data nc = _dipki.HASH_HexFromBytes(None, 0, bytes(data), len(data), alg) TypeError: string argument without an encoding >>> Hash.hex_from_data('abc'.encode()) # OK - string encoded into bytes array 'a9993e364706816aba3e25717850c26c9cd0d89d' >>> Hash.hex_from_data(b'abc') # Or simply write directly as a byte array 'a9993e364706816aba3e25717850c26c9cd0d89d'
There is set of examples in the test script test/test_pki.py
provided with the latest download from PyPi
(download the file cryptosyspki-x.x.x.zip and unzip it to get the files and test directory structure).
Here are the latest required test files for the tests.
You can cut and paste the parts you want to get started writing your own code.
Here are some of the most interesting examples.
Rsa.make_keys()
.Rsa.save_enc_key()
.Rsa.encrypt()
.Ecc.make_keys()
.Sig.sign_data()
.X509.make_cert()
.X509.query_cert()
.Cms.make_envdata()
.Cms.make_sigdata()
.Cms.make_comprdata()
.Cipher.encrypt()
.Hash.data()
.Hmac.data()
.# encrypt-text.py # Encrypt a string with a random IV in CBC mode using AES-128 # Output result as base64-encoding of IV+CT. # Then parse the result and decrypt. # [2019-12-28] v12.2 Updated for Python 3. # [2017-08-12] v11.2 Changed ``Rng.bytes`` to ``Rng.bytestring`` from cryptosyspki import * # Shared secret key k = Cnv.fromhex("112233445566778899aabbccddeeff00") print("KEY:", Cnv.tohex(k)) # Message to encrypt (bytes) m = b"Feather-footed through the plashy fen passes the questing vole." print("PT:", m) print("PT:", Cnv.tohex(m)) # Block length in bytes for AES-128 blen = Cipher.blockbytes(Cipher.Alg.AES128) # Generate a random IV of the correct length (NB different each time) iv = Rng.bytestring(blen) print("IV:", Cnv.tohex(iv)) # Do the business - Encrypt it. ct = Cipher.encrypt(m, k, alg=Cipher.Alg.AES128, mode=Cipher.Mode.CBC, iv=iv) print("CT:", Cnv.tohex(ct)) # Concatenate IV+ciphertext bytearrays cto = iv + ct print("IV|CT:", Cnv.tohex(cto)) # Output in base64 ct64 = Cnv.tobase64(cto) print("OUTPUT:", ct64) # Send output to recipient... print("Send to recipient...") #------------------------------- print("\nRecipient receives input...") print("INPUT:", ct64) # Recipient receives encoded data as input. # Recipient knows a) the shared secret key, # b) the algorithm is AES-128-CBC and # c) the data is in the form IV|CT. # Decode the base64 input to a byte array cto = Cnv.frombase64(ct64) # Parse the message - the first blocklen bytes are the IV iv = cto[:Cipher.blockbytes(Cipher.Alg.AES128)] ct = cto[Cipher.blockbytes(Cipher.Alg.AES128):] print("IV:", Cnv.tohex(iv)) print("CT:", Cnv.tohex(ct)) # Decrypt pt = Cipher.decrypt(ct, k, iv=iv, algmodepad="aes128/cbc/pkcs5") print("PT:", Cnv.tohex(pt)) # Display as text print("PT:", pt)
Typical output (IV and ciphertext will be different each time).
KEY: 112233445566778899AABBCCDDEEFF00 PT: b'Feather-footed through the plashy fen passes the questing vole.' PT: 466561746865722D666F6F746564207468726F7567682074686520706C617368792066656E2070617373657320746865207175657374696E6720766F6C652E IV: F63A311A9354D3C1B8B0A5DB1C1341DC CT: BA7606992B93B638EDC4C93EBC06C67894B395EF39F7086D0D4CBDE44FC5103B398788F6885FDE676CE370389E7F132529C9041D2C6857B89767F544542EB147 IV|CT: F63A311A9354D3C1B8B0A5DB1C1341DCBA7606992B93B638EDC4C93EBC06C67894B395EF39F7086D0D4CBDE44FC5103B398788F6885FDE676CE370389E7F132529C9041D2C6857B89767F544542EB147 OUTPUT: 9joxGpNU08G4sKXbHBNB3Lp2Bpkrk7Y47cTJPrwGxniUs5XvOfcIbQ1MveRPxRA7OYeI9ohf3mds43A4nn8TJSnJBB0saFe4l2f1RFQusUc= Send to recipient... Recipient receives input... INPUT: 9joxGpNU08G4sKXbHBNB3Lp2Bpkrk7Y47cTJPrwGxniUs5XvOfcIbQ1MveRPxRA7OYeI9ohf3mds43A4nn8TJSnJBB0saFe4l2f1RFQusUc= IV: F63A311A9354D3C1B8B0A5DB1C1341DC CT: BA7606992B93B638EDC4C93EBC06C67894B395EF39F7086D0D4CBDE44FC5103B398788F6885FDE676CE370389E7F132529C9041D2C6857B89767F544542EB147 PT: 466561746865722D666F6F746564207468726F7567682074686520706C617368792066656E2070617373657320746865207175657374696E6720766F6C652E PT: b'Feather-footed through the plashy fen passes the questing vole.'
See Create a SignatureValue from a DigestValue
which shows how to create a base64-encoded signature suitable for a <SignatureValue>
element
from the base64-encoded digest value and the signer's private key.
The tests in test/test_pki.py
demonstrate the use of each of the classes and methods using known test vectors where possible.
The script and test files are available in the download from PyPi.
The output should look something similar to this.
This particular test code requires a directory structure with a subdirectory work/
in the same folder
as the test_pki.py
file which should contain all the required test files.
The test function then creates a temporary subdirectory which is deleted automatically.
(If you lose the test files, copies are available separately in the file pkiPythonTestFiles.zip
.)
test/ test_pki.py # this module work/ # this _must_ exist <all required test files> pki.tmp.XXXXXXXX/ # created by `setup_temp_dir()` <copy of all required test files> <files created by tests>
This structure is already setup in the distribution file, so unzip the file cryptosyspki-x.x.x.zip
and open a command line prompt in the test
sub-directory.
Then do one of the following.
python test_pki.py
py.test -v ... test_pki.py::test_version PASSED test_pki.py::test_error_lookup PASSED test_pki.py::test_cnv PASSED test_pki.py::test_cnv_utf8 PASSED test_pki.py::test_cipher PASSED test_pki.py::test_cipher_block PASSED ...See †
test_pki.py
using IDLE and select Run > Run Module (F5)
.See Revision History
For more information, or to comment on this page, please send us a message.
This page last updated 23 October 2023