diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/api.tex | 13 | ||||
-rw-r--r-- | doc/building.tex | 149 | ||||
-rw-r--r-- | doc/examples/tss.cpp | 38 | ||||
-rw-r--r-- | doc/log.txt | 11 | ||||
-rw-r--r-- | doc/python.tex | 68 | ||||
-rwxr-xr-x | doc/python/cipher.py | 44 | ||||
-rwxr-xr-x | doc/python/cryptobox.py | 34 | ||||
-rwxr-xr-x | doc/python/nisttest.py | 61 | ||||
-rw-r--r-- | doc/python/results.txt | 60 | ||||
-rwxr-xr-x | doc/python/rng_test.py | 22 | ||||
-rwxr-xr-x | doc/python/rsa.py | 31 | ||||
-rwxr-xr-x | doc/scripts/configure.pl | 2 | ||||
-rw-r--r-- | doc/tutorial.tex | 4 |
13 files changed, 480 insertions, 57 deletions
diff --git a/doc/api.tex b/doc/api.tex index d86fa79e2..556e76aa0 100644 --- a/doc/api.tex +++ b/doc/api.tex @@ -1360,12 +1360,18 @@ private key: \begin{verbatim} namespace PKCS8 { - PKCS8_PrivateKey* load_key(DataSource& in, const User_Interface& ui); - PKCS8_PrivateKey* load_key(DataSource& in, std::string passphrase = ""); + PKCS8_PrivateKey* load_key(DataSource& in, + RandomNumberGenerator& rng, + const User_Interface& ui); + PKCS8_PrivateKey* load_key(DataSource& in, + RandomNumberGenerator& rng, + std::string passphrase = ""); PKCS8_PrivateKey* load_key(const std::string& filename, + RandomNumberGenerator& rng, const User_Interface& ui); PKCS8_PrivateKey* load_key(const std::string& filename, + RandomNumberGenerator& rng, const std::string& passphrase = ""); } \end{verbatim} @@ -1384,6 +1390,9 @@ using. You can think of it as a user interface interface. The default \type{User\_Interface} is actually very dumb, and effectively acts just like the versions taking the \type{std::string}. +All versions need access to a \type{RandomNumberGenerator} in order to +perform probabilistic tests on the loaded key material. + After loading a key, you can use \function{dynamic\_cast} to find out what operations it supports, and use it appropriately. Remember to \function{delete} it once you are done with it. diff --git a/doc/building.tex b/doc/building.tex index aa4435c14..f58786e76 100644 --- a/doc/building.tex +++ b/doc/building.tex @@ -13,7 +13,7 @@ \title{\textbf{Botan Build Guide}} \author{Jack Lloyd \\ \texttt{[email protected]}} -\date{2008-11-24} +\date{2009-10-09} \newcommand{\filename}[1]{\texttt{#1}} \newcommand{\module}[1]{\texttt{#1}} @@ -41,61 +41,58 @@ POSIX (such as VMS, MacOS 9, OS/390, OS/400, ...) are not supported by the build system, primarily due to lack of access. Please contact the maintainer if you would like to build Botan on such a system. -Botan's build is controlled by configure.pl, which is a Perl -script. Perl 5.6 or later is required. +Botan's build is controlled by configure.py, which is a Python +script. Python 2.4 or later is required. \section{For the Impatient} \begin{verbatim} -$ ./configure.pl [--prefix=/some/directory] +$ ./configure.py [--prefix=/some/directory] $ make $ make install \end{verbatim} Or using \verb|nmake|, if you're compiling on Windows with Visual C++. On platforms that do not understand the '\#!' convention for -beginning script files, or that have Perl installed in an unusual -spot, you might need to prefix the \texttt{configure.pl} command with -\texttt{perl} or \texttt{/path/to/perl}. +beginning script files, or that have Python installed in an unusual +spot, you might need to prefix the \texttt{configure.py} command with +\texttt{python} or \texttt{/path/to/python}. \section{Building the Library} -The first step is to run \filename{configure.pl}, which is a Perl +The first step is to run \filename{configure.py}, which is a Python script that creates various directories, config files, and a Makefile -for building everything. The script requires at least Perl 5.6; any -later version should also work. +for building everything. The script requires at least Python 2.4; any +later version of Python 2.x should also work. The script will attempt to guess what kind of system you are trying to compile for (and will print messages telling you what it guessed). You can override this process by passing the options \verb|--cc|, -\verb|--os|, and \verb|--cpu| -- acceptable values are printed if -you run \verb|configure.pl| with \verb|--help|. +\verb|--os|, and \verb|--cpu|. You can pass basically anything reasonable with \verb|--cpu|: the script knows about a large number of different architectures, their -sub-models, and common aliases for them. The script does not display -all the possibilities in its help message because there are simply too -many entries. You should only select the 64-bit version of a CPU (such -as ``sparc64'' or ``mips64'') if your operating system knows how to -handle 64-bit object code -- a 32-bit kernel on a 64-bit CPU will -generally not like 64-bit code. +sub-models, and common aliases for them. You should only select the +64-bit version of a CPU (such as ``sparc64'' or ``mips64'') if your +operating system knows how to handle 64-bit object code -- a 32-bit +kernel on a 64-bit CPU will generally not like 64-bit code. By default the script tries to figure out what will work on your -system, and use that. It will print a display at the end showing -which algorithms have and have not been abled. For instance on one -system we might see the line: +system, and use that. It will print a display at the end showing which +algorithms have and have not been enabled. For instance on one system +we might see lines like: \begin{verbatim} - (loading): entropy: [beos_stats] buf_es [cryptoapi_rng] - dev_random egd proc_walk unix_procs [win32_stats] + INFO: Skipping mod because CPU incompatible - asm_amd64 mp_amd64 mp_asm64 sha1_amd64 + INFO: Skipping mod because OS incompatible - cryptoapi_rng win32_stats + INFO: Skipping mod because compiler incompatible - mp_ia32_msvc + INFO: Skipping mod because loaded on request only - bzip2 gnump openssl qt_mutex zlib \end{verbatim} -The names listed in brackets are disabled, the others are -enabled. Here we see the list of entropy sources which are going to be -compiled into Botan. Since this particular line comes when Botan was -configuring for a Linux system, the Win32 and BeOS specific modules -were disabled, while modules that use Unix APIs and /dev/random are -built. +The ones that are 'loaded on request only' have to be explicitly asked +for, because they rely on third party libraries which your system +might not have. For instance to enable zlib support, add +\verb|--with-zlib| to your invocation of \verb|configure.py|. You can control which algorithms and modules are built using the options ``\verb|--enable-modules=MODS|'' and @@ -104,20 +101,6 @@ options ``\verb|--enable-modules=MODS|'' and Modules not listed on the command line will simply be loaded if needed or if configured to load by default. -Not all OSes or CPUs have specific support in -\filename{configure.pl}. If the CPU architecture of your system isn't -supported by \filename{configure.pl}, use 'generic'. This setting -disables machine-specific optimization flags. Similarly, setting OS to -'generic' disables things which depend greatly on OS support -(specifically, shared libraries). - -However, it's impossible to guess which options to give to a system -compiler. Thus, if you want to compile Botan with a compiler which -\filename{configure.pl} does not support, you will need to tell it how -that compiler works. This is done by adding a new file in the -directory \filename{src/build-data/cc}; the existing files should put you -in the right direction. - The script tries to guess what kind of makefile to generate, and it almost always guesses correctly (basically, Visual C++ uses NMAKE with Windows commands, and everything else uses Unix make with POSIX @@ -128,14 +111,12 @@ commonly used by Windows compilers. To add a new variant (eg, a build script for VMS), you will need to create a new template file in \filename{src/build-data/makefile}. -\pagebreak - \subsection{POSIX / Unix} The basic build procedure on Unix and Unix-like systems is: \begin{verbatim} - $ ./configure.pl [--enable-modules=<list>] [--cc=CC] + $ ./configure.py [--enable-modules=<list>] [--cc=CC] $ make # You may need to set your LD_LIBRARY_PATH or equivalent for ./check to run $ make check # optional, but a good idea @@ -148,9 +129,9 @@ found within your PATH. The \verb|make install| target has a default directory in which it will install Botan (typically \verb|/usr/local|). You can override this by using the \texttt{--prefix} argument to -\filename{configure.pl}, like so: +\filename{configure.py}, like so: -\verb|./configure.pl --prefix=/opt <other arguments>| +\verb|./configure.py --prefix=/opt <other arguments>| On some systems shared libraries might not be immediately visible to the runtime linker. For example, on Linux you may have to edit @@ -163,10 +144,10 @@ to include the directory that the Botan libraries were installed into. The situation is not much different here. We'll assume you're using Visual C++ (for Cygwin, the Unix instructions are probably more relevant). You need to -have a copy of Perl installed, and have both Perl and Visual C++ in your path. +have a copy of Python installed, and have both Python and Visual C++ in your path. \begin{verbatim} - > perl configure.pl --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU] + > python configure.py --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU] > nmake > nmake check # optional, but recommended \end{verbatim} @@ -244,7 +225,7 @@ environment in a different directory. \subsection{Local Configuration} You may want to do something peculiar with the configuration; to -support this there is a flag to \filename{configure.pl} called +support this there is a flag to \filename{configure.py} called \texttt{--with-local-config=<file>}. The contents of the file are inserted into \filename{build/build.h} which is (indirectly) included into every Botan header and source file. @@ -395,4 +376,70 @@ is less of a problem - only the developer needs to worry about it. As long as they can remember where they installed Botan, they just have to set the appropriate flags in their Makefile/project file. +\pagebreak + +\section{Language Wrappers} + +\subsection{Building the Python wrappers} + +The Python wrappers for Botan use Boost.Python, so you must have Boost +installed. To build the wrappers, add the flag + +\verb|--use-boost-python| + +to \verb|configure.py|. This will create a second makefile, +\verb|Makefile.python|, with instructions for building the Python +module. After building the library, execute + +\begin{verbatim} +$ make -f Makefile.python +\end{verbatim} + +to build the module. Currently only Unix systems are supported, and +the Makefile assumes that the version of Python you want to build +against is the same one you used to run \verb|configure.py|. + +To install the module, use the \verb|install| target. + +Examples of using the Python module can be seen in \filename{doc/python} + +\subsection{Building the Perl XS wrappers} + +To build the Perl XS wrappers, change your directory to +\filename{src/wrap/perl-xs} and run \verb|perl Makefile.PL|, then run +\verb|make| to build the module and \verb|make test| to run the test +suite. + +\begin{verbatim} +$ perl Makefile.PL +Checking if your kit is complete... +Looks good +Writing Makefile for Botan +$ make +cp Botan.pm blib/lib/Botan.pm +AutoSplitting blib/lib/Botan.pm (blib/lib/auto/Botan) +/usr/bin/perl5.8.8 /usr/lib64/perl5/5.8.8/ExtUtils/xsubpp [...] +g++ -c -Wno-write-strings -fexceptions -g [...] +Running Mkbootstrap for Botan () +chmod 644 Botan.bs +rm -f blib/arch/auto/Botan/Botan.so +g++ -shared Botan.o -o blib/arch/auto/Botan/Botan.so \ + -lbotan -lbz2 -lpthread -lrt -lz \ + +chmod 755 blib/arch/auto/Botan/Botan.so +cp Botan.bs blib/arch/auto/Botan/Botan.bs +chmod 644 blib/arch/auto/Botan/Botan.bs +Manifying blib/man3/Botan.3pm +$ make test +PERL_DL_NONLAZY=1 /usr/bin/perl5.8.8 [...] +t/base64......ok +t/filt........ok +t/hex.........ok +t/oid.........ok +t/pipe........ok +t/x509cert....ok +All tests successful. +Files=6, Tests=83, 0 wallclock secs ( 0.08 cusr + 0.02 csys = 0.10 CPU) +\end{verbatim} + \end{document} diff --git a/doc/examples/tss.cpp b/doc/examples/tss.cpp new file mode 100644 index 000000000..1881ffe24 --- /dev/null +++ b/doc/examples/tss.cpp @@ -0,0 +1,38 @@ +#include <botan/botan.h> +#include <botan/tss.h> +#include <iostream> +#include <stdio.h> + +namespace { + +void print(const Botan::SecureVector<Botan::byte>& r) + { + for(Botan::u32bit i = 0; i != r.size(); ++i) + printf("%02X", r[i]); + printf("\n"); + } + +} + +int main() + { + using namespace Botan; + + LibraryInitializer init; + + AutoSeeded_RNG rng; + + byte id[16]; + for(int i = 0; i != 16; ++i) + id[i] = i; + + const byte S2[] = { 0xDE, 0xAD, 0xCA, 0xFE, 0xBA, 0xBE, 0xBE, 0xEF }; + + std::vector<RTSS_Share> shares = + RTSS_Share::split(4, 6, S2, sizeof(S2), id, rng); + + for(size_t i = 0; i != shares.size(); ++i) + std::cout << i << " = " << shares[i].to_string() << "\n"; + + print(RTSS_Share::reconstruct(shares)); + } diff --git a/doc/log.txt b/doc/log.txt index c0193c235..9ebf3a2ad 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,9 +1,14 @@ -* 1.9.1-pre, 2009-??-?? - - Enable SSE2 optimizations under Visual C++ - - Add runtime checking for SSE2 availability +* 1.9.1-rc1, 2009-10-09 + - Better support for Python and Perl wrappers - Add an implementation of Blue Midnight Wish (Round 2 tweak version) + - Add threshold secret sharing (draft-mcgrew-tss-02) + - Add runtime cpu feature detection for x86/x86-64 + - Add code for general runtime self testing for hashes, MACs, and ciphers + - Add support for GNU/Hurd + - New parsing code for SCAN algorithm names - Alter Skein-512 to match the tweaked 1.2 specification + - Enable SSE2 optimizations under Visual C++ * 1.9.0, 2009-09-09 - Add support for parallel invocation of block ciphers where possible diff --git a/doc/python.tex b/doc/python.tex new file mode 100644 index 000000000..afdd66b6a --- /dev/null +++ b/doc/python.tex @@ -0,0 +1,68 @@ +\documentclass{article} + +\setlength{\textwidth}{6.5in} % 1 inch side margins +\setlength{\textheight}{9in} % ~1 inch top and bottom margins + +\setlength{\headheight}{0in} +\setlength{\topmargin}{0in} +\setlength{\headsep}{0in} + +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0in} + +\title{\textbf{Botan Python Interface Documentation}} +\author{Jack Lloyd \\ + \texttt{[email protected]}} +\date{2009/10/10} + +\newcommand{\filename}[1]{\texttt{#1}} +\newcommand{\manpage}[2]{\texttt{#1}(#2)} + +\newcommand{\macro}[1]{\texttt{#1}} + +\newcommand{\function}[1]{\textbf{#1}} +\newcommand{\type}[1]{\texttt{#1}} +\renewcommand{\arg}[1]{\textsl{#1}} +\newcommand{\variable}[1]{\textsl{#1}} + +\begin{document} + +\maketitle + +\tableofcontents + +\parskip=5pt +\pagebreak + +\section{Ciphers} + +Botan's Python interface provides a generic interface to any cipher +supported by the library. The class \type{botan.Cipher} takes three +arguments, all strings: first, the name of the algorith, second the +direction (which can be either ``encrypt'' or ``decrypt''), and +lastly, the key to use. For instance + +\begin{verbatim} + encryptor = botan.Cipher("AES-128/EAX", "encrypt", key) +\end{verbatim} + +creates an object that will encrypt and authenticate messages using +the EAX mode of operation using the AES cipher. To use this object, +call the \function{cipher} function with two arguments - the input +to encrypt, and the IV to use: + +\begin{verbatim} + ciphertext = encryptor.cipher(input, salt) +\end{verbatim} + + +\subsection{Cryptobox} + + +\subsection{RNGs} + +\section{RSA} + + + +\end{document} diff --git a/doc/python/cipher.py b/doc/python/cipher.py new file mode 100755 index 000000000..1be2759ae --- /dev/null +++ b/doc/python/cipher.py @@ -0,0 +1,44 @@ +#!/usr/bin/python + +import botan +import sys + +def encrypt(input, passphrase): + rng = botan.RandomNumberGenerator() + + # Use as both EAX IV and PBKDF2 salt + salt = rng.gen_random(10) + + iterations = 10000 + output_size = 16 + + key = botan.pbkdf2(passphrase, salt, iterations, output_size, "SHA-1") + + encryptor = botan.Cipher("AES-128/EAX", "encrypt", key) + + ciphertext = encryptor.cipher(input, salt) + return (ciphertext, salt) + +def decrypt(input, salt, passphrase): + iterations = 10000 + output_size = 16 + + key = botan.pbkdf2(passphrase, salt, iterations, output_size, "SHA-1") + + decryptor = botan.Cipher("AES-128/EAX", "decrypt", key) + + return decryptor.cipher(input, salt) + +def main(args = None): + if args is None: + args = sys.argv + + passphrase = args[1] + input = ''.join(open(args[2]).readlines()) + + (ciphertext, salt) = encrypt(input, passphrase) + + print decrypt(ciphertext, salt, passphrase) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/doc/python/cryptobox.py b/doc/python/cryptobox.py new file mode 100755 index 000000000..1968b40e1 --- /dev/null +++ b/doc/python/cryptobox.py @@ -0,0 +1,34 @@ +#!/usr/bin/python + +import sys +import botan + +def main(args = None): + if args is None: + args = sys.argv + + if len(args) != 3: + raise Exception("Bad usage") + + password = args[1] + input = ''.join(open(args[2]).readlines()) + + rng = botan.RandomNumberGenerator() + + ciphertext = botan.cryptobox_encrypt(input, password, rng) + + print ciphertext + + plaintext = '' + + try: + plaintext = botan.cryptobox_decrypt(ciphertext, password + 'FAIL') + except Exception, e: + print "Oops -- ", e + + plaintext = botan.cryptobox_decrypt(ciphertext, password) + + print plaintext + +if __name__ == '__main__': + sys.exit(main()) diff --git a/doc/python/nisttest.py b/doc/python/nisttest.py new file mode 100755 index 000000000..3ea8fda0f --- /dev/null +++ b/doc/python/nisttest.py @@ -0,0 +1,61 @@ +#!/usr/bin/python + +import sys, os, botan +from os.path import join; + +def validate(ca_certs, certs, crls, ee_certs): + store = botan.X509_Store() + for cert in certs: + if cert not in ee_certs: + store.add_cert(botan.X509_Certificate(cert), cert in ca_certs) + + for crl in crls: + r = store.add_crl(botan.X509_CRL(crl)) + if r != botan.verify_result.verified: + return r + + for ee in ee_certs: + r = store.validate(botan.X509_Certificate(ee)) + if r != botan.verify_result.verified: + return r + + return botan.verify_result.verified + +def run_test(files, rootdir, testname, expected): + crls = [join(rootdir,x) for x in files if x.endswith(".crl")] + certs = [join(rootdir,x) for x in files if x.endswith(".crt")] + end_entity = [x for x in certs if x.find("end.crt") != -1] + ca_certs = [x for x in certs if x.find("root.crt") != -1] + + print "%s..." % testname, + + result = validate(ca_certs, certs, crls, end_entity) + result = repr(result).replace('botan._botan.verify_result.', '') + + if result != expected: + print "FAILED: got %s, expected %s" % (result, expected) + else: + print "passed" + +def main(): + def load_results(file): + results = {} + for line in open(file, 'r'): + line = line[0:line.find('#')].strip() + if line: + test,result = line.split(' ') + results[test] = result + return results + + results = load_results('results.txt') + + for root, dirs, files in os.walk('../../checks/nist_tests/tests'): + if files: + thistest = root[root.rfind('/')+1:] + if thistest in results: + run_test(files, root, thistest, results[thistest]) + else: + print "%s... skipping - no expected result set" % thistest + +if __name__ == "__main__": + sys.exit(main()) diff --git a/doc/python/results.txt b/doc/python/results.txt new file mode 100644 index 000000000..7a3824001 --- /dev/null +++ b/doc/python/results.txt @@ -0,0 +1,60 @@ +# This is the file of expected results for nisttest.py +test01 verified +test02 signature_error +test03 signature_error +test04 verified +test05 cert_not_yet_valid +test06 cert_not_yet_valid +test07 verified +test08 cert_not_yet_valid +test09 cert_has_expired +test10 cert_has_expired +test11 cert_has_expired +test12 verified +test13 cert_issuer_not_found +test14 cert_issuer_not_found +test15 verified +test16 verified +test17 verified +test18 verified +# changed; should be no_revocation_data_available, but I don't want to +# force people to use CRLs +test19 verified +test20 cert_is_revoked +test21 cert_is_revoked +test22 ca_cert_not_for_cert_issuer +test23 ca_cert_not_for_cert_issuer +test24 verified +test25 ca_cert_not_for_cert_issuer +test26 verified +test27 verified +test28 ca_cert_not_for_cert_issuer +test29 ca_cert_not_for_cert_issuer +test30 verified +test31 ca_cert_not_for_crl_issuer +test32 ca_cert_not_for_crl_issuer +test33 verified +test54 cert_chain_too_long +test55 cert_chain_too_long +test56 verified +test57 verified +test58 cert_chain_too_long +test59 cert_chain_too_long +test60 cert_chain_too_long +test61 cert_chain_too_long +test62 verified +test63 verified +test64 signature_error +# changed; I have no idea why this test is supposed to fail +test65 verified +test66 crl_issuer_not_found +# changed; one of the CRLs has an unknown creator, so we fail +# prior to getting to the end-entity check +test67 crl_issuer_not_found +test68 cert_is_revoked +test69 cert_is_revoked +test70 cert_is_revoked +test71 cert_is_revoked +test72 crl_has_expired +test73 crl_has_expired +test74 verified diff --git a/doc/python/rng_test.py b/doc/python/rng_test.py new file mode 100755 index 000000000..06c79b84e --- /dev/null +++ b/doc/python/rng_test.py @@ -0,0 +1,22 @@ +#!/usr/bin/python + +import botan + +rng = botan.RandomNumberGenerator() + +print "name", rng.name() + +rng.add_entropy("blah") + +print "random 16", rng.gen_random(16).encode("hex") +print "random 32", rng.gen_random(32).encode("base64"), + +rng.reseed() + +for i in range(0, 10): + print rng.gen_random_byte(), +print + +rng.add_entropy("blah") + +print "random 16", rng.gen_random(16).encode("hex") diff --git a/doc/python/rsa.py b/doc/python/rsa.py new file mode 100755 index 000000000..15ffcffa3 --- /dev/null +++ b/doc/python/rsa.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + +import botan + +rng = botan.RandomNumberGenerator() + +rsa_priv = botan.RSA_PrivateKey(768, rng) + +print rsa_priv.to_string() +print int(rsa_priv.get_N()) +print int(rsa_priv.get_E()) + + +rsa_pub = botan.RSA_PublicKey(rsa_priv) + +key = rng.gen_random(20) + +ciphertext = rsa_pub.encrypt(key, 'EME1(SHA-1)', rng) + +print ciphertext.encode('hex') + +plaintext = rsa_priv.decrypt(ciphertext, 'EME1(SHA-1)') + +print plaintext == key + + +signature = rsa_priv.sign(key, 'EMSA4(SHA-256)', rng) + +key = key.replace('a', 'b') + +print rsa_pub.verify(key, signature, 'EMSA4(SHA-256)') diff --git a/doc/scripts/configure.pl b/doc/scripts/configure.pl index bd7e41a3e..9415d5a42 100755 --- a/doc/scripts/configure.pl +++ b/doc/scripts/configure.pl @@ -1582,6 +1582,8 @@ sub read_info_files { foreach my $file (dir_list($dir)) { my $fullpath = File::Spec->catfile($dir, $file); + $file =~ s/.txt//; + trace("reading $fullpath"); %{$allinfo{$file}} = &$func($file, $fullpath); } diff --git a/doc/tutorial.tex b/doc/tutorial.tex index 244461994..9229cb853 100644 --- a/doc/tutorial.tex +++ b/doc/tutorial.tex @@ -626,9 +626,11 @@ This is very similar to reading raw public keys, with the difference that the key may be encrypted with a user passphrase: \begin{verbatim} + // rng is a RandomNumberGenerator, like AutoSeeded_RNG + DataSource_Stream somefile("somefile"); std::string a_passphrase = /* get from the user */ - PKCS8_PrivateKey* key = PKCS8::load_key(somefile, a_passphrase); + PKCS8_PrivateKey* key = PKCS8::load_key(somefile, rng, a_passphrase); \end{verbatim} You can, by the way, convert a \type{PKCS8\_PrivateKey} to a |