├── .buildinfo ├── .coveragerc ├── .github └── workflows │ └── python-app.yml ├── .gitignore ├── .gitmodules ├── ChangeLog.rst ├── LICENSING.rst ├── MANIFEST.in ├── Makefile ├── README.rst ├── docs ├── Makefile ├── asymmetric.rst ├── conf.py ├── digest.rst ├── index.rst ├── mac.rst ├── random.rst ├── streaming.rst └── symmetric.rst ├── requirements ├── docs.txt ├── prod.txt ├── setup.txt └── test.txt ├── scripts └── build_ffi.py ├── setup.py ├── tests ├── certs │ ├── server-cert.der │ ├── server-cert.pem │ ├── server-key.der │ ├── server-key.pem │ └── server-keyPub.pem ├── test_aesgcmstream.py ├── test_asn.py ├── test_chacha20poly1305.py ├── test_ciphers.py ├── test_hashes.py ├── test_mldsa.py ├── test_mlkem.py ├── test_pwdbased.py └── test_random.py ├── tox.ini ├── windows ├── README.md ├── fips_ready │ └── user_settings.h └── non_fips │ └── user_settings.h └── wolfcrypt ├── __init__.py ├── _version.py ├── asn.py ├── ciphers.py ├── exceptions.py ├── hashes.py ├── pwdbased.py ├── random.py └── utils.py /.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 1a398edf40df95da3c0bed562b58dc22 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = 3 | */_build_ffi.py 4 | */_build_wolfssl.py 5 | */_ffi.py -------------------------------------------------------------------------------- /.github/workflows/python-app.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Python application 5 | 6 | on: 7 | push: 8 | branches: [ '*' ] 9 | pull_request: 10 | branches: [ '*' ] 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | build: 17 | 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | - name: Set up Python 3.10 23 | uses: actions/setup-python@v3 24 | with: 25 | python-version: "3.10" 26 | - name: Install dependencies 27 | run: | 28 | python -m pip install --upgrade pip 29 | pip install flake8 pytest tox 30 | pip install -r requirements/test.txt 31 | # Won't pass flake8 yet 32 | # - name: Lint with flake8 33 | # run: | 34 | # # stop the build if there are Python syntax errors or undefined names 35 | # flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 36 | # # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 37 | # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 38 | - name: Test with tox 39 | run: | 40 | tox 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | *.a 9 | *.dll 10 | wolfcrypt/_ffi.* 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | .pytest_cache 46 | nosetests.xml 47 | coverage.xml 48 | *,cover 49 | .hypothesis/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | 58 | # Sphinx documentation 59 | docs/_build/ 60 | 61 | # PyBuilder 62 | target/ 63 | 64 | # pyenv python configuration file 65 | .python-version 66 | 67 | # macos `make dist` venvs 68 | venv_* 69 | 70 | # code editor preferences 71 | .vscode 72 | .tags 73 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/wolfssl"] 2 | path = lib/wolfssl 3 | url = https://github.com/wolfssl/wolfssl 4 | -------------------------------------------------------------------------------- /ChangeLog.rst: -------------------------------------------------------------------------------- 1 | wolfCrypt-py Release 5.7.4 (Nov 13, 2024) 2 | ========================================== 3 | 4 | * Add support for ChaCha20-Poly1305 5 | * Update to wolfSSL version 5.7.4 6 | 7 | 8 | wolfCrypt-py Release 5.7.2 (Sep 6, 2024) 9 | ========================================== 10 | 11 | * Update to wolfSSL version 5.7.2 12 | 13 | 14 | wolfCrypt-py Release 5.6.6 (Jan 23, 2024) 15 | ========================================== 16 | 17 | * Update to wolfSSL version 5.6.6 18 | 19 | 20 | wolfCrypt-py Release 5.6.0 (May 2, 2022) 21 | ========================================== 22 | 23 | * Add user settings path for scripts/user_settings_asm.sh during cmake 24 | * Update to wolfSSL version 5.6.0 25 | 26 | 27 | wolfCrypt-py Release 5.5.4 (December 30, 2022) 28 | ========================================== 29 | 30 | * Update to wolfSSL version 5.5.4 31 | 32 | wolfCrypt-py Release 5.5.3 (November 7, 2022) 33 | ========================================== 34 | 35 | * Add ChangeLog file 36 | * Add optional hash_type parameter to RSA from_pem functions 37 | * Improve the RSA PSS code 38 | * Gate inclusion of wc_GenerateSeed in C wrapper on WC_RNG_SEED_CB_ENABLED 39 | * Make several improvements to the CFFI build process 40 | * Update to wolfSSL version 5.5.3 41 | 42 | 43 | wolfCrypt-py Release 5.4.0 (July 13, 2022) 44 | ========================================== 45 | 46 | New Features 47 | ------------ 48 | 49 | * Update to wolfCrypt 5.4.0 C library 50 | * Add GitHub Actions support, remove Travis CI 51 | 52 | Fixes 53 | ----- 54 | 55 | * Fixups for PyPi 56 | * Remove some of the CMake hack due to things moved into wolfSSL CMakeLists.txt 57 | 58 | wolfCrypt-py Release 5.3.0 (May 10, 2022) 59 | ========================================= 60 | 61 | New Features 62 | ------------ 63 | 64 | * Update to wolfCrypt 5.3.0 65 | * Build completely refactored to be more Python-like and easier to use 66 | * Added support for SHA3 67 | * Added support for ChaCha stream cipher 68 | * Add support for RSA private keys in PKCS #8 format 69 | * Add module pwdbased.py and expose wc_PBKDF2 70 | * Modifications to make wolfCrypt-py work with FIPS ready and FIPS v5 71 | * Add support for ed448 72 | * Add a pem_to_der function and support for PEM RSA keys 73 | * Add signature generation and verification 74 | * Enabled pwdbased by default 75 | * Windows support added 76 | * Added support for AES-CTR 77 | * Add support for AES GCM streaming 78 | * Add RSA OAEP and PSS padding 79 | * Add get_aad() function 80 | 81 | Fixes 82 | ----- 83 | 84 | * Documentation improvements 85 | 86 | -------------------------------------------------------------------------------- /LICENSING.rst: -------------------------------------------------------------------------------- 1 | Licensing 2 | --------- 3 | 4 | wolfSSL's software is available under two distinct licensing models: 5 | open source and standard commercial licensing. Please see the relevant 6 | section below for information on each type of license. 7 | 8 | Open Source 9 | ~~~~~~~~~~~ 10 | 11 | wolfCrypt and wolfSSL software are free software downloads and may be modified 12 | to the needs of the user as long as the user adheres to version two of the GPL 13 | License. The GPLv2 license can be found on the `gnu.org website 14 | `_. 15 | 16 | Commercial Licensing 17 | ~~~~~~~~~~~~~~~~~~~~ 18 | 19 | Businesses and enterprises who wish to incorporate wolfSSL products into 20 | proprietary appliances or other commercial software products for 21 | re-distribution must license commercial versions. Licenses are generally issued 22 | for one product and include unlimited royalty-free distribution. Custom 23 | licensing terms are also available at licensing@wolfssl.com. 24 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSING.rst 2 | include README.rst 3 | include ChangeLog.rst 4 | 5 | include scripts/build_ffi.py 6 | include windows/fips_ready/user_settings.h 7 | include windows/non_fips/user_settings.h 8 | 9 | recursive-include tests * 10 | recursive-include requirements * 11 | 12 | recursive-include docs *.rst conf.py Makefile 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean clean-test clean-pyc clean-build docs help 2 | .DEFAULT_GOAL := help 3 | define BROWSER_PYSCRIPT 4 | import os, webbrowser, sys 5 | try: 6 | from urllib import pathname2url 7 | except: 8 | from urllib.request import pathname2url 9 | 10 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) 11 | endef 12 | export BROWSER_PYSCRIPT 13 | 14 | define PRINT_HELP_PYSCRIPT 15 | import re, sys 16 | 17 | for line in sys.stdin: 18 | match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) 19 | if match: 20 | target, help = match.groups() 21 | print("%-20s %s" % (target, help)) 22 | endef 23 | export PRINT_HELP_PYSCRIPT 24 | BROWSER := python -c "$$BROWSER_PYSCRIPT" 25 | 26 | help: 27 | @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) 28 | 29 | clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts 30 | 31 | 32 | clean-build: ## remove build artifacts 33 | rm -fr build/ 34 | rm -fr dist/ 35 | rm -fr .eggs/ 36 | rm -fr wolfssl/_ffi* 37 | find . -name '*.egg-info' -exec rm -fr {} + 38 | find . -name '*.egg' -exec rm -f {} + 39 | -cd lib/wolfssl && make clean 40 | 41 | clean-pyc: ## remove Python file artifacts 42 | find . -name '*.pyc' -exec rm -f {} + 43 | find . -name '*.pyo' -exec rm -f {} + 44 | find . -name '*~' -exec rm -f {} + 45 | find . -name '__pycache__' -exec rm -fr {} + 46 | 47 | clean-test: ## remove test and coverage artifacts 48 | rm -fr .tox/ 49 | rm -f .coverage 50 | rm -fr htmlcov/ 51 | 52 | lint: ## check style with flake8 53 | flake8 src tests 54 | pylint src tests/* 55 | 56 | test: install ## run tests quickly with the default Python 57 | py.test tests 58 | 59 | check: test ## run tests quickly with the default Python 60 | 61 | test-all: ## run tests on every Python version with tox 62 | tox 63 | 64 | check-all: test-all ## run tests on every Python version with tox 65 | 66 | cov: install ## check code coverage quickly with the default Python 67 | py.test --cov-config .coveragerc --cov=wolfcrypt tests 68 | coverage report -m 69 | coverage html 70 | $(BROWSER) htmlcov/index.html 71 | 72 | docs: install ## generate Sphinx HTML documentation, including API docs 73 | $(MAKE) -C docs clean 74 | $(MAKE) -C docs html 75 | $(BROWSER) docs/_build/html/index.html 76 | 77 | doctest: install ## generate Sphinx HTML documentation, including API docs 78 | $(MAKE) -C docs clean 79 | $(MAKE) -C docs doctest 80 | 81 | servedocs: docs ## compile the docs watching for changes 82 | watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . 83 | 84 | dist: clean ## builds source and wheel package 85 | python setup.py sdist 86 | 87 | ./make/osx/build_wheels.sh 88 | 89 | ./make/manylinux1/build_wheels.sh 90 | 91 | ls -l dist 92 | 93 | release: ## package and upload a release 94 | twine upload dist/* 95 | 96 | install: clean ## install the package to the active Python's site-packages 97 | python setup.py install 98 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | wolfcrypt: the wolfSSL Crypto Engine 2 | ==================================== 3 | 4 | **wolfCrypt Python**, a.k.a. ``wolfcrypt`` is a Python module that encapsulates 5 | **wolfSSL's wolfCrypt API**. 6 | 7 | `wolfCrypt `_ is a 8 | lightweight, portable, C-language-based crypto library 9 | targeted at IoT, embedded, and RTOS environments primarily because of its size, 10 | speed, and feature set. It works seamlessly in desktop, enterprise, and cloud 11 | environments as well. It is the crypto engine behind `wolfSSL's embedded ssl 12 | library `_. 13 | 14 | Compiling 15 | --------- 16 | 17 | Windows 18 | ^^^^^^^ 19 | 20 | Install the following on Windows: 21 | 22 | * `CMake `_ 23 | * `Git `_ 24 | * `Python 3.9 `_ 25 | * `Build Tools for Visual Studio `_. This is in the "Tools for Visual Studio" section at the bottom of the page. The "Desktop development with C++" pack is needed from the installer. 26 | 27 | Then from the command line install tox and CFFI using: 28 | 29 | .. code-block:: sh 30 | 31 | pip install tox cffi 32 | 33 | You can then build the source distribution packages using: 34 | 35 | .. code-block:: sh 36 | 37 | python setup.py sdist 38 | 39 | 40 | Linux 41 | ^^^^^ 42 | 43 | The `setup.py` file covers most things you will need to do to build and install from source. As pre-requisites you will need to install either from your OS repository or pip. You'll also need the Python development package for your Python version: 44 | 45 | * `cffi` 46 | * `tox` 47 | * `pytest` 48 | 49 | To build a source package run `python setup.py sdist`, to build a wheel package run `python setup.py bdist_wheel`. To test the build run `tox`. The `tox` tests rely on Python 3.9 being installed, if you do not have this version we recommend using `pyenv` to install it. 50 | 51 | Installation 52 | ------------ 53 | 54 | We provide Python wheels (prebuilt binaries) for OSX 64 bits and Linux 64 bits: 55 | 56 | .. code-block:: bash 57 | 58 | $ pip install wolfcrypt 59 | 60 | To build wolfcrypt-py against a local installation of the native C wolfSSL 61 | library, use the USE_LOCAL_WOLFSSL variable. This variable should be 62 | 63 | wolfcrypt-py can be built against a local version of the native wolfSSL 64 | library by using pip with the USE_LOCAL_WOLFSSL variable. USE_LOCAL_WOLFSSL 65 | should be set equal to the installation path for the wolfSSL library: 66 | 67 | .. code-block:: bash 68 | 69 | $ USE_LOCAL_WOLFSSL=/path/to/wolfssl/install pip install . 70 | 71 | If building wolfcrypt-py against a local wolfSSL library, wolfcrypt-py 72 | will attempt to do native feature detection to enable/disable wolfcrypt-py 73 | features based on how native wolfSSL has been compiled. It uses the 74 | header to do feature detection. 75 | 76 | Testing 77 | ------- 78 | 79 | .. code-block:: python 80 | 81 | >>> from wolfcrypt.hashes import Sha256 82 | >>> Sha256('wolfcrypt').hexdigest() 83 | b'96e02e7b1cbcd6f104fe1fdb4652027a5505b68652b70095c6318f9dce0d1844' 84 | 85 | Testing ``wolfcrypt``'s source code with ``tox`` 86 | ------------------------------------------------ 87 | 88 | To run the unit tests in the source code, you'll need ``tox`` and a few other 89 | requirements. 90 | 91 | 1. Make sure that the testing requirements are installed: 92 | 93 | .. code-block:: console 94 | 95 | $ sudo -H pip install -r requirements/test.txt 96 | 97 | 98 | 2. Run ``tox``: 99 | 100 | .. code-block:: console 101 | 102 | $ tox 103 | ... 104 | _________________________________ summary _________________________________ 105 | py3: commands succeeded 106 | congratulations :) 107 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # You can set these variables from the command line. 22 | SPHINXOPTS = 23 | SPHINXBUILD = sphinx-build 24 | PAPER = 25 | BUILDDIR = _build 26 | 27 | # User-friendly check for sphinx-build 28 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 29 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) 30 | endif 31 | 32 | # Internal variables. 33 | PAPEROPT_a4 = -D latex_paper_size=a4 34 | PAPEROPT_letter = -D latex_paper_size=letter 35 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 36 | # the i18n builder cannot share the environment and doctrees with the others 37 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 38 | 39 | .PHONY: help 40 | help: 41 | @echo "Please use \`make ' where is one of" 42 | @echo " html to make standalone HTML files" 43 | @echo " dirhtml to make HTML files named index.html in directories" 44 | @echo " singlehtml to make a single large HTML file" 45 | @echo " pickle to make pickle files" 46 | @echo " json to make JSON files" 47 | @echo " htmlhelp to make HTML files and a HTML help project" 48 | @echo " qthelp to make HTML files and a qthelp project" 49 | @echo " applehelp to make an Apple Help Book" 50 | @echo " devhelp to make HTML files and a Devhelp project" 51 | @echo " epub to make an epub" 52 | @echo " epub3 to make an epub3" 53 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 54 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 55 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 56 | @echo " text to make text files" 57 | @echo " man to make manual pages" 58 | @echo " texinfo to make Texinfo files" 59 | @echo " info to make Texinfo files and run them through makeinfo" 60 | @echo " gettext to make PO message catalogs" 61 | @echo " changes to make an overview of all changed/added/deprecated items" 62 | @echo " xml to make Docutils-native XML files" 63 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 64 | @echo " linkcheck to check all external links for integrity" 65 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 66 | @echo " coverage to run coverage check of the documentation (if enabled)" 67 | @echo " dummy to check syntax errors of document sources" 68 | 69 | .PHONY: clean 70 | clean: 71 | rm -rf $(BUILDDIR)/* 72 | 73 | .PHONY: html 74 | html: 75 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 76 | @echo 77 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 78 | 79 | .PHONY: dirhtml 80 | dirhtml: 81 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 82 | @echo 83 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 84 | 85 | .PHONY: singlehtml 86 | singlehtml: 87 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 88 | @echo 89 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 90 | 91 | .PHONY: pickle 92 | pickle: 93 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 94 | @echo 95 | @echo "Build finished; now you can process the pickle files." 96 | 97 | .PHONY: json 98 | json: 99 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 100 | @echo 101 | @echo "Build finished; now you can process the JSON files." 102 | 103 | .PHONY: htmlhelp 104 | htmlhelp: 105 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 106 | @echo 107 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 108 | ".hhp project file in $(BUILDDIR)/htmlhelp." 109 | 110 | .PHONY: qthelp 111 | qthelp: 112 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 113 | @echo 114 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 115 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 116 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/wolfcrypt.qhcp" 117 | @echo "To view the help file:" 118 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/wolfcrypt.qhc" 119 | 120 | .PHONY: applehelp 121 | applehelp: 122 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 123 | @echo 124 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 125 | @echo "N.B. You won't be able to view it unless you put it in" \ 126 | "~/Library/Documentation/Help or install it in your application" \ 127 | "bundle." 128 | 129 | .PHONY: devhelp 130 | devhelp: 131 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 132 | @echo 133 | @echo "Build finished." 134 | @echo "To view the help file:" 135 | @echo "# mkdir -p $$HOME/.local/share/devhelp/wolfcrypt" 136 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/wolfcrypt" 137 | @echo "# devhelp" 138 | 139 | .PHONY: epub 140 | epub: 141 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 142 | @echo 143 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 144 | 145 | .PHONY: epub3 146 | epub3: 147 | $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 148 | @echo 149 | @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." 150 | 151 | .PHONY: latex 152 | latex: 153 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 154 | @echo 155 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 156 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 157 | "(use \`make latexpdf' here to do that automatically)." 158 | 159 | .PHONY: latexpdf 160 | latexpdf: 161 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 162 | @echo "Running LaTeX files through pdflatex..." 163 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 164 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 165 | 166 | .PHONY: latexpdfja 167 | latexpdfja: 168 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 169 | @echo "Running LaTeX files through platex and dvipdfmx..." 170 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 171 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 172 | 173 | .PHONY: text 174 | text: 175 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 176 | @echo 177 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 178 | 179 | .PHONY: man 180 | man: 181 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 182 | @echo 183 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 184 | 185 | .PHONY: texinfo 186 | texinfo: 187 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 188 | @echo 189 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 190 | @echo "Run \`make' in that directory to run these through makeinfo" \ 191 | "(use \`make info' here to do that automatically)." 192 | 193 | .PHONY: info 194 | info: 195 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 196 | @echo "Running Texinfo files through makeinfo..." 197 | make -C $(BUILDDIR)/texinfo info 198 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 199 | 200 | .PHONY: gettext 201 | gettext: 202 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 203 | @echo 204 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 205 | 206 | .PHONY: changes 207 | changes: 208 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 209 | @echo 210 | @echo "The overview file is in $(BUILDDIR)/changes." 211 | 212 | .PHONY: linkcheck 213 | linkcheck: 214 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 215 | @echo 216 | @echo "Link check complete; look for any errors in the above output " \ 217 | "or in $(BUILDDIR)/linkcheck/output.txt." 218 | 219 | .PHONY: doctest 220 | doctest: 221 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 222 | @echo "Testing of doctests in the sources finished, look at the " \ 223 | "results in $(BUILDDIR)/doctest/output.txt." 224 | 225 | .PHONY: coverage 226 | coverage: 227 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 228 | @echo "Testing of coverage in the sources finished, look at the " \ 229 | "results in $(BUILDDIR)/coverage/python.txt." 230 | 231 | .PHONY: xml 232 | xml: 233 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 234 | @echo 235 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 236 | 237 | .PHONY: pseudoxml 238 | pseudoxml: 239 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 240 | @echo 241 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 242 | 243 | .PHONY: dummy 244 | dummy: 245 | $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy 246 | @echo 247 | @echo "Build finished. Dummy builder generates no files." 248 | -------------------------------------------------------------------------------- /docs/asymmetric.rst: -------------------------------------------------------------------------------- 1 | Asymmetric Key Algorithms 2 | ========================= 3 | 4 | .. module:: wolfcrypt.ciphers 5 | 6 | **Asymmetric key algorithms** are encryption algorithms that use **a pair 7 | of cryptographic keys**, one for data encryption and signing and the other 8 | one for data decryption and signature verification. 9 | 10 | ``wolfcrypt`` provides access to the following **Asymmetric Key Ciphers**: 11 | 12 | RSA 13 | --- 14 | 15 | .. autoclass:: RsaPublic 16 | :members: 17 | :inherited-members: 18 | 19 | .. autoclass:: RsaPrivate 20 | :members: 21 | :inherited-members: 22 | 23 | **Example:** 24 | 25 | >>> from wolfcrypt.ciphers import RsaPrivate, RsaPublic 26 | >>> from wolfcrypt.utils import h2b 27 | >>> 28 | >>> private = "3082025C02010002818100BC730EA849F374A2A9EF18A5DA559921F9C8ECB36D" \ 29 | ... + "48E53535757737ECD161905F3ED9E4D5DF94CAC1A9D719DA86C9E84DC4613682" \ 30 | ... + "FEABAD7E7725BB8D11A5BC623AA838CC39A20466B4F7F7F3AADA4D020EBB5E8D" \ 31 | ... + "6948DC77C9280E22E96BA426BA4CE8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B" \ 32 | ... + "3C67C8DC2700F6916865A902030100010281801397EAE8387825A25C04CE0D40" \ 33 | ... + "7C31E5C470CD9B823B5809863B665FDC3190F14FD5DB15DDDED73B9593311831" \ 34 | ... + "0E5EA3D6A21A716E81481C4BCFDB8E7A866132DCFB55C1166D279224458BF1B8" \ 35 | ... + "48B14B1DACDEDADD8E2FC291FBA5A96EF83A6AF1FD5018EF9FE7C3CA78EA56D3" \ 36 | ... + "D3725B96DD4E064E3AC3D9BE72B66507074C01024100FA47D47A7C923C55EF81" \ 37 | ... + "F041302DA3CF8F1CE6872705700DDF9835D6F18B382F24B5D084B6794F712994" \ 38 | ... + "5AF0646AACE772C6ED4D59983E673AF3742CF9611769024100C0C1820D0CEBC6" \ 39 | ... + "2FDC92F99D821A31E9E9F74BF282871CEE166AD11D188270F3C0B62FF6F3F71D" \ 40 | ... + "F18623C84EEB8F568E8FF5BFF1F72BB5CC3DC657390C1B54410241009D7E05DE" \ 41 | ... + "EDF4B7B2FBFC304B551DE32F0147966905CD0E2E2CBD8363B6AB7CB76DCA5B64" \ 42 | ... + "A7CEBE86DF3B53DE61D21EEBA5F637EDACAB78D94CE755FBD71199C102401898" \ 43 | ... + "1829E61E2739702168AC0A2FA172C121869538C65890A0579CBAE3A7B115C8DE" \ 44 | ... + "F61BC2612376EFB09D1C44BE1343396717C89DCAFBF545648B38822CF2810240" \ 45 | ... + "3989E59C195530BAB7488C48140EF49F7E779743E1B419353123759C3B44AD69" \ 46 | ... + "1256EE0061641666D37C742B15B4A2FEBF086B1A5D3F9012B105863129DBD9E2" 47 | >>> 48 | >>> prv = RsaPrivate(h2b(private)) 49 | >>> 50 | >>> public = "30819F300D06092A864886F70D010101050003818D0030818902818100BC730E" \ 51 | ... + "A849F374A2A9EF18A5DA559921F9C8ECB36D48E53535757737ECD161905F3ED9" \ 52 | ... + "E4D5DF94CAC1A9D719DA86C9E84DC4613682FEABAD7E7725BB8D11A5BC623AA8" \ 53 | ... + "38CC39A20466B4F7F7F3AADA4D020EBB5E8D6948DC77C9280E22E96BA426BA4C" \ 54 | ... + "E8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B3C67C8DC2700F6916865A90203010001" 55 | >>> 56 | >>> pub = RsaPublic(h2b(public)) 57 | >>> 58 | >>> plaintext = b"Everyone gets Friday off." 59 | >>> 60 | >>> ciphertext = pub.encrypt(plaintext) 61 | >>> ciphertext # doctest: +SKIP 62 | b'e\xb7\xc2\xad\x0c\x04.\xefU8\x17QB\x852\x03\x01\xef\xbe=\xb4\xaf\xaf\x97\x9e4\x96\x9f\xc3\x8e\x87\x9a8o$.|_e\x1d\xa2yi?\x83\x18\xf9Yr|\x1fQ\x1a\x18\x1e\xab\xd17\xc5\x8c\xae\x08c)\xbc\nIr\x8d\xc3\x88\x7f\xde\x1f\x1a^lB\r\xf1\xc0\xfd0\xdeA\xf3\xd2\xe5q\x9a0\xee\xb4,\x97\x80\xa4|U;\xe6\x11\xf0\xc2Q\x987\xe1>F\xf5\x14\x186@G~(Q\xf2;\xcb\x05\xee\x88\x0b\xd8\xa7' 63 | >>> 64 | >>> prv.decrypt(ciphertext) 65 | b'Everyone gets Friday off.' 66 | >>> 67 | >>> signature = prv.sign(plaintext) 68 | >>> signature # doctest: +SKIP 69 | b'~\xc4\xe65\x15\xb17\x7fX\xaf,\xc2lw\xbd\x8f\t\x9d\xbf\xac\xdez\x90\xb4\x9f\x1aM\x88#Z\xea\xcb\xa6\xdb\x99\xf55\xd0\xfe|Mu\xb6\xb79(t\x81+h\xf2\xcd\x88v\xa8\xbaM\x86\xcfk\xe8\xf3\x0b\xb8\x8ew\xda>\xf8\xd5[H\xeaAh\xc6\xdaQlo]\xdd\xf8w\xe7#M-\x12f\xae,\xdd\xa6d FP<;R\xa2\x96hJ\xee_\x1fh\xaa\xc8\xdfAJ\xa5\xdd\x05\xc4\x89\x0c\xd7\xa0C\xb7u"U\x03' 70 | >>> 71 | >>> pub.verify(signature) 72 | b'Everyone gets Friday off.' 73 | 74 | ECC 75 | --- 76 | 77 | .. autoclass:: EccPublic 78 | :members: 79 | :inherited-members: 80 | 81 | .. autoclass:: EccPrivate 82 | :members: 83 | :inherited-members: 84 | 85 | ML-KEM 86 | ------ 87 | 88 | .. autoclass:: MlKemType 89 | :show-inheritance: 90 | 91 | .. autoclass:: MlKemPublic 92 | :private-members: 93 | :members: 94 | :inherited-members: 95 | 96 | .. autoclass:: MlKemPrivate 97 | :members: 98 | :inherited-members: 99 | 100 | **Example:** 101 | 102 | >>> from wolfcrypt.ciphers import MlKemType, MlKemPrivate, MlKemPublic 103 | >>> 104 | >>> mlkem_type = MlKemType.ML_KEM_512 105 | >>> 106 | >>> mlkem_priv = MlKemPrivate.make_key(mlkem_type) 107 | >>> pub_key = mlkem_priv.encode_pub_key() 108 | >>> 109 | >>> mlkem_pub = MlKemPublic(mlkem_type) 110 | >>> mlkem_pub.decode_key(pub_key) 111 | >>> ss_send, ct = mlkem_pub.encapsulate() 112 | >>> 113 | >>> ss_recv = mlkem_priv.decapsulate(ct) 114 | >>> ss_send == ss_recv 115 | True 116 | 117 | ML-DSA 118 | ------ 119 | 120 | .. autoclass:: MlDsaType 121 | :show-inheritance: 122 | 123 | .. autoclass:: MlDsaPublic 124 | :private-members: 125 | :members: 126 | :inherited-members: 127 | 128 | .. autoclass:: MlDsaPrivate 129 | :members: 130 | :inherited-members: 131 | 132 | **Example:** 133 | 134 | >>> ######## Simple Usage 135 | >>> from wolfcrypt.ciphers import MlDsaType, MlDsaPrivate, MlDsaPublic 136 | >>> 137 | >>> mldsa_type = MlDsaType.ML_DSA_44 138 | >>> 139 | >>> mldsa_priv = MlDsaPrivate.make_key(mldsa_type) 140 | >>> pub_key = mldsa_priv.encode_pub_key() 141 | >>> 142 | >>> mldsa_pub = MlDsaPublic(mldsa_type) 143 | >>> mldsa_pub.decode_key(pub_key) 144 | >>> 145 | >>> msg = b"This is an example message" 146 | >>> 147 | >>> sig = mldsa_priv.sign(msg) 148 | >>> mldsa_pub.verify(sig, msg) 149 | True 150 | >>> 151 | >>> ######## Export and Import Keys 152 | >>> exported_key_pair = mldsa_priv.encode_priv_key(), mldsa_priv.encode_pub_key() 153 | >>> exported_pub_key = mldsa_pub.encode_key() 154 | >>> exported_key_pair[1] == exported_pub_key 155 | True 156 | >>> 157 | >>> mldsa_priv2 = MlDsaPrivate(mldsa_type) 158 | >>> mldsa_priv2.decode_key(exported_key_pair[0], exported_key_pair[1]) 159 | >>> 160 | >>> mldsa_pub2 = MlDsaPublic(mldsa_type) 161 | >>> mldsa_pub2.decode_key(exported_pub_key) 162 | >>> 163 | >>> sig2 = mldsa_priv2.sign(msg) 164 | >>> mldsa_pub2.verify(sig2, msg) 165 | True -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # wolfcrypt documentation build configuration file, created by 4 | # sphinx-quickstart on Fri Apr 29 16:47:53 2016. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | import wolfcrypt 16 | import sphinx_rtd_theme 17 | 18 | # If extensions (or modules to document with autodoc) are in another directory, 19 | # add these directories to sys.path here. If the directory is relative to the 20 | # documentation root, use os.path.abspath to make it absolute, like shown here. 21 | #sys.path.insert(0, os.path.abspath('.')) 22 | 23 | # -- General configuration ------------------------------------------------ 24 | 25 | # If your documentation needs a minimal Sphinx version, state it here. 26 | #needs_sphinx = '1.0' 27 | 28 | # Add any Sphinx extension module names here, as strings. They can be 29 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 30 | # ones. 31 | extensions = [ 32 | 'sphinx.ext.autodoc', 33 | 'sphinx.ext.doctest', 34 | 'sphinx.ext.coverage', 35 | 'sphinx.ext.viewcode', 36 | 'sphinx.ext.githubpages', 37 | ] 38 | 39 | # Add any paths that contain templates here, relative to this directory. 40 | templates_path = ['_templates'] 41 | 42 | # The suffix(es) of source filenames. 43 | # You can specify multiple suffix as a list of string: 44 | # source_suffix = ['.rst', '.md'] 45 | source_suffix = '.rst' 46 | 47 | # The encoding of source files. 48 | #source_encoding = 'utf-8-sig' 49 | 50 | # The master toctree document. 51 | master_doc = 'index' 52 | 53 | # General information about the project. 54 | project = u'wolfcrypt Python' 55 | copyright = u'2022, wolfSSL Inc. All rights reserved' 56 | author = u'wolfSSL' 57 | 58 | # The version info for the project you're documenting, acts as replacement for 59 | # |version| and |release|, also used in various other places throughout the 60 | # built documents. 61 | # 62 | version = release = wolfcrypt.__version__ 63 | 64 | # The language for content autogenerated by Sphinx. Refer to documentation 65 | # for a list of supported languages. 66 | # 67 | # This is also used if you do content translation via gettext catalogs. 68 | # Usually you set "language" from the command line for these cases. 69 | language = None 70 | 71 | # There are two options for replacing |today|: either, you set today to some 72 | # non-false value, then it is used: 73 | #today = '' 74 | # Else, today_fmt is used as the format for a strftime call. 75 | #today_fmt = '%B %d, %Y' 76 | 77 | # List of patterns, relative to source directory, that match files and 78 | # directories to ignore when looking for source files. 79 | # This patterns also effect to html_static_path and html_extra_path 80 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 81 | 82 | # The reST default role (used for this markup: `text`) to use for all 83 | # documents. 84 | #default_role = None 85 | 86 | # If true, '()' will be appended to :func: etc. cross-reference text. 87 | #add_function_parentheses = True 88 | 89 | # If true, the current module name will be prepended to all description 90 | # unit titles (such as .. function::). 91 | #add_module_names = True 92 | 93 | # If true, sectionauthor and moduleauthor directives will be shown in the 94 | # output. They are ignored by default. 95 | #show_authors = False 96 | 97 | # The name of the Pygments (syntax highlighting) style to use. 98 | pygments_style = 'sphinx' 99 | 100 | # A list of ignored prefixes for module index sorting. 101 | #modindex_common_prefix = [] 102 | 103 | # If true, keep warnings as "system message" paragraphs in the built documents. 104 | #keep_warnings = False 105 | 106 | # If true, `todo` and `todoList` produce output, else they produce nothing. 107 | todo_include_todos = False 108 | 109 | 110 | # -- Options for HTML output ---------------------------------------------- 111 | 112 | # The theme to use for HTML and HTML Help pages. See the documentation for 113 | # a list of builtin themes. 114 | html_theme = 'sphinx_rtd_theme' 115 | 116 | # Theme options are theme-specific and customize the look and feel of a theme 117 | # further. For a list of options available for each theme, see the 118 | # documentation. 119 | #html_theme_options = {} 120 | 121 | # Add any paths that contain custom themes here, relative to this directory. 122 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 123 | 124 | # The name for this set of Sphinx documents. 125 | # " v documentation" by default. 126 | #html_title = u'%s v%s' % (project, release) 127 | 128 | # A shorter title for the navigation bar. Default is the same as html_title. 129 | #html_short_title = None 130 | 131 | # The name of an image file (relative to this directory) to place at the top 132 | # of the sidebar. 133 | #html_logo = None 134 | 135 | # The name of an image file (relative to this directory) to use as a favicon of 136 | # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 137 | # pixels large. 138 | #html_favicon = None 139 | 140 | # Add any paths that contain custom static files (such as style sheets) here, 141 | # relative to this directory. They are copied after the builtin static files, 142 | # so a file named "default.css" will overwrite the builtin "default.css". 143 | html_static_path = ['_static'] 144 | 145 | # Add any extra paths that contain custom files (such as robots.txt or 146 | # .htaccess) here, relative to this directory. These files are copied 147 | # directly to the root of the documentation. 148 | #html_extra_path = [] 149 | 150 | # If not None, a 'Last updated on:' timestamp is inserted at every page 151 | # bottom, using the given strftime format. 152 | # The empty string is equivalent to '%b %d, %Y'. 153 | #html_last_updated_fmt = None 154 | 155 | # If true, SmartyPants will be used to convert quotes and dashes to 156 | # typographically correct entities. 157 | #html_use_smartypants = True 158 | 159 | # Custom sidebar templates, maps document names to template names. 160 | #html_sidebars = {} 161 | 162 | # Additional templates that should be rendered to pages, maps page names to 163 | # template names. 164 | #html_additional_pages = {} 165 | 166 | # If false, no module index is generated. 167 | #html_domain_indices = True 168 | 169 | # If false, no index is generated. 170 | #html_use_index = True 171 | 172 | # If true, the index is split into individual pages for each letter. 173 | #html_split_index = False 174 | 175 | # If true, links to the reST sources are added to the pages. 176 | #html_show_sourcelink = True 177 | 178 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 179 | #html_show_sphinx = True 180 | 181 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 182 | #html_show_copyright = True 183 | 184 | # If true, an OpenSearch description file will be output, and all pages will 185 | # contain a tag referring to it. The value of this option must be the 186 | # base URL from which the finished HTML is served. 187 | #html_use_opensearch = '' 188 | 189 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 190 | #html_file_suffix = None 191 | 192 | # Language to be used for generating the HTML full-text search index. 193 | # Sphinx supports the following languages: 194 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' 195 | # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' 196 | #html_search_language = 'en' 197 | 198 | # A dictionary with options for the search language support, empty by default. 199 | # 'ja' uses this config value. 200 | # 'zh' user can custom change `jieba` dictionary path. 201 | #html_search_options = {'type': 'default'} 202 | 203 | # The name of a javascript file (relative to the configuration directory) that 204 | # implements a search results scorer. If empty, the default will be used. 205 | #html_search_scorer = 'scorer.js' 206 | 207 | # Output file base name for HTML help builder. 208 | htmlhelp_basename = 'wolfcrypt-pydoc' 209 | 210 | # -- Options for LaTeX output --------------------------------------------- 211 | 212 | latex_elements = { 213 | # The paper size ('letterpaper' or 'a4paper'). 214 | #'papersize': 'letterpaper', 215 | 216 | # The font size ('10pt', '11pt' or '12pt'). 217 | #'pointsize': '10pt', 218 | 219 | # Additional stuff for the LaTeX preamble. 220 | #'preamble': '', 221 | 222 | # Latex figure (float) alignment 223 | #'figure_align': 'htbp', 224 | } 225 | 226 | # Grouping the document tree into LaTeX files. List of tuples 227 | # (source start file, target name, title, 228 | # author, documentclass [howto, manual, or own class]). 229 | latex_documents = [ 230 | (master_doc, 'wolfcrypt.tex', u'wolfcrypt Python Documentation', 231 | u'wolfSSL', 'manual'), 232 | ] 233 | 234 | # The name of an image file (relative to this directory) to place at the top of 235 | # the title page. 236 | #latex_logo = None 237 | 238 | # For "manual" documents, if this is true, then toplevel headings are parts, 239 | # not chapters. 240 | #latex_use_parts = False 241 | 242 | # If true, show page references after internal links. 243 | #latex_show_pagerefs = False 244 | 245 | # If true, show URL addresses after external links. 246 | #latex_show_urls = False 247 | 248 | # Documents to append as an appendix to all manuals. 249 | #latex_appendices = [] 250 | 251 | # If false, no module index is generated. 252 | #latex_domain_indices = True 253 | 254 | 255 | # -- Options for manual page output --------------------------------------- 256 | 257 | # One entry per manual page. List of tuples 258 | # (source start file, name, description, authors, manual section). 259 | man_pages = [ 260 | (master_doc, 'wolfcrypt', u'wolfcrypt Python Documentation', 261 | [author], 1) 262 | ] 263 | 264 | # If true, show URL addresses after external links. 265 | #man_show_urls = False 266 | 267 | 268 | # -- Options for Texinfo output ------------------------------------------- 269 | 270 | # Grouping the document tree into Texinfo files. List of tuples 271 | # (source start file, target name, title, author, 272 | # dir menu entry, description, category) 273 | texinfo_documents = [ 274 | (master_doc, 'wolfcrypt', u'wolfcrypt Python Documentation', 275 | author, 'wolfcrypt', 'One line description of project.', 276 | 'Miscellaneous'), 277 | ] 278 | 279 | # Documents to append as an appendix to all manuals. 280 | #texinfo_appendices = [] 281 | 282 | # If false, no module index is generated. 283 | #texinfo_domain_indices = True 284 | 285 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 286 | #texinfo_show_urls = 'footnote' 287 | 288 | # If true, do not generate a @detailmenu in the "Top" node's menu. 289 | #texinfo_no_detailmenu = False 290 | 291 | # Preserves the order of the members, doesn't sorts them alphabetically. 292 | autodoc_member_order = 'bysource' 293 | -------------------------------------------------------------------------------- /docs/digest.rst: -------------------------------------------------------------------------------- 1 | Message Digests 2 | =============== 3 | 4 | .. module:: wolfcrypt.hashes 5 | 6 | A **message digest** is the output of a **cryptographic hash function** 7 | containing a string of bytes created by a **one-way formula** using the 8 | original message as input. 9 | 10 | Message digests are designed to protect the integrity of a piece of data or 11 | media to detect changes and alterations to any part of a message. 12 | 13 | 14 | Hashing Classes 15 | --------------- 16 | 17 | Interface 18 | ~~~~~~~~~ 19 | 20 | All Hashing Functions available in this module implements the following 21 | interface: 22 | 23 | .. autoclass:: _Hash 24 | :members: 25 | :inherited-members: 26 | 27 | 28 | SHA-1 29 | ~~~~~ 30 | 31 | .. attention:: 32 | 33 | NIST has deprecated SHA-1 in favor of the SHA-2 variants. New applications 34 | are strongly suggested to use SHA-2 over SHA-1. 35 | 36 | .. autoclass:: Sha 37 | :members: 38 | :inherited-members: 39 | 40 | SHA-2 family 41 | ~~~~~~~~~~~~ 42 | 43 | .. autoclass:: Sha256 44 | :members: 45 | :inherited-members: 46 | 47 | 48 | .. autoclass:: Sha384 49 | :members: 50 | :inherited-members: 51 | 52 | 53 | .. autoclass:: Sha512 54 | :members: 55 | :inherited-members: 56 | 57 | 58 | Example 59 | ------- 60 | 61 | .. doctest:: 62 | 63 | >>> from wolfcrypt.hashes import Sha256 64 | >>> 65 | >>> s = Sha256() 66 | >>> s.update(b'wolf') 67 | >>> s.update(b'crypt') 68 | >>> s.digest() 69 | b'\x96\xe0.{\x1c\xbc\xd6\xf1\x04\xfe\x1f\xdbFR\x02zU\x05\xb6\x86R\xb7\x00\x95\xc61\x8f\x9d\xce\r\x18D' 70 | >>> s.hexdigest() 71 | b'96e02e7b1cbcd6f104fe1fdb4652027a5505b68652b70095c6318f9dce0d1844' 72 | >>> 73 | >>> s.update(b'rocks') 74 | >>> s.hexdigest() 75 | b'e1a50df419d65715c48316bdc6a6f7f0485f4b26c1b107228faf17988b61c83f' 76 | >>> 77 | >>> Sha256(b'wolfcryptrocks').hexdigest() 78 | b'e1a50df419d65715c48316bdc6a6f7f0485f4b26c1b107228faf17988b61c83f' 79 | >>> 80 | >>> Sha256.new(b'wolfcryptrocks').hexdigest() 81 | b'e1a50df419d65715c48316bdc6a6f7f0485f4b26c1b107228faf17988b61c83f' 82 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | 3 | Summary 4 | ------- 5 | 6 | .. toctree:: 7 | :maxdepth: 1 8 | 9 | symmetric 10 | asymmetric 11 | digest 12 | mac 13 | random 14 | streaming 15 | 16 | .. include:: ../LICENSING.rst 17 | -------------------------------------------------------------------------------- /docs/mac.rst: -------------------------------------------------------------------------------- 1 | Message Authentication Codes 2 | ============================ 3 | 4 | .. module:: wolfcrypt.hashes 5 | 6 | A **message authentication code** (MAC) is a short piece of information used 7 | to authenticate a message — in other words, to confirm that the message came 8 | from the stated sender (its authenticity) and has not been changed in transit 9 | (its integrity). 10 | 11 | ``wolfcrypt`` implements the **Hash-based message authentication code** (HMAC), 12 | which uses a cryptographic hash function coupled with a secret key to produce 13 | **message authentication codes**. 14 | 15 | 16 | Hmac Classes 17 | ------------ 18 | 19 | Interface 20 | ~~~~~~~~~ 21 | 22 | All Hmac classes available in this module implements the following 23 | interface: 24 | 25 | .. autoclass:: _Hmac 26 | :members: 27 | :inherited-members: 28 | 29 | SHA-1 30 | ~~~~~ 31 | 32 | .. attention:: 33 | 34 | NIST has deprecated SHA-1 in favor of the SHA-2 variants. New applications 35 | are strongly suggested to use SHA-2 over SHA-1. 36 | 37 | .. autoclass:: HmacSha 38 | 39 | SHA-2 family 40 | ~~~~~~~~~~~~ 41 | 42 | .. autoclass:: HmacSha256 43 | 44 | 45 | .. autoclass:: HmacSha384 46 | 47 | 48 | .. autoclass:: HmacSha512 49 | 50 | 51 | Example 52 | ------- 53 | 54 | .. doctest:: 55 | 56 | >>> from wolfcrypt.hashes import HmacSha256 57 | >>> 58 | >>> h = HmacSha256('secret') 59 | >>> h.update("wolf") 60 | >>> h.update("crypt") 61 | >>> h.digest() 62 | b'\x18\xbf*\t9\xa2o\xdf\\\xc8\xe0\xc2U\x94,\x8dY\x02;\x1c>> h.hexdigest() 64 | b'18bf2a0939a26fdf5cc8e0c255942c8d59023b1c3c51df8ddb8633fbc166236f' 65 | >>> 66 | >>> h.update("rocks") 67 | >>> h.hexdigest() 68 | b'85dc8c1995d20b17942d52773d8a597d028ad958e5736beafb59a4742f63889e' 69 | >>> 70 | >>> HmacSha256('secret', 'wolfcryptrocks').hexdigest() 71 | b'85dc8c1995d20b17942d52773d8a597d028ad958e5736beafb59a4742f63889e' 72 | >>> 73 | >>> HmacSha256.new('secret', 'wolfcryptrocks').hexdigest() 74 | b'85dc8c1995d20b17942d52773d8a597d028ad958e5736beafb59a4742f63889e' 75 | -------------------------------------------------------------------------------- /docs/random.rst: -------------------------------------------------------------------------------- 1 | Random Number Generation 2 | ======================== 3 | 4 | A **cryptographically secure pseudo-random number generator** (CSPRNG) is a 5 | **pseudo-random number generator** (PRNG) with properties that make it suitable 6 | for use in cryptography. 7 | 8 | Using the standard random module APIs for cryptographic keys or initialization 9 | vectors can result in major security issues depending on the algorithms in use. 10 | 11 | ``wolfcrypt`` provides the following CSPRNG implementation: 12 | 13 | .. module:: wolfcrypt.random 14 | 15 | .. autoclass:: Random 16 | :members: 17 | :inherited-members: 18 | 19 | 20 | Example 21 | ------- 22 | 23 | >>> from wolfcrypt.random import Random 24 | >>> 25 | >>> r = Random() 26 | >>> b = r.byte() 27 | >>> b # doctest: +SKIP 28 | b'\x8c' 29 | >>> b16 = r.bytes(16) 30 | >>> b16 # doctest: +SKIP 31 | b']\x93nk\x95\xbc@\xffX\xab\xdcB\xda\x11\xf7\x03' 32 | -------------------------------------------------------------------------------- /docs/streaming.rst: -------------------------------------------------------------------------------- 1 | Streaming Encryption Algorithms 2 | =============================== 3 | 4 | .. module:: wolfcrypt.ciphers 5 | 6 | Steaming Encryption Classes 7 | --------------------------- 8 | 9 | Interface 10 | ~~~~~~~~~ 11 | 12 | AesGcmStream 13 | ~~~~~~~~~~~~ 14 | 15 | .. autoclass:: AesGcmStream 16 | :members: 17 | :inherited-members: 18 | 19 | **Example:** 20 | 21 | .. doctest:: 22 | 23 | >>> from wolfcrypt.ciphers import AesGcmStreamEncrypt 24 | >>> from binascii import hexlify as b2h 25 | >>> gcm = AesGcmStream(b'fedcba9876543210', b'0123456789abcdef') 26 | >>> buf = gcm.encrypt("hello world") 27 | >>> authTag = gcm.final() 28 | >>> b2h(buf) 29 | b'5ba7d42e1bf01d7998e932' 30 | >>> b2h(authTag) 31 | b'8f85338aa0b13f48f8b17482dbb8acca' 32 | >>> gcm = AesGcmStream(b'fedcba9876543210', b'0123456789abcdef') 33 | >>> buf = gcm.decrypt(h2b(b'5ba7d42e1bf01d7998e932')) 34 | >>> gcm.final(h2b(b'8f85338aa0b13f48f8b17482dbb8acca')) 35 | >>> t2b(buf) 36 | b'hello world' 37 | -------------------------------------------------------------------------------- /docs/symmetric.rst: -------------------------------------------------------------------------------- 1 | Symmetric Key Algorithms 2 | ======================== 3 | 4 | .. module:: wolfcrypt.ciphers 5 | 6 | **Symmetric key algorithms** are encryption algorithms that use the **same 7 | cryptographic key** for both encryption and decryption of data. 8 | This operation is also known as **Symmetric Key Encryption**. 9 | 10 | Symmetric Key Encryption Classes 11 | -------------------------------- 12 | 13 | Interface 14 | ~~~~~~~~~ 15 | 16 | All **Symmetric Key Ciphers** available in this module implements the following 17 | interface: 18 | 19 | .. autoclass:: _Cipher 20 | :members: 21 | :inherited-members: 22 | 23 | AES 24 | ~~~ 25 | 26 | .. autoclass:: Aes 27 | :members: 28 | :inherited-members: 29 | 30 | **Example:** 31 | 32 | .. doctest:: 33 | 34 | >>> from wolfcrypt.ciphers import Aes, MODE_CBC 35 | >>> 36 | >>> cipher = Aes(b'0123456789abcdef', MODE_CBC, b'1234567890abcdef') 37 | >>> ciphertext = cipher.encrypt('now is the time ') 38 | >>> ciphertext 39 | b'\x95\x94\x92W_B\x81S,\xcc\x9dFw\xa23\xcb' 40 | >>> cipher.decrypt(ciphertext) 41 | b'now is the time ' 42 | 43 | Triple DES 44 | ~~~~~~~~~~ 45 | 46 | .. autoclass:: Des3 47 | :members: 48 | :inherited-members: 49 | 50 | **Example:** 51 | 52 | .. doctest:: 53 | 54 | >>> from wolfcrypt.ciphers import Des3, MODE_CBC 55 | >>> 56 | >>> cipher = Des3(b'0123456789abcdeffedeba98', MODE_CBC, b'12345678') 57 | >>> ciphertext = cipher.encrypt('now is the time ') 58 | >>> ciphertext 59 | b'l\x04\xd0$\xe8\x0c1\xd6\x1b\x07}V\xa6ty\xe8' 60 | >>> cipher.decrypt(ciphertext) 61 | b'now is the time ' 62 | -------------------------------------------------------------------------------- /requirements/docs.txt: -------------------------------------------------------------------------------- 1 | -r prod.txt 2 | Sphinx 3 | sphinx_rtd_theme 4 | -------------------------------------------------------------------------------- /requirements/prod.txt: -------------------------------------------------------------------------------- 1 | cffi 2 | -------------------------------------------------------------------------------- /requirements/setup.txt: -------------------------------------------------------------------------------- 1 | -r prod.txt 2 | -------------------------------------------------------------------------------- /requirements/test.txt: -------------------------------------------------------------------------------- 1 | -r prod.txt 2 | tox 3 | pytest 4 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2006-2022 wolfSSL Inc. 5 | # 6 | # This file is part of wolfSSL. (formerly known as CyaSSL) 7 | # 8 | # wolfSSL is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # wolfSSL is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program; if not, write to the Free Software 20 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 21 | 22 | # pylint: disable=wrong-import-position 23 | 24 | import os 25 | import sys 26 | from setuptools import setup, find_packages 27 | 28 | os.chdir(os.path.dirname(sys.argv[0]) or ".") 29 | 30 | import re 31 | VERSIONFILE = "wolfcrypt/_version.py" 32 | verstrline = open(VERSIONFILE, "rt").read() 33 | VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]" 34 | mo = re.search(VSRE, verstrline, re.M) 35 | if mo: 36 | verstr = mo.group(1) 37 | else: 38 | raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,)) 39 | VSRE = r"^__wolfssl_version__ = ['\"]([^'\"]*)['\"]" 40 | mo = re.search(VSRE, verstrline, re.M) 41 | if mo: 42 | wolfverstr = mo.group(1) 43 | else: 44 | raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,)) 45 | 46 | 47 | # long_description 48 | with open("README.rst") as readme_file: 49 | long_description = readme_file.read() 50 | 51 | with open("LICENSING.rst") as licensing_file: 52 | long_description = long_description.replace(".. include:: LICENSING.rst\n", 53 | licensing_file.read()) 54 | 55 | setup( 56 | name="wolfcrypt", 57 | version=verstr, 58 | description="Python module that encapsulates wolfSSL's crypto engine API.", 59 | long_description=long_description, 60 | long_description_content_type='text/x-rst', 61 | author="wolfSSL Inc.", 62 | author_email="info@wolfssl.com", 63 | url="https://github.com/wolfssl/wolfcrypt-py", 64 | license="GPLv2 or Commercial License", 65 | 66 | packages=find_packages(), 67 | keywords="wolfssl, wolfcrypt, security, cryptography", 68 | classifiers=[ 69 | u"License :: OSI Approved :: GNU General Public License v2 (GPLv2)", 70 | u"License :: Other/Proprietary License", 71 | u"Operating System :: OS Independent", 72 | u"Programming Language :: Python :: 3", 73 | u"Programming Language :: Python :: 3.6", 74 | u"Programming Language :: Python :: 3.7", 75 | u"Programming Language :: Python :: 3.8", 76 | u"Programming Language :: Python :: 3.9", 77 | u"Topic :: Security", 78 | u"Topic :: Security :: Cryptography", 79 | u"Topic :: Software Development" 80 | ], 81 | 82 | setup_requires=["cffi>=1.0.0"], 83 | install_requires=["cffi>=1.0.0"], 84 | cffi_modules=["./scripts/build_ffi.py:ffibuilder"], 85 | 86 | package_data={"wolfcrypt": ["*.dll"]} 87 | ) 88 | -------------------------------------------------------------------------------- /tests/certs/server-cert.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolfSSL/wolfcrypt-py/2668e81abba648d1c16a53892835d7d2696c0984/tests/certs/server-cert.der -------------------------------------------------------------------------------- /tests/certs/server-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIE3TCCA8WgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx 3 | EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh 4 | d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz 5 | bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjEwMjEw 6 | MTk0OTUzWhcNMjMxMTA3MTk0OTUzWjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM 7 | B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxEDAO 8 | BgNVBAsMB1N1cHBvcnQxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG 9 | SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP 10 | ADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXOL07W9hyIvHyf+6hn 11 | f/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/X 12 | GQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBipAm2vwxkBLrgQ48bM 13 | QLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq 14 | 0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJag3DOWCktLBpQkIJ 15 | 6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAAaOCATowggE2MB0GA1UdDgQW 16 | BBSzETLJkpiE4sn40DtuA0LKHw6OPDCByQYDVR0jBIHBMIG+gBQnjmcRdMMmHT/t 17 | M2OzpNgdMOXo1aGBmqSBlzCBlDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRh 18 | bmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQL 19 | DApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG 20 | 9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CCQCq0z+sGAo3TTAMBgNVHRMEBTADAQH/ 21 | MBwGA1UdEQQVMBOCC2V4YW1wbGUuY29thwR/AAABMB0GA1UdJQQWMBQGCCsGAQUF 22 | BwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAGw2mRJMNDgw1KCZAMdLr 23 | JkxHWxn7rf469TA6KNeqaaQV5yZutzNWrI80PfMhL1NYkdA+tDlIv5MRdDbTh0nD 24 | NA0wMKv0TCcZ1cQMrUm9kfjansgtKqzidY6qCNm/Zf+jsU/wYG9NlcQGf69maiM7 25 | OqRhtmzKvuGwd/Psg9WMHYV/jXTI7B5J7FdKzP3iOj5UUK5nzRewZ6VTf8MOPqdY 26 | 6N/VDPJk860ScOO5QrwIYHbVDKUxd1DgyPM6PUXPMnXvEN217W7SLVeClTi8fVTE 27 | hF77foP18S2cmKxz46fSAjDWHwYe0Nw6rPTCwr5yQJrqzzUhO1Zt4VLygNc1g5cH 28 | zA== 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /tests/certs/server-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolfSSL/wolfcrypt-py/2668e81abba648d1c16a53892835d7d2696c0984/tests/certs/server-key.der -------------------------------------------------------------------------------- /tests/certs/server-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEAwJUI4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8fJ/7 3 | qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwbU7lf 4 | P9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEuuBDj 5 | xsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTSELlk 6 | wyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0sGlC 7 | Qgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t1wIDAQABAoIBAQCa0DQPUmIFUAHv 8 | n+1kbsLE2hryhNeSEEiSxOlq64t1bMZ5OPLJckqGZFSVd8vDmp231B2kAMieTuTd 9 | x7pnFsF0vKnWlI8rMBr77d8hBSPZSjm9mGtlmrjcxH3upkMVLj2+HSJgKnMw1T7Y 10 | oqyGQy7E9WReP4l1DxHYUSVOn9iqo85gs+KK2X4b8GTKmlsFC1uqy+XjP24yIgXz 11 | 0PrvdFKB4l90073/MYNFdfpjepcu1rYZxpIm5CgGUFAOeC6peA0Ul7QS2DFAq6EB 12 | QcIw+AdfFuRhd9Jg8p+N6PS662PeKpeB70xs5lU0USsoNPRTHMRYCj+7r7X3SoVD 13 | LTzxWFiBAoGBAPIsVHY5I2PJEDK3k62vvhl1loFk5rW4iUJB0W3QHBv4G6xpyzY8 14 | ZH3c9Bm4w2CxV0hfUk9ZOlV/MsAZQ1A/rs5vF/MOn0DKTq0VO8l56cBZOHNwnAp8 15 | yTpIMqfYSXUKhcLC/RVz2pkJKmmanwpxv7AEpox6Wm9IWlQ7xrFTF9/nAoGBAMuT 16 | 3ncVXbdcXHzYkKmYLdZpDmOzo9ymzItqpKISjI57SCyySzfcBhh96v52odSh6T8N 17 | zRtfr1+elltbD6F8r7ObkNtXczrtsCNErkFPHwdCEyNMy/r0FKTV9542fFufqDzB 18 | hV900jkt/9CE3/uzIHoumxeu5roLrl9TpFLtG8SRAoGBAOyY2rvV/vlSSn0CVUlv 19 | VW5SL4SjK7OGYrNU0mNS2uOIdqDvixWl0xgUcndex6MEH54ZYrUbG57D8rUy+UzB 20 | qusMJn3UX0pRXKRFBnBEp1bA1CIUdp7YY1CJkNPiv4GVkjFBhzkaQwsYpVMfORpf 21 | H0O8h2rfbtMiAP4imHBOGhkpAoGBAIpBVihRnl/Ungs7mKNU8mxW1KrpaTOFJAza 22 | 1AwtxL9PAmk4fNTm3Ezt1xYRwz4A58MmwFEC3rt1nG9WnHrzju/PisUr0toGakTJ 23 | c/5umYf4W77xfOZltU9s8MnF/xbKixsX4lg9ojerAby/QM5TjI7t7+5ZneBj5nxe 24 | 9Y5L8TvBAoGATUX5QIzFW/QqGoq08hysa+kMVja3TnKW1eWK0uL/8fEYEz2GCbjY 25 | dqfJHHFSlDBD4PF4dP1hG0wJzOZoKnGtHN9DvFbbpaS+NXCkXs9P/ABVmTo9I89n 26 | WvUi+LUp0EQR6zUuRr79jhiyX6i/GTKh9dwD5nyaHwx8qbAOITc78bA= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /tests/certs/server-keyPub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJUI4VdB8nFtt9JFQScB 3 | ZcZFrvK8JDC4lc4vTtb2HIi8fJ/7qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8 4 | yl17uuAh5XIuby6G2JVz2qwbU7lfP9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF 5 | 9n8LWWh4c6aMGKkCba/DGQEuuBDjxsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1m 6 | UQy9VLPhbV8cvCNz0QkDiRTSELlkwyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOV 7 | oXe6E9KXc+JdJclqDcM5YKS0sGlCQgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t 8 | 1wIDAQAB 9 | -----END RSA PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/test_aesgcmstream.py: -------------------------------------------------------------------------------- 1 | # test_aesgcmstream.py 2 | # 3 | # Copyright (C) 2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=redefined-outer-name 22 | 23 | from wolfcrypt._ffi import lib as _lib 24 | 25 | if _lib.AESGCM_STREAM_ENABLED: 26 | from collections import namedtuple 27 | import pytest 28 | from wolfcrypt.utils import t2b 29 | from wolfcrypt.exceptions import WolfCryptError 30 | from binascii import hexlify as b2h, unhexlify as h2b 31 | from wolfcrypt.ciphers import AesGcmStream 32 | 33 | def test_encrypt(): 34 | key = "fedcba9876543210" 35 | iv = "0123456789abcdef" 36 | gcm = AesGcmStream(key, iv) 37 | buf = gcm.encrypt("hello world") 38 | authTag = gcm.final() 39 | assert b2h(authTag) == bytes('ac8fcee96dc6ef8e5236da19b6197d2e', 'utf-8') 40 | assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8") 41 | gcmdec = AesGcmStream(key, iv) 42 | bufdec = gcmdec.decrypt(buf) 43 | gcmdec.final(authTag) 44 | assert bufdec == t2b("hello world") 45 | 46 | def test_encrypt_short_tag(): 47 | key = "fedcba9876543210" 48 | iv = "0123456789abcdef" 49 | gcm = AesGcmStream(key, iv, 12) 50 | buf = gcm.encrypt("hello world") 51 | authTag = gcm.final() 52 | assert b2h(authTag) == bytes('ac8fcee96dc6ef8e5236da19', 'utf-8') 53 | assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8") 54 | gcmdec = AesGcmStream(key, iv) 55 | bufdec = gcmdec.decrypt(buf) 56 | gcmdec.final(authTag) 57 | assert bufdec == t2b("hello world") 58 | 59 | def test_multipart(): 60 | key = "fedcba9876543210" 61 | iv = "0123456789abcdef" 62 | gcm = AesGcmStream(key, iv) 63 | buf = gcm.encrypt("hello") 64 | buf += gcm.encrypt(" world") 65 | authTag = gcm.final() 66 | assert b2h(authTag) == bytes('ac8fcee96dc6ef8e5236da19b6197d2e', 'utf-8') 67 | assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8") 68 | gcmdec = AesGcmStream(key, iv) 69 | bufdec = gcmdec.decrypt(buf[:5]) 70 | bufdec += gcmdec.decrypt(buf[5:]) 71 | gcmdec.final(authTag) 72 | assert bufdec == t2b("hello world") 73 | 74 | def test_encrypt_aad(): 75 | key = "fedcba9876543210" 76 | iv = "0123456789abcdef" 77 | aad = "aad data" 78 | gcm = AesGcmStream(key, iv) 79 | gcm.set_aad(aad) 80 | buf = gcm.encrypt("hello world") 81 | authTag = gcm.final() 82 | print(b2h(authTag)) 83 | assert b2h(authTag) == bytes('8f85338aa0b13f48f8b17482dbb8acca', 'utf-8') 84 | assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8") 85 | gcmdec = AesGcmStream(key, iv) 86 | gcmdec.set_aad(aad) 87 | bufdec = gcmdec.decrypt(buf) 88 | gcmdec.final(authTag) 89 | assert bufdec == t2b("hello world") 90 | 91 | def test_multipart_aad(): 92 | key = "fedcba9876543210" 93 | iv = "0123456789abcdef" 94 | aad = "aad data" 95 | gcm = AesGcmStream(key, iv) 96 | gcm.set_aad(aad) 97 | buf = gcm.encrypt("hello") 98 | buf += gcm.encrypt(" world") 99 | authTag = gcm.final() 100 | assert b2h(authTag) == bytes('8f85338aa0b13f48f8b17482dbb8acca', 'utf-8') 101 | assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8") 102 | gcmdec = AesGcmStream(key, iv) 103 | gcmdec.set_aad(aad) 104 | bufdec = gcmdec.decrypt(buf[:5]) 105 | bufdec += gcmdec.decrypt(buf[5:]) 106 | gcmdec.final(authTag) 107 | assert bufdec == t2b("hello world") 108 | 109 | def test_encrypt_aad_bad(): 110 | key = "fedcba9876543210" 111 | iv = "0123456789abcdef" 112 | aad = "aad data" 113 | aad_bad = "bad data" 114 | gcm = AesGcmStream(key, iv) 115 | gcm.set_aad(aad) 116 | buf = gcm.encrypt("hello world") 117 | authTag = gcm.final() 118 | print(b2h(authTag)) 119 | assert b2h(authTag) == bytes('8f85338aa0b13f48f8b17482dbb8acca', 'utf-8') 120 | assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8") 121 | gcmdec = AesGcmStream(key, iv) 122 | gcmdec.set_aad(aad_bad) 123 | gcmdec.decrypt(buf) 124 | with pytest.raises(WolfCryptError): 125 | gcmdec.final(authTag) 126 | -------------------------------------------------------------------------------- /tests/test_asn.py: -------------------------------------------------------------------------------- 1 | # test_asn.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=redefined-outer-name 22 | 23 | from collections import namedtuple 24 | import pytest 25 | import os 26 | from wolfcrypt._ffi import lib as _lib 27 | from wolfcrypt.utils import h2b 28 | 29 | if _lib.ASN_ENABLED: 30 | from wolfcrypt.asn import pem_to_der, der_to_pem, make_signature, check_signature 31 | if _lib.SHA256_ENABLED: 32 | from wolfcrypt.hashes import Sha256 33 | if _lib.RSA_ENABLED: 34 | from wolfcrypt.ciphers import RsaPrivate, RsaPublic 35 | 36 | certs_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "certs") 37 | 38 | @pytest.fixture 39 | def pem_der_conversion_vectors(): 40 | TestVector = namedtuple("TestVector", "pem der type") 41 | TestVector.__new__.__defaults__ = (None,) * len(TestVector._fields) 42 | 43 | vectors = [] 44 | 45 | if _lib.ASN_ENABLED: 46 | files = [ 47 | ("server-key.pem", "server-key.der", _lib.PRIVATEKEY_TYPE), 48 | ("server-cert.pem", "server-cert.der", _lib.CERT_TYPE), 49 | ] 50 | for f in files: 51 | pem_path = os.path.join(certs_dir, f[0]) 52 | with open(pem_path, "rb") as pem_handle: 53 | pem = pem_handle.read() 54 | 55 | der_path = os.path.join(certs_dir, f[1]) 56 | with open(der_path, "rb") as der_handle: 57 | der = der_handle.read() 58 | 59 | vectors.append(TestVector(pem=pem, der=der, type=f[2])) 60 | 61 | return vectors 62 | 63 | @pytest.fixture 64 | def signature_vectors(): 65 | TestVector = namedtuple("TestVector", """data signature hash_cls pub_key 66 | priv_key""") 67 | TestVector.__new__.__defaults__ = (None,) * len(TestVector._fields) 68 | 69 | vectors = [] 70 | 71 | with open(os.path.join(certs_dir, "server-keyPub.pem"), "rb") as f: 72 | pub_key_pem = f.read() 73 | with open(os.path.join(certs_dir, "server-key.pem"), "rb") as f: 74 | priv_key_pem = f.read() 75 | 76 | # Signature computed with: 77 | # echo -n "wolfcrypt is the best crypto around" | \ 78 | # openssl dgst -hex -sha256 -sign tests/certs/server-key.pem 79 | if _lib.ASN_ENABLED and _lib.SHA256_ENABLED and _lib.RSA_ENABLED: 80 | vectors.append(TestVector( 81 | data="wolfcrypt is the best crypto around", 82 | signature=h2b("1d65f21df8fdc9f3c2351792840423481c6b0f2332105abd9248" 83 | "9e0dc8f6f8c740e267cf49f522f771eabd484f961eaf9f907c97" 84 | "b513bb9de7411b508c4e7ab7dc4438890ca161a9e24addaffd3c" 85 | "86821f2431f55fde5d131dfbe5805dea74e8882bfbfbf451f809" 86 | "ed792dfb0b17c799e6a39f866ed9cf613138c9e5e99f757ea13a" 87 | "2b9c167c294cd89f38365ab40175d4e29c24d672cd5ad2d57fec" 88 | "e9ea2b29c1866235c791ec5b635b858512c2b832b1b8f1dc6854" 89 | "cd4927df5519eefee439848c7f109548b3a3c8265658e009899a" 90 | "51a4edaf9f1199f93e448482f27c43a53e0bc65b04e9848128e3" 91 | "60314e864190e6bb9812bfbf4b40994f2c1d4ca7aad9"), 92 | hash_cls=Sha256, 93 | pub_key=RsaPublic.from_pem(pub_key_pem), 94 | priv_key=RsaPrivate.from_pem(priv_key_pem) 95 | )) 96 | 97 | return vectors 98 | 99 | def test_pem_der_conversion(pem_der_conversion_vectors): 100 | for vector in pem_der_conversion_vectors: 101 | computed_der = pem_to_der(vector.pem, vector.type) 102 | assert computed_der == vector.der 103 | 104 | computed_pem = der_to_pem(vector.der, vector.type) 105 | assert computed_pem == vector.pem 106 | 107 | def test_signature(signature_vectors): 108 | for vector in signature_vectors: 109 | assert make_signature(vector.data, vector.hash_cls, vector.priv_key) == vector.signature 110 | assert check_signature(vector.signature, vector.data, vector.hash_cls, 111 | vector.pub_key) 112 | -------------------------------------------------------------------------------- /tests/test_chacha20poly1305.py: -------------------------------------------------------------------------------- 1 | 2 | # test_aesgcmstream.py 3 | # 4 | # Copyright (C) 2022 wolfSSL Inc. 5 | # 6 | # This file is part of wolfSSL. (formerly known as CyaSSL) 7 | # 8 | # wolfSSL is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # wolfSSL is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program; if not, write to the Free Software 20 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 21 | 22 | # pylint: disable=redefined-outer-name 23 | 24 | from wolfcrypt._ffi import lib as _lib 25 | 26 | if _lib.CHACHA20_POLY1305_ENABLED: 27 | from collections import namedtuple 28 | import pytest 29 | from wolfcrypt.utils import t2b 30 | from wolfcrypt.exceptions import WolfCryptError 31 | from binascii import hexlify as b2h, unhexlify as h2b 32 | from wolfcrypt.ciphers import ChaCha20Poly1305 33 | 34 | def test_encrypt_decrypt(): 35 | key = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" 36 | key = h2b(key) 37 | iv = "07000000404142434445464748" #Chnage from C test 38 | iv = h2b(iv) 39 | aad = "50515253c0c1c2c3c4c5c6c7" #Change from C test 40 | aad = h2b(aad) 41 | plaintext1 = "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e" 42 | plaintext1 = h2b(plaintext1) 43 | cipher1 = "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116" 44 | authTag = "1ae10b594f09e26a7e902ecbd0600691" 45 | chacha = ChaCha20Poly1305(key, iv, aad) 46 | generatedChipherText, generatedAuthTag = chacha.encrypt(plaintext1) 47 | assert h2b(cipher1) == generatedChipherText 48 | assert h2b(authTag) == generatedAuthTag 49 | chachadec = ChaCha20Poly1305(key, iv, aad) 50 | generatedPlaintextdec = chachadec.decrypt(generatedAuthTag, generatedChipherText)#takes in the generated authtag made by encrypt and decrypts and produces the plaintext 51 | assert generatedPlaintextdec == t2b("Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.") 52 | -------------------------------------------------------------------------------- /tests/test_ciphers.py: -------------------------------------------------------------------------------- 1 | # test_ciphers.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=redefined-outer-name 22 | 23 | from collections import namedtuple 24 | import pytest 25 | from wolfcrypt._ffi import ffi as _ffi 26 | from wolfcrypt._ffi import lib as _lib 27 | from wolfcrypt.utils import t2b, h2b 28 | import os 29 | 30 | certs_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "certs") 31 | 32 | if _lib.DES3_ENABLED: 33 | from wolfcrypt.ciphers import Des3 34 | 35 | if _lib.AES_ENABLED: 36 | from wolfcrypt.ciphers import Aes 37 | 38 | if _lib.CHACHA_ENABLED: 39 | from wolfcrypt.ciphers import ChaCha 40 | 41 | if _lib.RSA_ENABLED: 42 | from wolfcrypt.ciphers import (RsaPrivate, RsaPublic, HASH_TYPE_SHA256, MGF1SHA256, HASH_TYPE_SHA, MGF1SHA1) 43 | 44 | if _lib.ECC_ENABLED: 45 | from wolfcrypt.ciphers import (EccPrivate, EccPublic) 46 | 47 | if _lib.ED25519_ENABLED: 48 | from wolfcrypt.ciphers import (Ed25519Private, Ed25519Public) 49 | 50 | if _lib.ED448_ENABLED: 51 | from wolfcrypt.ciphers import (Ed448Private, Ed448Public) 52 | 53 | from wolfcrypt.ciphers import ( 54 | MODE_CTR, MODE_ECB, MODE_CBC, WolfCryptError 55 | ) 56 | 57 | 58 | @pytest.fixture 59 | def vectors(): 60 | TestVector = namedtuple("TestVector", """key iv plaintext ciphertext 61 | ciphertext_ctr raw_key 62 | pkcs8_key pem""") 63 | TestVector.__new__.__defaults__ = (None,) * len(TestVector._fields) 64 | 65 | # test vector dictionary 66 | vectorArray = {} 67 | 68 | if _lib.AES_ENABLED: 69 | vectorArray[Aes]=TestVector( 70 | key="0123456789abcdef", 71 | iv="1234567890abcdef", 72 | plaintext=t2b("now is the time "), 73 | ciphertext=h2b("959492575f4281532ccc9d4677a233cb"), 74 | ciphertext_ctr = h2b('287528ddf484b1055debbe751eb52b8a') 75 | ) 76 | if _lib.CHACHA_ENABLED: 77 | vectorArray[ChaCha]=TestVector( 78 | key="0123456789abcdef01234567890abcdef", 79 | iv="1234567890abcdef", 80 | ) 81 | if _lib.DES3_ENABLED: 82 | vectorArray[Des3]=TestVector( 83 | key=h2b("0123456789abcdeffedeba987654321089abcdef01234567"), 84 | iv=h2b("1234567890abcdef"), 85 | plaintext=t2b("Now is the time for all "), 86 | ciphertext=h2b("43a0297ed184f80e8964843212d508981894157487127db0") 87 | ) 88 | if _lib.RSA_ENABLED: 89 | vectorArray[RsaPublic]=TestVector( 90 | key=h2b( 91 | "30819F300D06092A864886F70D010101050003818D0030818902818100BC" 92 | "730EA849F374A2A9EF18A5DA559921F9C8ECB36D48E53535757737ECD161" 93 | "905F3ED9E4D5DF94CAC1A9D719DA86C9E84DC4613682FEABAD7E7725BB8D" 94 | "11A5BC623AA838CC39A20466B4F7F7F3AADA4D020EBB5E8D6948DC77C928" 95 | "0E22E96BA426BA4CE8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B3C67C8DC" 96 | "2700F6916865A90203010001"), 97 | pem=os.path.join(certs_dir, "server-keyPub.pem") 98 | ) 99 | vectorArray[RsaPrivate]=TestVector( 100 | key=h2b( 101 | "3082025C02010002818100BC730EA849F374A2A9EF18A5DA559921F9C8EC" 102 | "B36D48E53535757737ECD161905F3ED9E4D5DF94CAC1A9D719DA86C9E84D" 103 | "C4613682FEABAD7E7725BB8D11A5BC623AA838CC39A20466B4F7F7F3AADA" 104 | "4D020EBB5E8D6948DC77C9280E22E96BA426BA4CE8C1FD4A6F2B1FEF8AAE" 105 | "F69062E5641EEB2B3C67C8DC2700F6916865A902030100010281801397EA" 106 | "E8387825A25C04CE0D407C31E5C470CD9B823B5809863B665FDC3190F14F" 107 | "D5DB15DDDED73B95933118310E5EA3D6A21A716E81481C4BCFDB8E7A8661" 108 | "32DCFB55C1166D279224458BF1B848B14B1DACDEDADD8E2FC291FBA5A96E" 109 | "F83A6AF1FD5018EF9FE7C3CA78EA56D3D3725B96DD4E064E3AC3D9BE72B6" 110 | "6507074C01024100FA47D47A7C923C55EF81F041302DA3CF8F1CE6872705" 111 | "700DDF9835D6F18B382F24B5D084B6794F7129945AF0646AACE772C6ED4D" 112 | "59983E673AF3742CF9611769024100C0C1820D0CEBC62FDC92F99D821A31" 113 | "E9E9F74BF282871CEE166AD11D188270F3C0B62FF6F3F71DF18623C84EEB" 114 | "8F568E8FF5BFF1F72BB5CC3DC657390C1B54410241009D7E05DEEDF4B7B2" 115 | "FBFC304B551DE32F0147966905CD0E2E2CBD8363B6AB7CB76DCA5B64A7CE" 116 | "BE86DF3B53DE61D21EEBA5F637EDACAB78D94CE755FBD71199C102401898" 117 | "1829E61E2739702168AC0A2FA172C121869538C65890A0579CBAE3A7B115" 118 | "C8DEF61BC2612376EFB09D1C44BE1343396717C89DCAFBF545648B38822C" 119 | "F28102403989E59C195530BAB7488C48140EF49F7E779743E1B419353123" 120 | "759C3B44AD691256EE0061641666D37C742B15B4A2FEBF086B1A5D3F9012" 121 | "B105863129DBD9E2"), 122 | pkcs8_key=h2b( 123 | "30820276020100300d06092a864886f7" 124 | "0d0101010500048202603082025c0201" 125 | "0002818100bc730ea849f374a2a9ef18" 126 | "a5da559921f9c8ecb36d48e535357577" 127 | "37ecd161905f3ed9e4d5df94cac1a9d7" 128 | "19da86c9e84dc4613682feabad7e7725" 129 | "bb8d11a5bc623aa838cc39a20466b4f7" 130 | "f7f3aada4d020ebb5e8d6948dc77c928" 131 | "0e22e96ba426ba4ce8c1fd4a6f2b1fef" 132 | "8aaef69062e5641eeb2b3c67c8dc2700" 133 | "f6916865a902030100010281801397ea" 134 | "e8387825a25c04ce0d407c31e5c470cd" 135 | "9b823b5809863b665fdc3190f14fd5db" 136 | "15ddded73b95933118310e5ea3d6a21a" 137 | "716e81481c4bcfdb8e7a866132dcfb55" 138 | "c1166d279224458bf1b848b14b1dacde" 139 | "dadd8e2fc291fba5a96ef83a6af1fd50" 140 | "18ef9fe7c3ca78ea56d3d3725b96dd4e" 141 | "064e3ac3d9be72b66507074c01024100" 142 | "fa47d47a7c923c55ef81f041302da3cf" 143 | "8f1ce6872705700ddf9835d6f18b382f" 144 | "24b5d084b6794f7129945af0646aace7" 145 | "72c6ed4d59983e673af3742cf9611769" 146 | "024100c0c1820d0cebc62fdc92f99d82" 147 | "1a31e9e9f74bf282871cee166ad11d18" 148 | "8270f3c0b62ff6f3f71df18623c84eeb" 149 | "8f568e8ff5bff1f72bb5cc3dc657390c" 150 | "1b54410241009d7e05deedf4b7b2fbfc" 151 | "304b551de32f0147966905cd0e2e2cbd" 152 | "8363b6ab7cb76dca5b64a7cebe86df3b" 153 | "53de61d21eeba5f637edacab78d94ce7" 154 | "55fbd71199c1024018981829e61e2739" 155 | "702168ac0a2fa172c121869538c65890" 156 | "a0579cbae3a7b115c8def61bc2612376" 157 | "efb09d1c44be1343396717c89dcafbf5" 158 | "45648b38822cf28102403989e59c1955" 159 | "30bab7488c48140ef49f7e779743e1b4" 160 | "19353123759c3b44ad691256ee006164" 161 | "1666d37c742b15b4a2febf086b1a5d3f" 162 | "9012b105863129dbd9e2"), 163 | pem=os.path.join(certs_dir, "server-key.pem") 164 | ) 165 | 166 | if _lib.ECC_ENABLED: 167 | vectorArray[EccPublic]=TestVector( 168 | key=h2b( 169 | "3059301306072A8648CE3D020106082A8648CE3D0301070342000455BFF4" 170 | "0F44509A3DCE9BB7F0C54DF5707BD4EC248E1980EC5A4CA22403622C9BDA" 171 | "EFA2351243847616C6569506CC01A9BDF6751A42F7BDA9B236225FC75D7F" 172 | "B4" 173 | ), 174 | raw_key=h2b( 175 | "55bff40f44509a3dce9bb7f0c54df5707bd4ec248e1980ec5a4ca22403622c9b" 176 | "daefa2351243847616c6569506cc01a9bdf6751a42f7bda9b236225fc75d7fb4" 177 | ) 178 | ) 179 | vectorArray[EccPrivate]=TestVector( 180 | key=h2b( 181 | "30770201010420F8CF926BBD1E28F1A8ABA1234F3274188850AD7EC7EC92" 182 | "F88F974DAF568965C7A00A06082A8648CE3D030107A1440342000455BFF4" 183 | "0F44509A3DCE9BB7F0C54DF5707BD4EC248E1980EC5A4CA22403622C9BDA" 184 | "EFA2351243847616C6569506CC01A9BDF6751A42F7BDA9B236225FC75D7F" 185 | "B4" 186 | ), 187 | raw_key=h2b( 188 | "55bff40f44509a3dce9bb7f0c54df5707bd4ec248e1980ec5a4ca22403622c9b" 189 | "daefa2351243847616c6569506cc01a9bdf6751a42f7bda9b236225fc75d7fb4" 190 | "f8cf926bbd1e28f1a8aba1234f3274188850ad7ec7ec92f88f974daf568965c7" 191 | ) 192 | ) 193 | 194 | if _lib.ED25519_ENABLED: 195 | vectorArray[Ed25519Private]=TestVector( 196 | key = h2b( 197 | "47CD22B276161AA18BA1E0D13DBE84FE4840E4395D784F555A92E8CF739B" 198 | "F86B" 199 | ) 200 | ) 201 | vectorArray[Ed25519Public]=TestVector( 202 | key=h2b( 203 | "8498C65F4841145F9C51E8BFF4504B5527E0D5753964B7CB3C707A2B9747" 204 | "FC96" 205 | ) 206 | ) 207 | if _lib.ED448_ENABLED: 208 | vectorArray[Ed448Private]=TestVector( 209 | key=h2b("c2b29804e9a893c9e275cac1f8a3033f3d4b78b79eb427ed359fdeb8" 210 | "82d657c129c7930936b181971b795167ad18cabeeb52b59b94f115ad" 211 | "59" 212 | ) 213 | ) 214 | vectorArray[Ed448Public]=TestVector( 215 | key=h2b("89fb2b5a5ab67dd317794cc5f1700cace295b043f3ad73a66299e10a" 216 | "d3fc0a28289ddd1c641598a354113867a42e82ad844b4d858d92e4e7" 217 | "80" 218 | ) 219 | ) 220 | return vectorArray 221 | 222 | algo_params = [] 223 | if _lib.AES_ENABLED: 224 | algo_params.append(Aes) 225 | if _lib.DES3_ENABLED: 226 | algo_params.append(Des3) 227 | 228 | @pytest.fixture(params=algo_params) 229 | def cipher_cls(request): 230 | return request.param 231 | 232 | 233 | def cipher_new(cipher_cls, vectors): 234 | return cipher_cls.new( 235 | vectors[cipher_cls].key, 236 | MODE_CBC, 237 | vectors[cipher_cls].iv) 238 | 239 | def test_block_cipher(cipher_cls, vectors): 240 | key = vectors[cipher_cls].key 241 | iv = vectors[cipher_cls].iv 242 | plaintext = vectors[cipher_cls].plaintext 243 | ciphertext = vectors[cipher_cls].ciphertext 244 | ciphertext_ctr = vectors[cipher_cls].ciphertext_ctr 245 | 246 | with pytest.raises(ValueError): 247 | cipher_cls.new(key[:-1], MODE_CBC, iv) # invalid key length 248 | 249 | with pytest.raises(ValueError): 250 | cipher_cls.new(key, -1, iv) # invalid mode 251 | 252 | with pytest.raises(ValueError): 253 | cipher_cls.new(key, MODE_ECB, iv) # unsuported mode 254 | 255 | with pytest.raises(ValueError): 256 | cipher_cls.new(key, MODE_CBC, None) # invalid iv 257 | 258 | with pytest.raises(ValueError): 259 | cipher_cls.new(key, MODE_CBC, iv[:-1]) # invalid iv length 260 | 261 | 262 | # Test AES in counter mode 263 | if ciphertext_ctr is not None: 264 | cipher_obj = cipher_cls.new(key, MODE_CTR, iv) 265 | res = cipher_obj.encrypt(plaintext) 266 | assert res == ciphertext_ctr 267 | cipher_obj = cipher_cls.new(key, MODE_CTR, iv) 268 | assert plaintext == cipher_obj.decrypt(res) 269 | 270 | # single encryption 271 | cipher_obj = cipher_new(cipher_cls, vectors) 272 | 273 | assert cipher_obj.encrypt(plaintext) == ciphertext 274 | 275 | 276 | # many encryptions 277 | cipher_obj = cipher_new(cipher_cls, vectors) 278 | result = t2b("") 279 | 280 | segments = tuple(plaintext[i:i + cipher_obj.block_size] 281 | for i in range(0, len(plaintext), cipher_obj.block_size)) 282 | 283 | for segment in segments: 284 | result += cipher_obj.encrypt(segment) 285 | 286 | assert result == ciphertext 287 | 288 | # single decryption 289 | cipher_obj = cipher_new(cipher_cls, vectors) 290 | 291 | assert cipher_obj.decrypt(ciphertext) == plaintext 292 | 293 | # many decryptions 294 | cipher_obj = cipher_new(cipher_cls, vectors) 295 | result = t2b("") 296 | 297 | segments = tuple(ciphertext[i:i + cipher_obj.block_size] 298 | for i in range(0, len(ciphertext), cipher_obj.block_size)) 299 | 300 | for segment in segments: 301 | result += cipher_obj.decrypt(segment) 302 | 303 | assert result == plaintext 304 | 305 | # invalid data sizes 306 | with pytest.raises(ValueError): 307 | cipher_obj.encrypt(plaintext[:-1]) 308 | 309 | with pytest.raises(ValueError): 310 | cipher_obj.decrypt(ciphertext[:-1]) 311 | 312 | if _lib.CHACHA_ENABLED: 313 | @pytest.fixture 314 | def chacha_obj(vectors): 315 | r = ChaCha(vectors[ChaCha].key, 32) 316 | r.set_iv(vectors[ChaCha].iv) 317 | return r 318 | 319 | @pytest.fixture 320 | def test_chacha_enc_dec(chacha_obj): 321 | plaintext = t2b("Everyone gets Friday off.") 322 | cyt = chacha_obj.encrypt(plaintext) 323 | chacha_obj.set_iv(vectors[ChaCha].iv) 324 | dec = chacha_obj.decrypt(cyt) 325 | assert plaintext == dec 326 | 327 | if _lib.RSA_ENABLED: 328 | @pytest.fixture 329 | def rsa_private(vectors): 330 | return RsaPrivate(vectors[RsaPrivate].key) 331 | 332 | @pytest.fixture 333 | def rsa_private_oaep(vectors): 334 | return RsaPrivate(vectors[RsaPrivate].key, hash_type=HASH_TYPE_SHA) 335 | 336 | @pytest.fixture 337 | def rsa_private_pss(vectors): 338 | return RsaPrivate(vectors[RsaPrivate].key, hash_type=HASH_TYPE_SHA256) 339 | 340 | @pytest.fixture 341 | def rsa_private_pkcs8(vectors): 342 | return RsaPrivate(vectors[RsaPrivate].pkcs8_key) 343 | 344 | @pytest.fixture 345 | def rsa_public(vectors): 346 | return RsaPublic(vectors[RsaPublic].key) 347 | 348 | @pytest.fixture 349 | def rsa_public_oaep(vectors): 350 | return RsaPublic(vectors[RsaPublic].key, hash_type=HASH_TYPE_SHA) 351 | 352 | @pytest.fixture 353 | def rsa_public_pss(vectors): 354 | return RsaPublic(vectors[RsaPublic].key, hash_type=HASH_TYPE_SHA256) 355 | 356 | @pytest.fixture 357 | def rsa_private_pem(vectors): 358 | with open(vectors[RsaPrivate].pem, "rb") as f: 359 | pem = f.read() 360 | return RsaPrivate.from_pem(pem) 361 | 362 | @pytest.fixture 363 | def rsa_public_pem(vectors): 364 | with open(vectors[RsaPublic].pem, "rb") as f: 365 | pem = f.read() 366 | return RsaPublic.from_pem(pem) 367 | 368 | 369 | def test_new_rsa_raises(vectors): 370 | with pytest.raises(WolfCryptError): 371 | RsaPrivate(vectors[RsaPrivate].key[:-1]) # invalid key length 372 | 373 | with pytest.raises(WolfCryptError): 374 | RsaPublic(vectors[RsaPublic].key[:-1]) # invalid key length 375 | 376 | if _lib.KEYGEN_ENABLED: 377 | with pytest.raises(WolfCryptError): # invalid key size 378 | RsaPrivate.make_key(16384) 379 | 380 | 381 | def test_rsa_encrypt_decrypt(rsa_private, rsa_public): 382 | plaintext = t2b("Everyone gets Friday off.") 383 | 384 | # normal usage, encrypt with public, decrypt with private 385 | ciphertext = rsa_public.encrypt(plaintext) 386 | 387 | assert 1024 / 8 == len(ciphertext) == rsa_public.output_size 388 | assert plaintext == rsa_private.decrypt(ciphertext) 389 | 390 | # private object holds both private and public info, so it can also encrypt 391 | # using the known public key. 392 | ciphertext = rsa_private.encrypt(plaintext) 393 | 394 | assert 1024 / 8 == len(ciphertext) == rsa_private.output_size 395 | assert plaintext == rsa_private.decrypt(ciphertext) 396 | 397 | def test_rsa_encrypt_decrypt_pad_oaep(rsa_private_oaep, rsa_public_oaep): 398 | plaintext = t2b("Everyone gets Friday off.") 399 | 400 | # normal usage, encrypt with public, decrypt with private 401 | ciphertext = rsa_public_oaep.encrypt_oaep(plaintext) 402 | 403 | assert 1024 / 8 == len(ciphertext) == rsa_public_oaep.output_size 404 | assert plaintext == rsa_private_oaep.decrypt_oaep(ciphertext) 405 | 406 | # private object holds both private and public info, so it can also encrypt 407 | # using the known public key. 408 | ciphertext = rsa_private_oaep.encrypt_oaep(plaintext) 409 | 410 | assert 1024 / 8 == len(ciphertext) == rsa_private_oaep.output_size 411 | assert plaintext == rsa_private_oaep.decrypt_oaep(ciphertext) 412 | 413 | 414 | def test_rsa_pkcs8_encrypt_decrypt(rsa_private_pkcs8, rsa_public): 415 | plaintext = t2b("Everyone gets Friday off.") 416 | 417 | # normal usage, encrypt with public, decrypt with private 418 | ciphertext = rsa_public.encrypt(plaintext) 419 | 420 | assert 1024 / 8 == len(ciphertext) == rsa_public.output_size 421 | assert plaintext == rsa_private_pkcs8.decrypt(ciphertext) 422 | 423 | # private object holds both private and public info, so it can also encrypt 424 | # using the known public key. 425 | ciphertext = rsa_private_pkcs8.encrypt(plaintext) 426 | 427 | assert 1024 / 8 == len(ciphertext) == rsa_private_pkcs8.output_size 428 | assert plaintext == rsa_private_pkcs8.decrypt(ciphertext) 429 | 430 | 431 | def test_rsa_sign_verify(rsa_private, rsa_public): 432 | plaintext = t2b("Everyone gets Friday off.") 433 | 434 | # normal usage, sign with private, verify with public 435 | signature = rsa_private.sign(plaintext) 436 | 437 | assert 1024 / 8 == len(signature) == rsa_private.output_size 438 | assert plaintext == rsa_public.verify(signature) 439 | 440 | # private object holds both private and public info, so it can also verify 441 | # using the known public key. 442 | signature = rsa_private.sign(plaintext) 443 | 444 | assert 1024 / 8 == len(signature) == rsa_private.output_size 445 | assert plaintext == rsa_private.verify(signature) 446 | 447 | if _lib.RSA_PSS_ENABLED: 448 | def test_rsa_pss_sign_verify(rsa_private_pss, rsa_public_pss): 449 | plaintext = t2b("Everyone gets Friday off.") 450 | 451 | # normal usage, sign with private, verify with public 452 | signature = rsa_private_pss.sign_pss(plaintext) 453 | 454 | assert 1024 / 8 == len(signature) == rsa_private_pss.output_size 455 | assert 0 == rsa_public_pss.verify_pss(plaintext, signature) 456 | 457 | # private object holds both private and public info, so it can also verify 458 | # using the known public key. 459 | signature = rsa_private_pss.sign_pss(plaintext) 460 | 461 | assert 1024 / 8 == len(signature) == rsa_private_pss.output_size 462 | assert 0 == rsa_private_pss.verify_pss(plaintext, signature) 463 | 464 | def test_rsa_sign_verify_pem(rsa_private_pem, rsa_public_pem): 465 | plaintext = t2b("Everyone gets Friday off.") 466 | 467 | # normal usage, sign with private, verify with public 468 | signature = rsa_private_pem.sign(plaintext) 469 | 470 | assert 256 == len(signature) == rsa_private_pem.output_size 471 | assert plaintext == rsa_public_pem.verify(signature) 472 | 473 | # private object holds both private and public info, so it can also verify 474 | # using the known public key. 475 | signature = rsa_private_pem.sign(plaintext) 476 | 477 | assert 256 == len(signature) == rsa_private_pem.output_size 478 | assert plaintext == rsa_private_pem.verify(signature) 479 | 480 | def test_rsa_pkcs8_sign_verify(rsa_private_pkcs8, rsa_public): 481 | plaintext = t2b("Everyone gets Friday off.") 482 | 483 | # normal usage, sign with private, verify with public 484 | signature = rsa_private_pkcs8.sign(plaintext) 485 | 486 | assert 1024 / 8 == len(signature) == rsa_private_pkcs8.output_size 487 | assert plaintext == rsa_public.verify(signature) 488 | 489 | # private object holds both private and public info, so it can also verify 490 | # using the known public key. 491 | signature = rsa_private_pkcs8.sign(plaintext) 492 | 493 | assert 1024 / 8 == len(signature) == rsa_private_pkcs8.output_size 494 | assert plaintext == rsa_private_pkcs8.verify(signature) 495 | 496 | 497 | if _lib.ECC_ENABLED: 498 | @pytest.fixture 499 | def ecc_private(vectors): 500 | return EccPrivate(vectors[EccPrivate].key) 501 | 502 | 503 | @pytest.fixture 504 | def ecc_public(vectors): 505 | return EccPublic(vectors[EccPublic].key) 506 | 507 | 508 | def test_new_ecc_raises(vectors): 509 | with pytest.raises(WolfCryptError): 510 | EccPrivate(vectors[EccPrivate].key[:-1]) # invalid key length 511 | 512 | with pytest.raises(WolfCryptError): 513 | EccPublic(vectors[EccPublic].key[:-1]) # invalid key length 514 | 515 | with pytest.raises(WolfCryptError): 516 | EccPrivate(vectors[EccPublic].key) # invalid key type 517 | 518 | with pytest.raises(WolfCryptError): # invalid key size 519 | EccPrivate.make_key(1024) 520 | 521 | 522 | def test_key_encoding(vectors): 523 | priv = EccPrivate() 524 | pub = EccPublic() 525 | raw_priv = EccPrivate() 526 | raw_pub = EccPublic() 527 | 528 | 529 | # Test default encode/decode key 530 | priv.decode_key(vectors[EccPrivate].key) 531 | pub.decode_key(vectors[EccPublic].key) 532 | assert priv.encode_key() == vectors[EccPrivate].key 533 | assert pub.encode_key() == vectors[EccPublic].key 534 | 535 | # Test EccPrivate.encode_key_raw/decode_key_raw 536 | key = vectors[EccPrivate].raw_key 537 | raw_priv.decode_key_raw(key[0:32], key[32:64], key[64:96]) 538 | qx, qy, d = raw_priv.encode_key_raw() 539 | assert qx[0:32] == vectors[EccPrivate].raw_key[0:32] 540 | assert qy[0:32] == vectors[EccPrivate].raw_key[32:64] 541 | assert d[0:32] == vectors[EccPrivate].raw_key[64:96] 542 | # Verify ECC key is the same as the raw key 543 | qx, qy, d = priv.encode_key_raw() 544 | assert qx[0:32] == vectors[EccPrivate].raw_key[0:32] 545 | assert qy[0:32] == vectors[EccPrivate].raw_key[32:64] 546 | assert d[0:32] == vectors[EccPrivate].raw_key[64:96] 547 | 548 | # Test EccPublic.encode_key_raw/decode_key_raw 549 | key = vectors[EccPublic].raw_key 550 | raw_pub.decode_key_raw(key[0:32], key[32:64]) 551 | qx, qy = raw_pub.encode_key_raw() 552 | assert qx[0:32] == vectors[EccPublic].raw_key[0:32] 553 | assert qy[0:32] == vectors[EccPublic].raw_key[32:64] 554 | # Verify ECC public key is the same as the raw key 555 | qx, qy = pub.encode_key_raw() 556 | assert qx[0:32] == vectors[EccPublic].raw_key[0:32] 557 | assert qy[0:32] == vectors[EccPublic].raw_key[32:64] 558 | 559 | 560 | 561 | 562 | 563 | def test_x963(ecc_private, ecc_public): 564 | assert ecc_private.export_x963() == ecc_public.export_x963() 565 | 566 | 567 | def test_ecc_sign_verify(ecc_private, ecc_public): 568 | plaintext = "Everyone gets Friday off." 569 | 570 | # normal usage, sign with private, verify with public 571 | signature = ecc_private.sign(plaintext) 572 | 573 | assert len(signature) <= ecc_private.max_signature_size 574 | assert ecc_public.verify(signature, plaintext) 575 | 576 | # invalid signature 577 | with pytest.raises(WolfCryptError): 578 | ecc_public.verify(signature[:-1], plaintext) 579 | 580 | # private object holds both private and public info, so it can also verify 581 | # using the known public key. 582 | assert ecc_private.verify(signature, plaintext) 583 | 584 | ecc_x963 = EccPublic() 585 | ecc_x963.import_x963(ecc_public.export_x963()) 586 | assert ecc_x963.verify(signature, plaintext) 587 | 588 | ecc_x963 = EccPublic() 589 | ecc_x963.import_x963(ecc_private.export_x963()) 590 | assert ecc_x963.verify(signature, plaintext) 591 | 592 | ecc_x963 = EccPublic() 593 | with pytest.raises(WolfCryptError): 594 | ecc_x963.import_x963(ecc_public.export_x963()[:-1]) 595 | 596 | if _lib.MPAPI_ENABLED: 597 | def test_ecc_sign_verify_raw(ecc_private, ecc_public): 598 | plaintext = "Everyone gets Friday off." 599 | 600 | # normal usage, sign with private, verify with public 601 | r,s = ecc_private.sign_raw(plaintext) 602 | 603 | assert len(r) + len(s) <= 2 * ecc_private.size 604 | assert ecc_public.verify_raw(r, s, plaintext) 605 | 606 | # invalid signature 607 | ret = ecc_public.verify_raw(r, s[:-1], plaintext) 608 | assert ret == False 609 | 610 | # private object holds both private and public info, so it can also verify 611 | # using the known public key. 612 | assert ecc_private.verify_raw(r, s, plaintext) 613 | 614 | 615 | def test_ecc_make_shared_secret(): 616 | a = EccPrivate.make_key(32) 617 | a_pub = EccPublic() 618 | a_pub.import_x963(a.export_x963()) 619 | 620 | b = EccPrivate.make_key(32) 621 | b_pub = EccPublic() 622 | b_pub.import_x963(b.export_x963()) 623 | 624 | assert a.shared_secret(b) \ 625 | == b.shared_secret(a) \ 626 | == a.shared_secret(b_pub) \ 627 | == b.shared_secret(a_pub) 628 | 629 | if _lib.ED25519_ENABLED: 630 | @pytest.fixture 631 | def ed25519_private(vectors): 632 | return Ed25519Private(vectors[Ed25519Private].key, vectors[Ed25519Public].key) 633 | 634 | 635 | @pytest.fixture 636 | def ed25519_public(vectors): 637 | return Ed25519Public(vectors[Ed25519Public].key) 638 | 639 | 640 | def test_new_ed25519_raises(vectors): 641 | with pytest.raises(WolfCryptError): 642 | Ed25519Private(vectors[Ed25519Private].key[:-1]) # invalid key length 643 | 644 | with pytest.raises(WolfCryptError): 645 | Ed25519Public(vectors[Ed25519Public].key[:-1]) # invalid key length 646 | 647 | with pytest.raises(WolfCryptError): # invalid key size 648 | Ed25519Private.make_key(1024) 649 | 650 | 651 | def test_ed25519_key_encoding(vectors): 652 | priv = Ed25519Private() 653 | pub = Ed25519Public() 654 | 655 | priv.decode_key(vectors[Ed25519Private].key) 656 | pub.decode_key(vectors[Ed25519Public].key) 657 | 658 | assert priv.encode_key()[0] == vectors[Ed25519Private].key 659 | assert priv.encode_key()[1] == vectors[Ed25519Public].key # Automatically re-generated from private-only 660 | assert pub.encode_key() == vectors[Ed25519Public].key 661 | 662 | 663 | def test_ed25519_sign_verify(ed25519_private, ed25519_public): 664 | plaintext = "Everyone gets Friday off." 665 | 666 | # normal usage, sign with private, verify with public 667 | signature = ed25519_private.sign(plaintext) 668 | 669 | assert len(signature) <= ed25519_private.max_signature_size 670 | assert ed25519_public.verify(signature, plaintext) 671 | 672 | # invalid signature 673 | with pytest.raises(WolfCryptError): 674 | ed25519_public.verify(signature[:-1], plaintext) 675 | 676 | # private object holds both private and public info, so it can also verify 677 | # using the known public key. 678 | assert ed25519_private.verify(signature, plaintext) 679 | 680 | if _lib.ED448_ENABLED: 681 | @pytest.fixture 682 | def ed448_private(vectors): 683 | return Ed448Private(vectors[Ed448Private].key, vectors[Ed448Public].key) 684 | 685 | 686 | @pytest.fixture 687 | def ed448_public(vectors): 688 | return Ed448Public(vectors[Ed448Public].key) 689 | 690 | 691 | def test_new_ed448_raises(vectors): 692 | with pytest.raises(WolfCryptError): 693 | Ed448Private(vectors[Ed448Private].key[:-1]) # invalid key length 694 | 695 | with pytest.raises(WolfCryptError): 696 | Ed448Public(vectors[Ed448Public].key[:-1]) # invalid key length 697 | 698 | with pytest.raises(WolfCryptError): # invalid key size 699 | Ed448Private.make_key(1024) 700 | 701 | 702 | def test_ed448_key_encoding(vectors): 703 | priv = Ed448Private() 704 | pub = Ed448Public() 705 | 706 | priv.decode_key(vectors[Ed448Private].key) 707 | pub.decode_key(vectors[Ed448Public].key) 708 | 709 | assert priv.encode_key()[0] == vectors[Ed448Private].key 710 | assert priv.encode_key()[1] == vectors[Ed448Public].key # Automatically re-generated from private-only 711 | assert pub.encode_key() == vectors[Ed448Public].key 712 | 713 | 714 | def test_ed448_sign_verify(ed448_private, ed448_public): 715 | plaintext = "Everyone gets Friday off." 716 | 717 | # normal usage, sign with private, verify with public 718 | signature = ed448_private.sign(plaintext) 719 | 720 | assert len(signature) <= ed448_private.max_signature_size 721 | assert ed448_public.verify(signature, plaintext) 722 | 723 | # invalid signature 724 | with pytest.raises(WolfCryptError): 725 | ed448_public.verify(signature[:-1], plaintext) 726 | 727 | # private object holds both private and public info, so it can also verify 728 | # using the known public key. 729 | assert ed448_private.verify(signature, plaintext) 730 | -------------------------------------------------------------------------------- /tests/test_hashes.py: -------------------------------------------------------------------------------- 1 | # test_hashes.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=redefined-outer-name 22 | 23 | from collections import namedtuple 24 | import pytest 25 | from wolfcrypt._ffi import ffi as _ffi 26 | from wolfcrypt._ffi import lib as _lib 27 | from wolfcrypt.utils import t2b 28 | 29 | if _lib.SHA_ENABLED: 30 | from wolfcrypt.hashes import Sha 31 | 32 | if _lib.SHA256_ENABLED: 33 | from wolfcrypt.hashes import Sha256 34 | 35 | if _lib.SHA384_ENABLED: 36 | from wolfcrypt.hashes import Sha384 37 | 38 | if _lib.SHA512_ENABLED: 39 | from wolfcrypt.hashes import Sha512 40 | 41 | if _lib.SHA3_ENABLED: 42 | from wolfcrypt.hashes import Sha3 43 | 44 | if _lib.HMAC_ENABLED: 45 | if _lib.SHA_ENABLED: 46 | from wolfcrypt.hashes import HmacSha 47 | if _lib.SHA256_ENABLED: 48 | from wolfcrypt.hashes import HmacSha256 49 | if _lib.SHA384_ENABLED: 50 | from wolfcrypt.hashes import HmacSha384 51 | if _lib.SHA512_ENABLED: 52 | from wolfcrypt.hashes import HmacSha512 53 | 54 | 55 | @pytest.fixture 56 | def vectors(): 57 | TestVector = namedtuple("TestVector", "digest") 58 | TestVector.__new__.__defaults__ = (None,) * len(TestVector._fields) 59 | 60 | # test vector dictionary 61 | vectorArray = {} 62 | 63 | if _lib.SHA_ENABLED: 64 | vectorArray[Sha]=TestVector( 65 | digest=t2b("1b6182d68ae91ce0853bd9c6b6edfedd4b6a510d") 66 | ) 67 | 68 | if _lib.SHA256_ENABLED: 69 | vectorArray[Sha256]=TestVector( 70 | digest=t2b("96e02e7b1cbcd6f104fe1fdb4652027a" + 71 | "5505b68652b70095c6318f9dce0d1844") 72 | ) 73 | 74 | if _lib.SHA384_ENABLED: 75 | vectorArray[Sha384]=TestVector( 76 | digest=t2b("4c79d80531203a16f91bee325f18c6aada47f9382fe44fc1" + 77 | "1f92917837e9b7902f5dccb7d3656f667a1dce3460bc884b") 78 | ) 79 | 80 | if _lib.SHA512_ENABLED: 81 | vectorArray[Sha512]=TestVector( 82 | digest=t2b("88fcf67ffd8558d713f9cedcd852db47" + 83 | "9e6573f0bd9955610a993f609637553c" + 84 | "e8fff55e644ee8a106aae19c07f91b3f" + 85 | "2a2a6d40dfa7302c0fa6a1a9a5bfa03f") 86 | ) 87 | if _lib.SHA3_ENABLED: 88 | vectorArray[Sha3]=TestVector( 89 | digest=t2b("6170dedf06f83c3305ec18b7558384a5" + 90 | "a62d86e42c143d416aaec32f971986c1" + 91 | "e84edf61df308cc6d8c310d1956e1908") 92 | ) 93 | if _lib.HMAC_ENABLED: 94 | if _lib.SHA_ENABLED: 95 | vectorArray[HmacSha]=TestVector( 96 | digest=t2b("7ab9aca2c87c7c45ba2ffa52f719fdbd8fbff62d") 97 | ) 98 | if _lib.SHA256_ENABLED: 99 | vectorArray[HmacSha256]=TestVector( 100 | digest=t2b("9041ac8c66fc350a1a0d5f4fff9d8ef74721d5a43ec8893a2" + 101 | "875cf69576c45c2") 102 | ) 103 | if _lib.SHA384_ENABLED: 104 | vectorArray[HmacSha384]=TestVector( 105 | digest=t2b("f8c589ddf5489404f85c3c718a8345f207fb1ed6c6f5ecb09" + 106 | "8e8be8aeb1aaa9f0c6dd84c141410b29a47a1a2b3a85ae0") 107 | ) 108 | if _lib.SHA512_ENABLED: 109 | vectorArray[HmacSha512]=TestVector( 110 | digest=t2b("7708a12ca110cd81a334bd4e8bddc4314acd3ed218bbff7c6" + 111 | "486e149fc145e9f5c05f05e919f7c2bc027266e986679984c" + 112 | "3ade1a14084ad7627a65c3671a2d05") 113 | ) 114 | 115 | return vectorArray 116 | 117 | 118 | hash_params = [] 119 | if _lib.SHA_ENABLED: 120 | hash_params.append(Sha) 121 | if _lib.SHA256_ENABLED: 122 | hash_params.append(Sha256) 123 | if _lib.SHA384_ENABLED: 124 | hash_params.append(Sha384) 125 | if _lib.SHA512_ENABLED: 126 | hash_params.append(Sha512) 127 | if _lib.SHA3_ENABLED: 128 | hash_params.append(Sha3) 129 | 130 | hmac_params = [] 131 | if _lib.HMAC_ENABLED: 132 | if _lib.SHA_ENABLED: 133 | hmac_params.append(HmacSha) 134 | if _lib.SHA256_ENABLED: 135 | hmac_params.append(HmacSha256) 136 | if _lib.SHA384_ENABLED: 137 | hmac_params.append(HmacSha384) 138 | if _lib.SHA512_ENABLED: 139 | hmac_params.append(HmacSha512) 140 | 141 | @pytest.fixture(params=(hash_params + hmac_params)) 142 | def hash_cls(request): 143 | return request.param 144 | 145 | 146 | def hash_new(cls, data=None): 147 | if cls in hash_params: 148 | # If it's a non-HMAC hash algo, we don't need a key. Call the 149 | # constructor that doesn't take a key. 150 | return cls(data) 151 | # HMAC requires a key (first parameter to constructor below). Do not shorten 152 | # the length of this key below the FIPS requirement. See HMAC_FIPS_MIN_KEY. 153 | return cls("wolfCrypt is the best crypto around", data) 154 | 155 | 156 | def test_hash(hash_cls, vectors): 157 | digest = vectors[hash_cls].digest 158 | 159 | # update inside constructor 160 | assert hash_new(hash_cls, "wolfcrypt").hexdigest() == digest 161 | 162 | # single update 163 | hash_obj = hash_new(hash_cls) 164 | hash_obj.update("wolfcrypt") 165 | 166 | assert hash_obj.hexdigest() == digest 167 | 168 | # many updates 169 | hash_obj = hash_new(hash_cls) 170 | hash_obj.update("wolf") 171 | hash_obj.update("crypt") 172 | 173 | assert hash_obj.hexdigest() == digest 174 | 175 | # copy 176 | hash_obj = hash_new(hash_cls) 177 | copy = hash_obj.copy() 178 | 179 | assert hash_obj.hexdigest() == copy.hexdigest() 180 | 181 | hash_obj.update("wolfcrypt") 182 | 183 | assert hash_obj.hexdigest() != copy.hexdigest() 184 | 185 | copy.update("wolfcrypt") 186 | 187 | assert hash_obj.hexdigest() == copy.hexdigest() == digest 188 | -------------------------------------------------------------------------------- /tests/test_mldsa.py: -------------------------------------------------------------------------------- 1 | # test_mldsa.py 2 | # 3 | # Copyright (C) 2025 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=redefined-outer-name 22 | 23 | from wolfcrypt._ffi import lib as _lib 24 | 25 | if _lib.ML_DSA_ENABLED: 26 | import pytest 27 | 28 | from wolfcrypt.ciphers import MlDsaPrivate, MlDsaPublic, MlDsaType 29 | from wolfcrypt.random import Random 30 | 31 | @pytest.fixture 32 | def rng(): 33 | return Random() 34 | 35 | @pytest.fixture( 36 | params=[MlDsaType.ML_DSA_44, MlDsaType.ML_DSA_65, MlDsaType.ML_DSA_87] 37 | ) 38 | def mldsa_type(request): 39 | return request.param 40 | 41 | def test_init_base(mldsa_type): 42 | mldsa_priv = MlDsaPrivate(mldsa_type) 43 | assert isinstance(mldsa_priv, MlDsaPrivate) 44 | 45 | mldsa_pub = MlDsaPublic(mldsa_type) 46 | assert isinstance(mldsa_pub, MlDsaPublic) 47 | 48 | def test_size_properties(mldsa_type): 49 | refvals = { 50 | MlDsaType.ML_DSA_44: { 51 | "sig_size": 2420, 52 | "pub_key_size": 1312, 53 | "priv_key_size": 2560, 54 | }, 55 | MlDsaType.ML_DSA_65: { 56 | "sig_size": 3309, 57 | "pub_key_size": 1952, 58 | "priv_key_size": 4032, 59 | }, 60 | MlDsaType.ML_DSA_87: { 61 | "sig_size": 4627, 62 | "pub_key_size": 2592, 63 | "priv_key_size": 4896, 64 | }, 65 | } 66 | 67 | mldsa_pub = MlDsaPublic(mldsa_type) 68 | assert mldsa_pub.sig_size == refvals[mldsa_type]["sig_size"] 69 | assert mldsa_pub.key_size == refvals[mldsa_type]["pub_key_size"] 70 | 71 | mldsa_priv = MlDsaPrivate(mldsa_type) 72 | assert mldsa_priv.sig_size == refvals[mldsa_type]["sig_size"] 73 | assert mldsa_priv.pub_key_size == refvals[mldsa_type]["pub_key_size"] 74 | assert mldsa_priv.priv_key_size == refvals[mldsa_type]["priv_key_size"] 75 | 76 | def test_initializations(mldsa_type, rng): 77 | mldsa_priv = MlDsaPrivate.make_key(mldsa_type, rng) 78 | assert type(mldsa_priv) is MlDsaPrivate 79 | 80 | mldsa_priv2 = MlDsaPrivate(mldsa_type) 81 | assert type(mldsa_priv2) is MlDsaPrivate 82 | 83 | mldsa_pub = MlDsaPublic(mldsa_type) 84 | assert type(mldsa_pub) is MlDsaPublic 85 | 86 | def test_key_import_export(mldsa_type, rng): 87 | # Generate key pair and export keys 88 | mldsa_priv = MlDsaPrivate.make_key(mldsa_type, rng) 89 | priv_key = mldsa_priv.encode_priv_key() 90 | pub_key = mldsa_priv.encode_pub_key() 91 | assert len(priv_key) == mldsa_priv.priv_key_size 92 | assert len(pub_key) == mldsa_priv.pub_key_size 93 | 94 | # Export key pair from imported one 95 | mldsa_priv2 = MlDsaPrivate(mldsa_type) 96 | mldsa_priv2.decode_key(priv_key, pub_key) 97 | priv_key2 = mldsa_priv2.encode_priv_key() 98 | pub_key2 = mldsa_priv2.encode_pub_key() 99 | assert priv_key == priv_key2 100 | assert pub_key == pub_key2 101 | 102 | # Export private key from imported one 103 | mldsa_priv3 = MlDsaPrivate(mldsa_type) 104 | mldsa_priv3.decode_key(priv_key) 105 | priv_key3 = mldsa_priv3.encode_priv_key() 106 | assert priv_key == priv_key3 107 | 108 | # Export public key from imported one 109 | mldsa_pub = MlDsaPublic(mldsa_type) 110 | mldsa_pub.decode_key(pub_key) 111 | pub_key3 = mldsa_pub.encode_key() 112 | assert pub_key == pub_key3 113 | 114 | def test_sign_verify(mldsa_type, rng): 115 | # Generate a key pair and export public key 116 | mldsa_priv = MlDsaPrivate.make_key(mldsa_type, rng) 117 | pub_key = mldsa_priv.encode_pub_key() 118 | 119 | # Import public key 120 | mldsa_pub = MlDsaPublic(mldsa_type) 121 | mldsa_pub.decode_key(pub_key) 122 | 123 | # Sign a message 124 | message = b"This is a test message for ML-DSA signature" 125 | signature = mldsa_priv.sign(message, rng) 126 | assert len(signature) == mldsa_priv.sig_size 127 | 128 | # Verify the signature by MlDsaPrivate 129 | assert mldsa_priv.verify(signature, message) 130 | 131 | # Verify the signature by MlDsaPublic 132 | assert mldsa_pub.verify(signature, message) 133 | 134 | # Verify with wrong message 135 | wrong_message = b"This is a wrong message for ML-DSA signature" 136 | assert not mldsa_pub.verify(signature, wrong_message) 137 | -------------------------------------------------------------------------------- /tests/test_mlkem.py: -------------------------------------------------------------------------------- 1 | # test_mlkem.py 2 | # 3 | # Copyright (C) 2025 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=redefined-outer-name 22 | 23 | from wolfcrypt._ffi import lib as _lib 24 | 25 | if _lib.ML_KEM_ENABLED: 26 | from binascii import unhexlify as h2b 27 | 28 | import pytest 29 | 30 | from wolfcrypt.ciphers import MlKemPrivate, MlKemPublic, MlKemType 31 | 32 | ref_priv_key_512 = h2b( 33 | "7a9789b11b5871249ab5fac64e19599150960daa8872898ac55a580c906d7872" 34 | "a8ec16b43791a30a821c6770a1aab98837548e39a37e30674e5efbced0e38a85" 35 | "a920ef5aa07fa5c9ad219cd4e198709a4c949bc8104b946de343f6f4b1ff3155" 36 | "6c681a8db66da3b308d09b08c421611a3743fa82c760f35b94727fb70058d866" 37 | "bd5b05ca12c8a1eef4a9360640b576457174a827b402904b559b839fe9fa3a6f" 38 | "01c340019530657967354f9ae8aa96a7709697a4e1947d52393c8f8a40cad310" 39 | "5ef84559e8b0b2244fdb769d28f854afe6cde616c9cfc5cfc5b8170199bbd384" 40 | "b365dbc2fd651f3042ce8c625ae4410be3a96fcce09c0122bd8d68203345778d" 41 | "7b5a1454cccaa7b6b26b8b97a290e3e3a577d5b0deb56adee45c9be5c5984340" 42 | "21f38afcf9aee9625a4caac44d2199e27ac324b3153830bd3791ab654a61d0f9" 43 | "03f902a3f06a42e1241dd262791c242fe13516abb3b51bf46c22d77b6cea44a4" 44 | "e962ebd42dcde5851028a57b86a880278c8dc6acf05b17185a3186a097edb56c" 45 | "0265577646ce47411c1fba8e83418e0d2c5176dac5951a6fbdd619fb48045339" 46 | "3fa4d21dada8b073e961f7ccade8035997171b3f63959eb087ae6732e7c049f2" 47 | "11c024a054cd4607dc417847a48e107b80b72117883bcc8b272c138c64bc6bbb" 48 | "46904b6fd2b249d49255608ec3ea30d79b6cec09a92b49244c90cca559995ec9" 49 | "013ac0825c502a4c33cc5b094ac20477332b28b092bd83558a791536a0013026" 50 | "2a73a2e3a78688238162237dd3a0c4d22fec2a30b9f19c58fb39cd1ac4944030" 51 | "1cfa54b566736e6b7600b3b650a42d3afaa57a0c1e451a3243b2367945958f38" 52 | "32e5ebba28e365fd35377069c3e75ac5f7175cc341437302350e837b30f90a13" 53 | "0b7efa7614a614b96cf071ec2cb886854ad5e19cc5a4306bb8173a47670a9748" 54 | "1a92b2d8e66688690445b8b2a87482fb638f3d88b6e6378d6ff9150f8a753db7" 55 | "11b5d2a571788e686b2688b2b10db0310690c8039ba664f6634260afd88730a6" 56 | "34471a510662f17431560d2b0811587c004e209af9215e2bfb493fb9ad36699f" 57 | "181bc699c2b59d5176bcf59005729ea7a4011d050d5cf28633c3761b6879e959" 58 | "7c83d005a8b67bab274e10ec9617533190eb8c7cf98da995b68331b0637862d4" 59 | "90119126576c419aa328c53c097efea7118dc9b8aa68c1727c679e62611efa13" 60 | "4031c0ec5041594a3c15ea14b1a03bc1d70f11404b8bc128ab126261f362b014" 61 | "2e3d7c4cb0448141fc9909a07819c3208efc0c0df6bc9593a53ae500e0152987" 62 | "a5bd51e45e351358b850b5f2304c1515ae6a8b151ad7ab4ba0abf9f9bd981311" 63 | "51f9b57c35a6cba16a65726e67fca904c02a97a75be6f875c38ab35f35bf0e22" 64 | "23d65a5be9ccc329e2becbf2963d858a40e37d3392cc71d612f3c06ca2f0215a" 65 | "3949d7d40f34e97c18521e562066512347a913314a46ccf0a5bf9c081c50f666" 66 | "d3119a05956edfd89c800a0dfe263b47e20e9488b8c1170171d0213640252496" 67 | "b5aa7431e56a290d564ce8f58e7a57ad3076974d271096f79a5be069d0836673" 68 | "ec85b732801991c5e2847052279829180543b17e8946aea5fb7c8ed8c19f19cf" 69 | "5e4c9f57e70999d550c8946e22a6287452ae05a55cc0617147791f0ad581a097" 70 | "a9c3d97434a5485a0a5aed7bc255913ce83cacc7478e4658597a3093640809ff" 71 | "6b4005984bc6868f2ec42610f477b55a34d1053682613ce0cab5ff78ae8baa1c" 72 | "213b9d774aac2c43ca065a441287b368010a9256059bf069b4abcd555b04ff69" 73 | "cb0a7078091c69d188c83d919019671ea3e759ebfcbe90413691babb81c80b45" 74 | "54a7e2b717bdc2c3c18cc1ca42634f515239118e2718709651b9b3f50fb6064d" 75 | "8dd58ece0380a167424b367091c7c29805c3942a9fb67a5494db2acee6518feb" 76 | "727ba97fb6dab15a10be51241991f32b9ceb28d4a28d19e5b915e02e024277d3" 77 | "2985a516be2d7331a005699ca0c3723b9e2dd953987774904c9cdfbb3835b1a9" 78 | "bab2524f845e3e27c58b34b56634a4f6f79be751842cbb382759624e0c62c5b3" 79 | "1669a1020f83889b386918d8b3c866adf979b923273946969c8b04c7b7fa68b4" 80 | "30433e4ca9792124f9515bc39b795a32058e3289a75b5aeb9bcbdd825777992c" 81 | "c30b502c96db43f97ff3c365407aad0c6be42358909d6d873a93b48edb9f7948" 82 | "582991075b0f2d4a52981d3dabe8d517aa9cb8a9436ed40ec0bef3af37967faa" 83 | "7e385f73630001f67fa091f49a35284c088f1727f3818a78e174248229641389" 84 | ) 85 | 86 | ref_pub_key_512 = h2b( 87 | "181bc699c2b59d5176bcf59005729ea7a4011d050d5cf28633c3761b6879e959" 88 | "7c83d005a8b67bab274e10ec9617533190eb8c7cf98da995b68331b0637862d4" 89 | "90119126576c419aa328c53c097efea7118dc9b8aa68c1727c679e62611efa13" 90 | "4031c0ec5041594a3c15ea14b1a03bc1d70f11404b8bc128ab126261f362b014" 91 | "2e3d7c4cb0448141fc9909a07819c3208efc0c0df6bc9593a53ae500e0152987" 92 | "a5bd51e45e351358b850b5f2304c1515ae6a8b151ad7ab4ba0abf9f9bd981311" 93 | "51f9b57c35a6cba16a65726e67fca904c02a97a75be6f875c38ab35f35bf0e22" 94 | "23d65a5be9ccc329e2becbf2963d858a40e37d3392cc71d612f3c06ca2f0215a" 95 | "3949d7d40f34e97c18521e562066512347a913314a46ccf0a5bf9c081c50f666" 96 | "d3119a05956edfd89c800a0dfe263b47e20e9488b8c1170171d0213640252496" 97 | "b5aa7431e56a290d564ce8f58e7a57ad3076974d271096f79a5be069d0836673" 98 | "ec85b732801991c5e2847052279829180543b17e8946aea5fb7c8ed8c19f19cf" 99 | "5e4c9f57e70999d550c8946e22a6287452ae05a55cc0617147791f0ad581a097" 100 | "a9c3d97434a5485a0a5aed7bc255913ce83cacc7478e4658597a3093640809ff" 101 | "6b4005984bc6868f2ec42610f477b55a34d1053682613ce0cab5ff78ae8baa1c" 102 | "213b9d774aac2c43ca065a441287b368010a9256059bf069b4abcd555b04ff69" 103 | "cb0a7078091c69d188c83d919019671ea3e759ebfcbe90413691babb81c80b45" 104 | "54a7e2b717bdc2c3c18cc1ca42634f515239118e2718709651b9b3f50fb6064d" 105 | "8dd58ece0380a167424b367091c7c29805c3942a9fb67a5494db2acee6518feb" 106 | "727ba97fb6dab15a10be51241991f32b9ceb28d4a28d19e5b915e02e024277d3" 107 | "2985a516be2d7331a005699ca0c3723b9e2dd953987774904c9cdfbb3835b1a9" 108 | "bab2524f845e3e27c58b34b56634a4f6f79be751842cbb382759624e0c62c5b3" 109 | "1669a1020f83889b386918d8b3c866adf979b923273946969c8b04c7b7fa68b4" 110 | "30433e4ca9792124f9515bc39b795a32058e3289a75b5aeb9bcbdd825777992c" 111 | "c30b502c96db43f97ff3c365407aad0c6be42358909d6d873a93b48edb9f7948" 112 | ) 113 | 114 | ref_ss_512 = h2b("d1cef1d861b7a7d3a2bc8b5a0faa70c4bf6b0b4394df7a7330debe0c2a8326c1") 115 | 116 | ref_ct_512 = h2b( 117 | "8a883c621214524d47fa60da21f46aa62e0ba24771e1195772b2aecc10883422" 118 | "cc68fb29a50782548c06fb6550660ea38035c871818eebc7129134e4d8de7c0f" 119 | "d34a4d32985c830f56a0cb057eb5422fdd94a58c68ada859614ff410a4ecb660" 120 | "8813138ef0f26634f81e69802f1b9415c65b1e47f1e84e52b24255ac91496a03" 121 | "8d86c01b827057868a1749fa7590fee6442793909ca954bc986ae624cdf2fb57" 122 | "d9c534cbc1c235b74e44f3eb23ee136a57815343b148fe4c055257ae490d85e7" 123 | "1c0ddc954d5a6447ce6eed26a9bd149cd21044c38ab1bda703d478b15f74ac75" 124 | "c4aaaf60657990162c0d6d1f891ea2de4e5d7ddf56dddc0e2dbeabf2fdf6e26b" 125 | "dc850ca53ae773c16b7b9132eef7723f77fc5776965e49866b01b66758b598ab" 126 | "868118ee21a25a61eaa391d84903a3cdaafcc3fae2106b4ff32f506e18b0ee6e" 127 | "7caea426240ac8d2c07aea738f67c4951aa6d352849147b97486d97cc9695e40" 128 | "b8eedb8f95e44463cf90f67b6cec23e3cdc91f7cab07b75dae60413ec9126850" 129 | "318852df87d1d5ed042f749c5534edeab52e32d61ab6d851403bdd72ab0ea771" 130 | "34a08bbc1e76c961b97b6eeae1d29e892dee6f601d1f8e9eb0bc41c961d35d1c" 131 | "92e6ec043a61d790f42fb454f64bc95cdeb2792a0f971b33b92fc58176f96026" 132 | "8550bf4e8e40c4c61e84cf4e1b113ccc367cfc2171b31b86fa0e3fc0c48b0db9" 133 | "f05fe2f7a0e6735f6ab94c29bc3f63630407ccc1e61f3e6446bb55511ea03684" 134 | "af609b327e6b0ea96badfe84674e4d5da9b37cd78ccf82f61b83b7baabaaec62" 135 | "60e73e7f1319c7573772733d50cd3856f1fbde2e37e526be056af94c4e96efa2" 136 | "803890416726d21b880c278540d698eb6deb80b85282005e4b3c8393ceacb3e5" 137 | "092405d7253f5d35b83c6bbfba0fd287db0e522d74dfa9038da332d50ef4df72" 138 | "c6ce351ffa410c594121ca24cd9a319baf1b85980e8ed9f54ea2936d545c854a" 139 | "a3428ca0ac909175d76be70686ea4429dd069020ce299b53d2bf34c85e78c739" 140 | "a15e23d98ae42712bee5a07d73db464dda59cc422344d2cd8fe7b36eef2e05ad" 141 | ) 142 | 143 | ref_priv_key_768 = h2b( 144 | "be3a79da6370a170cabec9212e2930b9fb425703b49925882fc2b66a38c56c46" 145 | "c3bfd7803156b43de132bdd9a24d064763357460135b1f32a9aba48413ebcb08" 146 | "d823bdd4ccac3294ee830123bc42ad2412416c126d86b9c953c5c459960ca76c" 147 | "4b42737698b1e78c0c44039c2fe7577534319b01aa6e26962362b733148f3290" 148 | "1a3e38056a7790b51bc08dcbad5e193b6d53803dbb1bc7b81378c54ac994a600" 149 | "7a16c3d3a70f60748d5acb92163c2dd4cf482b28aa773adedc5b8f5b3a8a974a" 150 | "a4ba095e0895033270f51144e90cba6e36aa8e06bc11a5c2dfa746f6eb3af095" 151 | "0f15c5c48b4c4388406568057c6918bb5a37b0db788184b56a09ca61fbab6eff" 152 | "04ba56e53e1b804c583c8850a4a68deb82c8b8124d0a3bdf1c43b875811e009d" 153 | "4e539d3a840f03447896aa41ca221219740b647a82359c9ea972545ab4b0fa8a" 154 | "c50ac47816e6c9bcf61faa306d839c4bae0c40a656c34145a4daac6ceb2801c4" 155 | "844959b75401809c1aab8368993dfc5c08d7d337d1a23eebe23313243e68e8c6" 156 | "b5cbb184c67942b872f0aaa61d61aa9a4a934986c2ff1b643d1bcbcdd554c020" 157 | "9c855a52eb86a7a5b17b53465b68c08e0f174a88ba5f452158e17c8595673d45" 158 | "da3420b3af747b19d6326e631b0c37c008d984b7f18067d7dc894a04c2c7385f" 159 | "526574bd27c4b9c8b9d44985f8c62bdd6118f4dc25f083723596343a806fd052" 160 | "9d8c2563f789b9ddb9c5db56ada8ebc10587bba86c249923916d8a12bd485134" 161 | "078309b772fbb756d5b1480b2438e95502344a77ae145b183b897f712bf006c2" 162 | "da02ba3b11600f8c4af9b755d56ccbbec7af3c6966aaf7578f22c419332ad9d9" 163 | "343e971d10a2c8003783df082f6a6060d3f9b56cd2a022a52e7a334137325d91" 164 | "bbcd05075819ec45b3db30179405652262f1397f0b136cc06aafdb6b461c2b10" 165 | "7bf448e6f68e22650ceff184a3228c3ff0cbbf0bbe562b6b63fba139d4284f17" 166 | "3db6b048e5898363034e7e49566fe5026c239ec63318b7acb90c103d13d89a04" 167 | "3678550274e7025d3858449b01c464d5a9705294bdaccc556454963058789b95" 168 | "96f2562df7c76e50180c33c438f9792ad3128fa0c390202910420ee68658a4d5" 169 | "33a1d70356c2b9b248147d9ac64b1b2ded108595144e46bb7ff2b9a30e991e1f" 170 | "4979b20c4bf9ac2fcab36956692b4a856d6ed8781f2a3ce6700673e4239daa7a" 171 | "4a8186308327a1883666eb13b41cbdc4d413088a3995595a02b260df4ac8d804" 172 | "988e3b1103ec35d3f342c447208109686d80a26d1cb1d1f068cec31c9da06f17" 173 | "440cd4958d7c08badf92bb85f3532a74c4c2c944ec86aa5975ad50f9c31f155c" 174 | "d1e2449b089775dbaf87889de73127b28515f35c2b2a319a37b292193b0d3f89" 175 | "5ac698986f57c4a79940fd42133c190ab6b611f8988a9009c512c60275b721db" 176 | "984e37daa1b13c5272a880b120b477953028b3ae30406c313100d78ccb24e566" 177 | "453b566c32b7c3e237088771a941385713bc05885592853bc5600fc152c46252" 178 | "5f1de95f2c1b0cf1111bf40b391acc608421c577f35e06fc037330395aac5dcf" 179 | "822f91f18eac3b2c4e39b12de27a1926a3d2f8a3ed047b648042c2a78200f5bb" 180 | "72480a6256a076339b826c99e6866ef9e3519f10616558a13549878626cecb5b" 181 | "c4f4e9695b5baea55a9a9c3b6226e90ad56a418b865006b188b0aa0f54555f93" 182 | "b62809689b456854f2924b0936392abb862e896355739c9ccb843769775c3746" 183 | "7526ae7636489591ca7ba50f37c72b23b12f139357469242f060793ce9c90b49" 184 | "260116c117c04d80f609775472d7064dd7726311060678a0737e66aae9513710" 185 | "acce5931c6c32379444ab4d1340332b271c363a4a08502d4c398f4f839c01910" 186 | "313583748326d1f1a01d8cc99ab09faed03e80664044c62a97ec64c78b93bbfb" 187 | "59e6929d175c51918026fe923388425612926c24728eb9266725d1a0b6ba07a3" 188 | "5667602b61552533910c7e0edc8193f243f3a5bacffcbca9078ee0c600576593" 189 | "3359a6ca2133f86a4321946285d62c22489c74d3af723574b8e647a0183ffe05" 190 | "0a08331750f16c8032668a3a89be0458f89604001223667a2b8f825f892a222e" 191 | "aa8c8826a5903533571469088b5bbba8cf1947c43ebc9ba29cb308862e954ac9" 192 | "4a2170ef0b319a676c184022271c67e65404f86a2a3d607312e51e8e29bf70c1" 193 | "c78eb5000686b6578517f5f1162f0c558960c3de3a0a65885d246bcb8e8528b0" 194 | "7b18cf3485809cbe539113e33690f9132081a1115159845afa780f90ce09a0ab" 195 | "39fa8378d7c2313a1e4dec367d0401194352e5f638d06a09ce478dcfc4995a8a" 196 | "50aad1571b2607c251666b1375be98cca190af25893534e1bf0ff0b9152393b4" 197 | "b97c7fca4753a29c176831b91163fdd47cf833289ec98358608c3bc2321081ca" 198 | "5d4b962dd7ce91382fd82380e84c761d660d87bb1299a7196671105fa25c7cd6" 199 | "535935b69e036c09ea5fdc69ba198a92a3368a11469440b4cae7a9374123ac1c" 200 | "d958ed8bc2258aa9a8ac0d9c9296836c11e260900a23cd87f7b997c029d21c48" 201 | "570134987323fba507ddc40c7361bde775966628a8f5354db2cb44ba044cb287" 202 | "8162f32a82517036fa8ba38b0a9239caf393ce894cb51ae2038919614f315f21" 203 | "501af45b882630b606c6b701973ed76a7fd3070b5845b9f661bafef30beab81a" 204 | "3333609835030f4bc81c91cc8958996d098560063744b38cec1cc612b4c1b983" 205 | "3f2a7c3d2c67786b363788509dd9f0284a09150232a8f3a0ca0f190b0b0bbc56" 206 | "930fb8a6acb5d40a1f033fb2ab14791339d1fb98abcb51fc2a8b5d79c98a5a59" 207 | "7dfa07844c989e7015d2349b903068962498d7006ac17795c7f77ac8f97bcf44" 208 | "4e12e17936fa312ea27f22eb5ffc776a6f61681c37496b6cc437b54183c625b7" 209 | "8271e476b8f4377cf457369900cb78f911ab4a6f3868a2cf956f8a233277a492" 210 | "5f775e4127441794255ab0a7caec4484c374d9e57adbd24a97f81a482c77c9b0" 211 | "60f235bc63900bcf4b435edc66541696199c1bac788aa3796d7064822e411dea" 212 | "9433a18c991a0744b881076361cc740243763b3f4b2a672f0a36497241ae1cb7" 213 | "d2766f6bd68339f4230eb8bcb3743d5e71c217864e690929c1cba031402246ec" 214 | "ab7a452c19fc9511fc0f82581971975ed00772c789443aca822980629a6366cd" 215 | "b29728860bdcd24fd2eb8fe0b81f3c84b7fc53676863291ba0cf5e569230410e" 216 | "cb9a0cf3e65cae67bf7c3d6b1b726dc7a6bd4a437931ec6a9302629bca24276c" 217 | "536401d4a638430b27f9a343055a9fe5b109ad8897b993c2e66df5b07ae8f4a8" 218 | "7e385f73630001f67fa091f49a35284c088f1727f3818a78e174248229641389" 219 | ) 220 | 221 | ref_pub_key_768 = h2b( 222 | "72480a6256a076339b826c99e6866ef9e3519f10616558a13549878626cecb5b" 223 | "c4f4e9695b5baea55a9a9c3b6226e90ad56a418b865006b188b0aa0f54555f93" 224 | "b62809689b456854f2924b0936392abb862e896355739c9ccb843769775c3746" 225 | "7526ae7636489591ca7ba50f37c72b23b12f139357469242f060793ce9c90b49" 226 | "260116c117c04d80f609775472d7064dd7726311060678a0737e66aae9513710" 227 | "acce5931c6c32379444ab4d1340332b271c363a4a08502d4c398f4f839c01910" 228 | "313583748326d1f1a01d8cc99ab09faed03e80664044c62a97ec64c78b93bbfb" 229 | "59e6929d175c51918026fe923388425612926c24728eb9266725d1a0b6ba07a3" 230 | "5667602b61552533910c7e0edc8193f243f3a5bacffcbca9078ee0c600576593" 231 | "3359a6ca2133f86a4321946285d62c22489c74d3af723574b8e647a0183ffe05" 232 | "0a08331750f16c8032668a3a89be0458f89604001223667a2b8f825f892a222e" 233 | "aa8c8826a5903533571469088b5bbba8cf1947c43ebc9ba29cb308862e954ac9" 234 | "4a2170ef0b319a676c184022271c67e65404f86a2a3d607312e51e8e29bf70c1" 235 | "c78eb5000686b6578517f5f1162f0c558960c3de3a0a65885d246bcb8e8528b0" 236 | "7b18cf3485809cbe539113e33690f9132081a1115159845afa780f90ce09a0ab" 237 | "39fa8378d7c2313a1e4dec367d0401194352e5f638d06a09ce478dcfc4995a8a" 238 | "50aad1571b2607c251666b1375be98cca190af25893534e1bf0ff0b9152393b4" 239 | "b97c7fca4753a29c176831b91163fdd47cf833289ec98358608c3bc2321081ca" 240 | "5d4b962dd7ce91382fd82380e84c761d660d87bb1299a7196671105fa25c7cd6" 241 | "535935b69e036c09ea5fdc69ba198a92a3368a11469440b4cae7a9374123ac1c" 242 | "d958ed8bc2258aa9a8ac0d9c9296836c11e260900a23cd87f7b997c029d21c48" 243 | "570134987323fba507ddc40c7361bde775966628a8f5354db2cb44ba044cb287" 244 | "8162f32a82517036fa8ba38b0a9239caf393ce894cb51ae2038919614f315f21" 245 | "501af45b882630b606c6b701973ed76a7fd3070b5845b9f661bafef30beab81a" 246 | "3333609835030f4bc81c91cc8958996d098560063744b38cec1cc612b4c1b983" 247 | "3f2a7c3d2c67786b363788509dd9f0284a09150232a8f3a0ca0f190b0b0bbc56" 248 | "930fb8a6acb5d40a1f033fb2ab14791339d1fb98abcb51fc2a8b5d79c98a5a59" 249 | "7dfa07844c989e7015d2349b903068962498d7006ac17795c7f77ac8f97bcf44" 250 | "4e12e17936fa312ea27f22eb5ffc776a6f61681c37496b6cc437b54183c625b7" 251 | "8271e476b8f4377cf457369900cb78f911ab4a6f3868a2cf956f8a233277a492" 252 | "5f775e4127441794255ab0a7caec4484c374d9e57adbd24a97f81a482c77c9b0" 253 | "60f235bc63900bcf4b435edc66541696199c1bac788aa3796d7064822e411dea" 254 | "9433a18c991a0744b881076361cc740243763b3f4b2a672f0a36497241ae1cb7" 255 | "d2766f6bd68339f4230eb8bcb3743d5e71c217864e690929c1cba031402246ec" 256 | "ab7a452c19fc9511fc0f82581971975ed00772c789443aca822980629a6366cd" 257 | "b29728860bdcd24fd2eb8fe0b81f3c84b7fc53676863291ba0cf5e569230410e" 258 | "cb9a0cf3e65cae67bf7c3d6b1b726dc7a6bd4a437931ec6a9302629bca24276c" 259 | ) 260 | 261 | ref_ss_768 = h2b("8202089e59a4e5db7c979c49228804535fd5009ad4308edbbde843a38e1a9f56") 262 | 263 | ref_ct_768 = h2b( 264 | "3f520ff455db289ee0140e0b59dcf8792c819d48f487b4cca2ac5b04cb450248" 265 | "d269d9fcae46154c06fefbd465d2019c3b090148b1b02a9a3854cb137f98ff51" 266 | "db8ed422c940a14891e297ec192fe5755d486f9a0306f80fa88ebee8b86d1eb6" 267 | "5e5f6de3ac429c34f3fe1075a977c9d6b057203e7e7ace62ad0af4336cfeeada" 268 | "857c7f0c5e1e275244cc825adff3ab3c9922e3c0d3561667d2f6e23c072ec58e" 269 | "e7cae83760114980234394addbd1eadca155e0b498eb6746d870c7ffab390549" 270 | "d5f76f6579165655383659d88a9237c79c9a5a705bd180bc645b8c6b7eb0eb21" 271 | "c73122457d3532442b36a9b40b8f1c8a534055c39dc2f7e67bb44388310aefbc" 272 | "52747ac3c3111627e73580acc4d602047fde59f1a9df3770b1808b9d391db8c5" 273 | "6bcdc2ffaac52008de46a93aafa99c28e8ec5cc13ef6c3be553e85ed54fd6925" 274 | "4cddcdd2da55cb14c8ae057779336b4b679f480b325b20f894f695da139f57af" 275 | "569872f0849b1dabb8bcdc366d9de63b81c4420faa1b02a87261c58bae34c600" 276 | "41ced1e28a3122f2a89e8134c857f88cb79846ae8a468bdd029bc894a3a6b94c" 277 | "2758a3d0b02a4e36d49b02302c42ad1c63524d147c95e8b06a13a1e25b881120" 278 | "cb54af9e026424307454dacac3677bd28afbd11709587e5e08b06808de22dca4" 279 | "66d5a86b0487cdd0d7dfaaa84d7ed112cb1002c7a2811de6f307c994c5c063bd" 280 | "3c1cff803e5ce4d52d33511d5e17702bf8c21b654408034a00d38531c7a33f83" 281 | "157dcd3bf09308da29d8a32af03b39080b8f4a590b9d40173094c4b97bddcf03" 282 | "c10a5f5f024fbbb3e95ee21711c13b4e45f0da1797fb30b66571d7cecfddfa0f" 283 | "10eca7b3af7b19f1be1fe79abeec05076a34247e95a224f417efbf6863d80087" 284 | "19c536c226166c7a2a241c951bfb9f4535bd2919f6b82e60fc3b4c6f161ce5d7" 285 | "0b4a16cb8558624d4bf3b504f3f3c9cef4134f001c006c5107ec5a5adab557cb" 286 | "5ff79677f7542aa84b1aa89a33db7cc68f88a18323bd371cc6067e29ea1f6fab" 287 | "bd71508aa7ae4cbbf5b4a629d1896a7870ac567d146474759224decc01d86772" 288 | "5ea8c9fb0bc4b960c400db41400297b9e17978ba9cb23d2d01c1ed91651c84ed" 289 | "ab67cd754cb50905462de656c637d5b2d89a4b87cf846cbead8b1a3b03eb1b4b" 290 | "4b7eacaeba03f7d019fa677f9db5dfba3cbdaf0cb5027cc5c8b9854458065404" 291 | "9de07c405f1163970d21c5343f0b6002ed0da581269b80869e212c72d9920edc" 292 | "8360c292d2e5422fddce18b70e45eff0f7785993a3062e6da99a16482e177fc7" 293 | "9d1aef7a20c5bb681ff529e8f492aea21dc09072e81e1f34f7a615d0bf6a36ac" 294 | "63f47d609a2331e0b7973fdf0286aacaf4b12f3ed0a578bf4c6592ba90d4013f" 295 | "3633f66a15115dde3019f7263a94fc527f2a4bbaeae1a978ae3db279c17db178" 296 | "db999ad9665a1bb50e886de6886c4fdea1b4c55b229b9cf075a9eab897433c8d" 297 | "d842a370d9d826861447e0600c25e04564f7973116c57a83e528a440d664347a" 298 | ) 299 | 300 | ref_priv_key_1024 = h2b( 301 | "a454277ee55b9be091c8b1a41ca26db2ab1b888851749cc35f81aedcbc77d849" 302 | "a9a921481a8a636133121b4088795c12a6b84a9ae37591ea29107ca635275023" 303 | "04634d180ec7963e31e69a77ab2ff4b94bbb87501b1cb03024ce11b36016f479" 304 | "152653283551c96aa82801647f70abffb17dbf838fdc72152f215a7a976e0687" 305 | "850abc9b99b9c90bf7383930a3440c9d3328b8ba9a5ec0768fdbb28b6673c0f9" 306 | "e9314a1637064ccd2700608b093c007b23ec615871182216f5cb804ccd3155c9" 307 | "792b4817708c2c5c26b77b93d7c70b31231e7f5c27a6c5825b9939a0f31efd43" 308 | "993f894e9e799a893985987990e2bb9a10741ae56a85c21b51c84900fd3a30a4" 309 | "75af9e65a3df89b07d061738508feff113995348597999901607634386bd3900" 310 | "3f33099f273fa6c4cbaf7aa31e08686ed33a8f5c3792804fc5d4751631986c73" 311 | "1a63974e949cb8b075c81e7241491c87bc17cf78b520256a63a4db1d6d034b62" 312 | "565d8478b7b2eb3229129fdc34c78469c9b555052c66c54f83a7e53b7cb65b65" 313 | "8ec8bcb9d4bbd9288581b6a4f3fcabed34a4714cba14b7cc0f7a49a8c34034e3" 314 | "64b0f2abf061117bd23f65a98630ac259d186812a5a18ca322537b2576691acd" 315 | "c6ac1e13875837cc95291a5a62428908cf01749e86cb017da11fc325cf4135bd" 316 | "1b50828522875fd87cd1ab9ddd10cd303c387f66223c998d62a086631aa26d67" 317 | "214e971f82751f577312cf7a0b30d84844f3581963a4d63214c5f71dc75abc6d" 318 | "d8c2997c1fe22b70f7e579d041bcc6605b6ce740b57b6c3004c507b72f1e166e" 319 | "5e237e5b3830fc77261b9b57c173cba3b1ce429a2c1fc06529a64af99b28c583" 320 | "b731c5c76ecbb8a9e2ab799c11992bc249a929472a3c5f44c1371898ee07a1de" 321 | "b455de759362014082412dc0e7128cd66b5635a57139663d002307766ad81c04" 322 | "ce8a29a1aa2f65d13389226e2b5cce839896b16b4e701bad6ab1712bf601222b" 323 | "8f4bd5acfcf83f7db5760956b8189102bfb3c0962c2c3b1a6b0db54d770997f1" 324 | "d1a22596616b73071c60004c3b1c212b5066ab63ab71ad47262d7e426dcb96cb" 325 | "2a19281cac1af625068ed6a20ec66cd8d63a07dabe1aa1389ba437f0b3638d09" 326 | "23d3e2b078b44d44241f0073720e356f88d1b567b93c82e535abca1378f529d7" 327 | "04373d3bb540443f68d64a9134bd8a954669a725165a40f8aab9df93ce8970cd" 328 | "df5a15819783c2d13dd723b7c1d77d0978ccf896276400604a263d5e7b9b7a9b" 329 | "5392e0648da2852b32626c695dca229657894398b00ee691b07783bf157c040f" 330 | "58ca3cb260ad58a5c45bca73a0c59672a92f8c2c14fa6579cc1afce94f30b5ba" 331 | "431597791c619e32926c621aae6817d0751e672263f2270fc9e7c0f41c964fb9" 332 | "269bc908d62b9a47ca9c629b4ea53b91a4d65a2611b29f287a77dbbce4b3cd07" 333 | "f78f0500c8f3086afff146e3489e2fc8b6a5fabb801a5cf33785d34c6f7aa08c" 334 | "ccc091c3915cf2d882526a91288865e1389354d485b5c338700b7802422a3c90" 335 | "20c118847a7bb62e26288a4a4240010aa4393785d35b38729987c45636748776" 336 | "b373a2e545cff67b4c02225d25bfce75b916009d9aa97b370b444ea19f89bc4f" 337 | "efb6649f0c4a15951ac23198f882a2cae88dac171663391b78382e121933b062" 338 | "b6f895bd32d79ba4fa61d507171b1008dce364ed1c5d61b247415448408698be" 339 | "62024f57a6ccb2cf70108f1f59cc9972a365220636bc978dd994abe82e1cbb39" 340 | "aa37ca9d363f3c735cb26b29327b1e04f37a2919ccffcacea2ec4c7c83b87be0" 341 | "9c6fea1744b043080909d98039c91721a506cf271a5a5c122fb30b8a897c39fa" 342 | "28a60df28443a98ad408271a5538648c0775221db98944859755aca21db06286" 343 | "c553426af0c7a8864411f15af7853f201975b9e9c279ab0787230e514044d734" 344 | "9da8034431d7b199c00fe84a1a7c6693e3f5b5f4fb108305b24ccb1ff9621dfb" 345 | "3619cf5780ef06bc61db788063cae6e02f3aeb362ad4110f5c025e03d0f0e52f" 346 | "ced541865a912b777a8d92a936439155cc3a6543ad8055afa716472017548dfa" 347 | "cac6f305ee85c262d329edbc7fafc8ade4e0190204a43ed9673dfbac40b3ae42" 348 | "e50e10b6c2c05c8aa00776f176c13ed7c0ad5820620447f2ca20e7322cdef745" 349 | "41813a77a5536af20968a654e04c2e7ffb22a702739251b3b4f41f110aa8c3ab" 350 | "cd7798979ae7b204d05495655fc1c8bca0f37c1df96a194628e1aa457d1784a9" 351 | "64c6ce4a6eb8135e8c751b0c127ff4fa3939c23fad3a7e9ba08564e5bdd1862f" 352 | "6de7ca2984c8acfb26080c350b08a8ad01a63d2912f91255f21a95da042bfb72" 353 | "70d5168b41e48c894097ce10cae0a709f8898747a140a9b62616d22b05187a08" 354 | "b6102c88c4d5313d2fa137a13178aa5066f15856b2e68eefa36f867a9f477882" 355 | "21c10a36d508207984e4aa51847bab4966c3acf5b792ab9b0bd65827e172c313" 356 | "8f1e75328f4636dff7c6a4612b93b6940d5a5fcdb698df0b1453e4936d215be3" 357 | "a9c52210437fa7b363eac0edfba01ba29a26f1a82ec8218707b56c33b4c3831c" 358 | "7ddc1203cc57e7ca506b15730c49aeb71846fed8578158c3873a471625953d23" 359 | "9151e4b1aabc4d10e962d7c90c9f409d9cd5a73eecafcd58505387a3d452b62c" 360 | "900483f75924279259e72f8dd516b5377987c9b69a0963222815685070bd7723" 361 | "a48aa3489cc5760a00b35863dd620c96863d25a501744ab1d8a771407170971c" 362 | "53c3f9679cf95f73688cea6bcc04eb48a1e6c2d090ce882016f828432c218f9b" 363 | "a703f726176d9aa7a0f3b14ec617533b5e804a964e099a53301fbfe88c6bb40f" 364 | "a98273984a1dd9481f8a7b6a6d23a2ac1b471a46cb05d484db946551ac6a5e08" 365 | "880a41818c550e6a020c4366a416253ef18c835a185c6125b6367c7e1b1069aa" 366 | "028d56175f9d05048928a558b04e14eb7c6689a76c718288dc7a929c5681658b" 367 | "17f4cdf945632e93627b2611c03a6639115ff5a668fd4ba06994c8c8911bd007" 368 | "092b4496daaab7015165ec92cc4d459fcd811ddc41523d39744a186b3aba26c8" 369 | "1a4bb2c16968b61d1c0c9b6301c7d32411dd8b0dfb47184d5482fc23381043bd" 370 | "a7364a6ea07b0b29631780a5d83b6ec6258c27e4ca8734810ed1269e8982c07a" 371 | "0f27e234802aab8f377a9593597b6cb8c380cff188320fba37d026a7baa8ce61" 372 | "626922f2c6bc25c1284cbad077668ff96553434feb5703dbca92718a32e745a4" 373 | "ead790bf877c857533b3dc2091d11e33147bad00b789d6421a377d14118d6012" 374 | "c10f66678fa32412d243690b3123229f4a268e269c56f65525f4929e42463c81" 375 | "20adf7e0ade7992977166cd3e585a91420682953006a0c0b6caf277a928e1635" 376 | "bee2b07e630bf131711b3c92410c27005556fd68a5a41706ae0cbf595b62bf18" 377 | "42a0934631843570606d14c704c507806065154ad9c9c617138fcc0720f98dd0" 378 | "d0b5591002356a1b47217484857ce8a8ba69f85a72d102b2317ac6964334dc32" 379 | "a4b8699f6bc349a34afa01564df5c2c6a53ed4880ef7ca6408241d43a9c1a5da" 380 | "a529b9c62f0a966279a947d66c20dc185ef6b228909c16c6587a564d7f63a1dd" 381 | "841a32e6564ab22e936693e2c556c1664e59b85b2a4b27b71bb5ece1b36bca14" 382 | "3c4903d1b1cc5c716435e61c8aca0f5c7576147573413894cc8b06191890fbc6" 383 | "1ac8baafbf807586c683229205005c2124d1c54fc07febb79f3e38194bc9bf40" 384 | "039b5c3007ca551c106634fdc906bf43b4fad0425f189fb05a9c209bc953b02a" 385 | "74d4193a580ea86a0aa1f503560074b031c4f9c9c68e98596490c34a34a7e665" 386 | "0e147c714a326c93ba76aea90e8003083bca90e30bbff059a07f87caf9055828" 387 | "11236527cff99bca214565efd17d56721fbb6bce3d17a27a775309ecb78d620d" 388 | "d1d3b5b468790d337ef191af991609f90ba5ff3b3181882ff531635db917f18a" 389 | "0fcb7a2b1a828a14e1333b259126f7943f6a60b6e00c48375edce10c6463a592" 390 | "6308c639906b7770c531307f1a5e65335e64c4bc38dcca31128d06d09433d609" 391 | "9ea72a4d98858c691075a331ffd652d6102481b7063cf5193c192b0cecbe43a1" 392 | "0a574ca386ac89406c7fc405b3e6e873ae1493278095c10ccbb2c2582527a420" 393 | "18881f810fce011f29278cf4c04c6837c6c28589f9276704fb91d1973b042697" 394 | "1443996aeb269306b7b1283f05748e007b739c8521d690a387f908fce98a1527" 395 | "770a3443d345cf342a4f1af53cf23ab0ffc9c5fd26ceee0571bdc661f859a4e8" 396 | "399c86cc5017e51295011a6cc7926cd3136d4b809cb316d404a01892c8957343" 397 | "38f9336360afe8d97709a541b217491066de19c4f320b189f6e0bcb3753f25bc" 398 | "e98de871560bdc365cefcd41589b71be09d91a66e97559cc506745b8f11b78f5" 399 | "7e385f73630001f67fa091f49a35284c088f1727f3818a78e174248229641389" 400 | ) 401 | 402 | ref_pub_key_1024 = h2b( 403 | "41813a77a5536af20968a654e04c2e7ffb22a702739251b3b4f41f110aa8c3ab" 404 | "cd7798979ae7b204d05495655fc1c8bca0f37c1df96a194628e1aa457d1784a9" 405 | "64c6ce4a6eb8135e8c751b0c127ff4fa3939c23fad3a7e9ba08564e5bdd1862f" 406 | "6de7ca2984c8acfb26080c350b08a8ad01a63d2912f91255f21a95da042bfb72" 407 | "70d5168b41e48c894097ce10cae0a709f8898747a140a9b62616d22b05187a08" 408 | "b6102c88c4d5313d2fa137a13178aa5066f15856b2e68eefa36f867a9f477882" 409 | "21c10a36d508207984e4aa51847bab4966c3acf5b792ab9b0bd65827e172c313" 410 | "8f1e75328f4636dff7c6a4612b93b6940d5a5fcdb698df0b1453e4936d215be3" 411 | "a9c52210437fa7b363eac0edfba01ba29a26f1a82ec8218707b56c33b4c3831c" 412 | "7ddc1203cc57e7ca506b15730c49aeb71846fed8578158c3873a471625953d23" 413 | "9151e4b1aabc4d10e962d7c90c9f409d9cd5a73eecafcd58505387a3d452b62c" 414 | "900483f75924279259e72f8dd516b5377987c9b69a0963222815685070bd7723" 415 | "a48aa3489cc5760a00b35863dd620c96863d25a501744ab1d8a771407170971c" 416 | "53c3f9679cf95f73688cea6bcc04eb48a1e6c2d090ce882016f828432c218f9b" 417 | "a703f726176d9aa7a0f3b14ec617533b5e804a964e099a53301fbfe88c6bb40f" 418 | "a98273984a1dd9481f8a7b6a6d23a2ac1b471a46cb05d484db946551ac6a5e08" 419 | "880a41818c550e6a020c4366a416253ef18c835a185c6125b6367c7e1b1069aa" 420 | "028d56175f9d05048928a558b04e14eb7c6689a76c718288dc7a929c5681658b" 421 | "17f4cdf945632e93627b2611c03a6639115ff5a668fd4ba06994c8c8911bd007" 422 | "092b4496daaab7015165ec92cc4d459fcd811ddc41523d39744a186b3aba26c8" 423 | "1a4bb2c16968b61d1c0c9b6301c7d32411dd8b0dfb47184d5482fc23381043bd" 424 | "a7364a6ea07b0b29631780a5d83b6ec6258c27e4ca8734810ed1269e8982c07a" 425 | "0f27e234802aab8f377a9593597b6cb8c380cff188320fba37d026a7baa8ce61" 426 | "626922f2c6bc25c1284cbad077668ff96553434feb5703dbca92718a32e745a4" 427 | "ead790bf877c857533b3dc2091d11e33147bad00b789d6421a377d14118d6012" 428 | "c10f66678fa32412d243690b3123229f4a268e269c56f65525f4929e42463c81" 429 | "20adf7e0ade7992977166cd3e585a91420682953006a0c0b6caf277a928e1635" 430 | "bee2b07e630bf131711b3c92410c27005556fd68a5a41706ae0cbf595b62bf18" 431 | "42a0934631843570606d14c704c507806065154ad9c9c617138fcc0720f98dd0" 432 | "d0b5591002356a1b47217484857ce8a8ba69f85a72d102b2317ac6964334dc32" 433 | "a4b8699f6bc349a34afa01564df5c2c6a53ed4880ef7ca6408241d43a9c1a5da" 434 | "a529b9c62f0a966279a947d66c20dc185ef6b228909c16c6587a564d7f63a1dd" 435 | "841a32e6564ab22e936693e2c556c1664e59b85b2a4b27b71bb5ece1b36bca14" 436 | "3c4903d1b1cc5c716435e61c8aca0f5c7576147573413894cc8b06191890fbc6" 437 | "1ac8baafbf807586c683229205005c2124d1c54fc07febb79f3e38194bc9bf40" 438 | "039b5c3007ca551c106634fdc906bf43b4fad0425f189fb05a9c209bc953b02a" 439 | "74d4193a580ea86a0aa1f503560074b031c4f9c9c68e98596490c34a34a7e665" 440 | "0e147c714a326c93ba76aea90e8003083bca90e30bbff059a07f87caf9055828" 441 | "11236527cff99bca214565efd17d56721fbb6bce3d17a27a775309ecb78d620d" 442 | "d1d3b5b468790d337ef191af991609f90ba5ff3b3181882ff531635db917f18a" 443 | "0fcb7a2b1a828a14e1333b259126f7943f6a60b6e00c48375edce10c6463a592" 444 | "6308c639906b7770c531307f1a5e65335e64c4bc38dcca31128d06d09433d609" 445 | "9ea72a4d98858c691075a331ffd652d6102481b7063cf5193c192b0cecbe43a1" 446 | "0a574ca386ac89406c7fc405b3e6e873ae1493278095c10ccbb2c2582527a420" 447 | "18881f810fce011f29278cf4c04c6837c6c28589f9276704fb91d1973b042697" 448 | "1443996aeb269306b7b1283f05748e007b739c8521d690a387f908fce98a1527" 449 | "770a3443d345cf342a4f1af53cf23ab0ffc9c5fd26ceee0571bdc661f859a4e8" 450 | "399c86cc5017e51295011a6cc7926cd3136d4b809cb316d404a01892c8957343" 451 | "38f9336360afe8d97709a541b217491066de19c4f320b189f6e0bcb3753f25bc" 452 | ) 453 | 454 | ref_ss_1024 = h2b( 455 | "6fd1e1e9b9933ff892a120874aa337b00aa15c78f17685ec6bbb538f3a292444" 456 | ) 457 | 458 | ref_ct_1024 = h2b( 459 | "52d4997fb1cc24a519bd079379d99949dfcb85cb9df2e8ada7adf734c2912e71" 460 | "93ed9d03d1fd9c656be27b493df0dc876c4734ecdefda53e39feaa7b48e496cb" 461 | "a62fd8c9fd646230e373e84312b7aa6617313b515b10e34a5335031ed62e8dcb" 462 | "934644d2d15508c1b06dc7117e20f74c25260695bfabefcbfd4cc2288e11228c" 463 | "8e904ff8dc3599f2ddfe8b977321bf4ab4baec12121a6dce4e1c9f6f07a84c69" 464 | "1dd97ccc681d05641c66bdb7b0129f424a5718e7adf00cef7a3cb276b90d136f" 465 | "b43cfafed8e20b25a4a739bfd0feeb99d1136adf901f04737db09d4cc52383b7" 466 | "e9a90f162e524ea6851712a743ce81f2ccf5957b7ace529c0a9614c258e52952" 467 | "859eeca3028d3c2c4f85f0f3c93a67366ca86c649f6b23343127cee76bd85f7e" 468 | "50de35853e5ca4bf9cdc4dc4a7f77e2fc1e0eb2e1b6bc9ab4e5e67313e165a9d" 469 | "0abffc611a6d0a106181445cc084ae7d5f5f8cd18d1230dab8bb052788c990f9" 470 | "0f533cf9222e9f3db7d0c0e660053419b9d616eb030b9e9dedc2f0f811df2135" 471 | "d8c490f319aed216bff22661cc4ea51ea6ae84f9b0646474d756581cbde17e9f" 472 | "4352d7bed6d19df08900ea6021e94432611bcced4afc24a40c09c979ab0d8eab" 473 | "f848c4323fcb71d04cee30c3280109db6e6c3db04dc82af2bfb62c0b7d478635" 474 | "940c1995e4d3c3e0893d421cf72fa89be0861cd33c2dca4ed1547fd2125a67b4" 475 | "03910ecdc00654c0579f4190e8f52bba14f83acb31160f425903c3db92b937df" 476 | "be1e8f24be9eda5b5a29374e801af2d5dbfc5eac7e16ea8180a7032a4d295d5d" 477 | "d7a1fb6c3f0563daae680d1fefe4cd3504e05599bb1ebb03ab9e8a06ae944c26" 478 | "b8c3677c358234936d5af1bfd5d081445f05979c07e8db65c8106ea0aad87eef" 479 | "33e6b4d1b0164e4a7ae2c7cebbd8b5d50c8e3f28d1b5ffef0f062f13ffc4b05b" 480 | "e4319b1034d3a93b1948923cb5d94c94dd704763241107e588ad8e5e20d9f242" 481 | "7282236682efc4b7c9074b6b4b12484331ea82b950601e6eb535722f7fe47489" 482 | "d87a6d56d61d8a370f4d71ad9e56c7ee3ce0d5eb77c2c8e35a99a6f8b3b6f7d9" 483 | "5a03d1478da1e96277b4861a322b05595bf30243c38664316ec4102a812a1ad1" 484 | "258241f8ca598fcb6b56087b16957ce1c0b46c0eb2109364c344918d12328132" 485 | "164065bef16856beadcb5ac485147e3d94bc75c4006113d523afeca534791b56" 486 | "c43c3085205734d53f19cb1501c53b1fe0c5a53661ea23d2e4f8eee908bbf83d" 487 | "e7dc6b5cd4f3800e88bfe2403b018d5115378131db0cd2d241954922bf2ebda7" 488 | "007b2f8333c76576a5dde36556d195d6495745f729e8f77eeeac76044dead4ac" 489 | "e33f20ed47403a7e91c90bd17bb288afe0bd8baa82246d83118d6ace95f66303" 490 | "90301c30f7e84cd9db647fd5af28664057d7f0cb9a7d72cb365ebd58aab478bd" 491 | "6b56b6135cc2f453c9d10168e0dc7877d888d27e0126798e1ae1d5a2fa76f814" 492 | "8caf37358a9720f3fe8a3b3f0a0a2de800befd550f7fa2b3c5b6ab20faf77103" 493 | "845a49de41c3ada2f30f6fc4dfe85d263ec780e2d23da44d890146ff16355863" 494 | "d22c2696d486bdbe86c8929dec7380f3b944db446928e43f4ac9c0fe91a019b2" 495 | "82786631950873ad8f9a682a194eaedfd03db093d0caacf0a15583d9dae39cc0" 496 | "65bee2c978bce4c63b7487eb9069e7b82153111766dad4fea1f285e23d8c8e69" 497 | "24c6ef27df239d91e0e7b8bf9a6c8756d59145f09be9ec82b4900679ef0b7485" 498 | "b1dbdf2c7a4df6551d07ae634dacf635935e2b5ac7754f1f2214076b043da4f0" 499 | "98279480e876e10a02c02cfd1747aa91ab490dc0fcadf83e34d7226f72808cec" 500 | "baecfb2b13e08e5698f59897c3b1678697403b1b535ed7796b6370162aca7e5e" 501 | "3835ea6155dae0959d1e1799437b197d091833e055fa4a5703bf6b53c35552a2" 502 | "b73da0712207e23f40b818f2d0a7fc57b344c2f5216d230218a9926c83b44ffe" 503 | "532e4f90f736243e6d27edde14deae75d595731519b9ec44f4d48fa6ea79c105" 504 | "06d782ec071300e30a0f0f4cc501a676d4b9a6476d954f0a9b3b7eb01c210e6f" 505 | "cb4f0ba36d042b3f04e37f2aa2737543feb7a133c992ba77f7ab02228c0068d1" 506 | "c926ef22b074b2a90ae0da557bb8fc3248a53e606ee06dd138a512d0ba9e40ab" 507 | "cdac31c7b5404a0a57bd34fd18ebfbac98cc41dc2f6dcc6b561081c877c5e70c" 508 | ) 509 | 510 | # This random number is common among MlKemType.{ML_KEM_512, ML_KEM_768, ML_KEM_1024}. 511 | ref_rand_for_make_key = h2b( 512 | "d0978f5fcb5109d016f199d5d357184e1490fdf772005385d1d22f507d34acf8" 513 | "7e385f73630001f67fa091f49a35284c088f1727f3818a78e174248229641389" 514 | ) 515 | 516 | # This random number is common among MlKemType.{ML_KEM_512, ML_KEM_768, ML_KEM_1024}. 517 | ref_rand_for_encap = h2b( 518 | "91a244f62ab68f42c5b3a6816bd491332f133a69d87e58ce76b26e026d3c0e1e" 519 | ) 520 | 521 | ref_priv_key = { 522 | MlKemType.ML_KEM_512: ref_priv_key_512, 523 | MlKemType.ML_KEM_768: ref_priv_key_768, 524 | MlKemType.ML_KEM_1024: ref_priv_key_1024, 525 | } 526 | 527 | ref_pub_key = { 528 | MlKemType.ML_KEM_512: ref_pub_key_512, 529 | MlKemType.ML_KEM_768: ref_pub_key_768, 530 | MlKemType.ML_KEM_1024: ref_pub_key_1024, 531 | } 532 | 533 | ref_ss = { 534 | MlKemType.ML_KEM_512: ref_ss_512, 535 | MlKemType.ML_KEM_768: ref_ss_768, 536 | MlKemType.ML_KEM_1024: ref_ss_1024, 537 | } 538 | 539 | ref_ct = { 540 | MlKemType.ML_KEM_512: ref_ct_512, 541 | MlKemType.ML_KEM_768: ref_ct_768, 542 | MlKemType.ML_KEM_1024: ref_ct_1024, 543 | } 544 | 545 | mlkem_types = [ 546 | (MlKemType.ML_KEM_512), 547 | (MlKemType.ML_KEM_768), 548 | (MlKemType.ML_KEM_1024), 549 | ] 550 | 551 | @pytest.mark.parametrize("mlkem_type", mlkem_types) 552 | def test_init_pattern_1(mlkem_type): 553 | mlkem_priv = MlKemPrivate(mlkem_type) 554 | assert type(mlkem_priv) is MlKemPrivate 555 | mlkem_priv.decode_key(ref_priv_key[mlkem_type]) 556 | assert mlkem_priv.encode_priv_key() == ref_priv_key[mlkem_type] 557 | pub_key = mlkem_priv.encode_pub_key() 558 | assert pub_key == ref_pub_key[mlkem_type] 559 | 560 | mlkem_pub = MlKemPublic(mlkem_type) 561 | assert type(mlkem_pub) is MlKemPublic 562 | mlkem_pub.decode_key(pub_key) 563 | assert mlkem_pub.encode_key() == ref_pub_key[mlkem_type] 564 | 565 | ss_send, ct = mlkem_pub.encapsulate() 566 | ss_recv = mlkem_priv.decapsulate(ct) 567 | assert ss_send == ss_recv 568 | 569 | ss_send, ct = mlkem_pub.encapsulate_with_random(ref_rand_for_encap) 570 | assert ct == ref_ct[mlkem_type] 571 | ss_recv = mlkem_priv.decapsulate(ct) 572 | assert ss_send == ref_ss[mlkem_type] 573 | assert ss_send == ss_recv 574 | 575 | @pytest.mark.parametrize("mlkem_type", mlkem_types) 576 | def test_init_pattern_2(mlkem_type): 577 | mlkem_priv = MlKemPrivate.make_key_with_random( 578 | mlkem_type, ref_rand_for_make_key 579 | ) 580 | assert type(mlkem_priv) is MlKemPrivate 581 | assert mlkem_priv.encode_priv_key() == ref_priv_key[mlkem_type] 582 | pub_key = mlkem_priv.encode_pub_key() 583 | assert pub_key == ref_pub_key[mlkem_type] 584 | 585 | mlkem_pub = MlKemPublic(mlkem_type) 586 | assert type(mlkem_pub) is MlKemPublic 587 | mlkem_pub.decode_key(pub_key) 588 | assert mlkem_pub.encode_key() == ref_pub_key[mlkem_type] 589 | 590 | ss_send, ct = mlkem_pub.encapsulate() 591 | ss_recv = mlkem_priv.decapsulate(ct) 592 | assert ss_send == ss_recv 593 | 594 | ss_send, ct = mlkem_pub.encapsulate_with_random(ref_rand_for_encap) 595 | assert ct == ref_ct[mlkem_type] 596 | ss_recv = mlkem_priv.decapsulate(ct) 597 | assert ss_send == ref_ss[mlkem_type] 598 | assert ss_send == ss_recv 599 | 600 | @pytest.mark.parametrize("mlkem_type", mlkem_types) 601 | def test_init_pattern_3(mlkem_type): 602 | mlkem_priv = MlKemPrivate.make_key(mlkem_type) 603 | assert type(mlkem_priv) is MlKemPrivate 604 | mlkem_priv.encode_priv_key() 605 | pub_key = mlkem_priv.encode_pub_key() 606 | 607 | mlkem_pub = MlKemPublic(mlkem_type) 608 | assert type(mlkem_pub) is MlKemPublic 609 | mlkem_pub.decode_key(pub_key) 610 | 611 | ss_send, ct = mlkem_pub.encapsulate() 612 | ss_recv = mlkem_priv.decapsulate(ct) 613 | assert ss_send == ss_recv 614 | 615 | ss_send, ct = mlkem_pub.encapsulate_with_random(ref_rand_for_encap) 616 | ss_recv = mlkem_priv.decapsulate(ct) 617 | assert ss_send == ss_recv 618 | 619 | @pytest.mark.parametrize("mlkem_type", mlkem_types) 620 | def test_size_properties(mlkem_type): 621 | refvals = { 622 | MlKemType.ML_KEM_512: { 623 | "pub_key_size": 800, 624 | "priv_key_size": 1632, 625 | "ct_size": 768, 626 | "ss_size": 32, 627 | }, 628 | MlKemType.ML_KEM_768: { 629 | "pub_key_size": 1184, 630 | "priv_key_size": 2400, 631 | "ct_size": 1088, 632 | "ss_size": 32, 633 | }, 634 | MlKemType.ML_KEM_1024: { 635 | "pub_key_size": 1568, 636 | "priv_key_size": 3168, 637 | "ct_size": 1568, 638 | "ss_size": 32, 639 | }, 640 | } 641 | 642 | mlkem_pub = MlKemPublic(mlkem_type) 643 | assert mlkem_pub.key_size == refvals[mlkem_type]["pub_key_size"] 644 | assert mlkem_pub.ct_size == refvals[mlkem_type]["ct_size"] 645 | assert mlkem_pub.ss_size == refvals[mlkem_type]["ss_size"] 646 | 647 | mlkem_priv = MlKemPrivate(mlkem_type) 648 | assert mlkem_priv.pub_key_size == refvals[mlkem_type]["pub_key_size"] 649 | assert mlkem_priv.priv_key_size == refvals[mlkem_type]["priv_key_size"] 650 | assert mlkem_priv.ct_size == refvals[mlkem_type]["ct_size"] 651 | assert mlkem_priv.ss_size == refvals[mlkem_type]["ss_size"] 652 | -------------------------------------------------------------------------------- /tests/test_pwdbased.py: -------------------------------------------------------------------------------- 1 | # test_pwdbased.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=redefined-outer-name 22 | from collections import namedtuple 23 | import pytest 24 | from wolfcrypt._ffi import lib as _lib 25 | 26 | if _lib.PWDBASED_ENABLED: 27 | from wolfcrypt.pwdbased import PBKDF2 28 | 29 | if _lib.SHA_ENABLED: 30 | from wolfcrypt.hashes import Sha 31 | if _lib.HMAC_ENABLED: 32 | from wolfcrypt.hashes import HmacSha 33 | 34 | @pytest.fixture 35 | def pbkdf2_vectors(): 36 | TestVector = namedtuple("TestVector", """password salt iterations key_length 37 | hash_type""") 38 | TestVector.__new__.__defaults__ = (None,) * len(TestVector._fields) 39 | 40 | vectors = [] 41 | 42 | if _lib.PWDBASED_ENABLED and _lib.SHA_ENABLED and _lib.HMAC_ENABLED: 43 | # HMAC requires a key, which in this case is the password. Do not 44 | # shorten the length of the password below the FIPS requirement. 45 | # See HMAC_FIPS_MIN_KEY. 46 | vectors.append(TestVector( 47 | password="wolfcrypt is the best crypto around", 48 | salt="salt1234", 49 | iterations=1000, 50 | key_length=Sha.digest_size, 51 | hash_type=HmacSha._type 52 | )) 53 | 54 | return vectors 55 | 56 | def test_pbkdf2(pbkdf2_vectors): 57 | for vector in pbkdf2_vectors: 58 | key = PBKDF2(vector.password, vector.salt, vector.iterations, 59 | vector.key_length, vector.hash_type) 60 | assert len(key) == vector.key_length 61 | -------------------------------------------------------------------------------- /tests/test_random.py: -------------------------------------------------------------------------------- 1 | # test_random.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=redefined-outer-name 22 | 23 | import pytest 24 | from wolfcrypt.random import Random 25 | 26 | 27 | @pytest.fixture 28 | def rng(): 29 | return Random() 30 | 31 | 32 | def test_byte(rng): 33 | assert len(rng.byte()) == 1 34 | 35 | 36 | def test_bytes(rng): 37 | assert len(rng.bytes(1)) == 1 38 | assert len(rng.bytes(8)) == 8 39 | assert len(rng.bytes(128)) == 128 40 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py3 3 | 4 | [testenv] 5 | wheel = true 6 | 7 | deps = -rrequirements/test.txt 8 | commands = py.test tests/ 9 | -------------------------------------------------------------------------------- /windows/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This directory contains user_settings.h files that can be used to build wolfSSL 4 | on Windows for use with wolfcrypt-py. non_fips/user_settings.h is, as the name 5 | indicates, intended for non-FIPS builds. fips_ready/user_settings.h is for FIPS 6 | Ready builds. non_fips/user_settings.h is used by build_ffi.py when building 7 | wolfcrypt-py on Windows without USE_LOCAL_WOLFSSL. fips_ready/user_settings.h 8 | isn't used by build_ffi.py. 9 | 10 | ## Non-FIPS 11 | 12 | If building with our wolfssl64.sln Visual Studio solution, copy 13 | non_fips\user_settings.h into IDE\WIN in the wolfSSL directory, overwriting the 14 | existing user_settings.h. Build the solution, set the environment variable 15 | USE_LOCAL_WOLFSSL to point to the wolfSSL directory, and proceed with the 16 | wolfcrypt-py build/install (e.g. `pip install .` from the wolfcrypt-py 17 | directory). 18 | 19 | ## FIPS Ready 20 | 21 | The instructions are similar to the non-FIPS instructions. Copy 22 | fips_ready\user_settings.h into IDE\WIN10. Build the IDE\WIN10\wolfssl-fips.sln 23 | solution. Set the environment variable USE_LOCAL_WOLFSSL to point to the wolfSSL 24 | directory, and proceed with the wolfcrypt-py build/install (e.g. `pip install .` 25 | from the wolfcrypt-py directory). 26 | -------------------------------------------------------------------------------- /windows/fips_ready/user_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef _FIPS_READY_USER_SETTINGS_H_ 2 | #define _FIPS_READY_USER_SETTINGS_H_ 3 | 4 | /* Verify this is Windows */ 5 | #ifndef _WIN32 6 | #error This user_settings.h header is only designed for Windows 7 | #endif 8 | 9 | #undef HAVE_FIPS 10 | #define HAVE_FIPS 11 | #undef HAVE_FIPS_VERSION 12 | #define HAVE_FIPS_VERSION 5 13 | #undef HAVE_FIPS_VERSION_MINOR 14 | #define HAVE_FIPS_VERSION_MINOR 3 15 | 16 | #define WOLFCRYPT_ONLY 17 | #define HAVE_HASHDRBG 18 | #define WOLFSSL_AES_DIRECT 19 | #define WOLFSSL_AESGCM_STREAM 20 | #define HAVE_AESGCM 21 | #define GCM_TABLE_4BIT 22 | #define WOLFSSL_AES_COUNTER 23 | #define WOLFSSL_SHA224 24 | #define WOLFSSL_SHA384 25 | #define WOLFSSL_SHA512 26 | #define WOLFSSL_SHA3 27 | #define HAVE_HKDF 28 | #define WOLFSSL_NO_SHAKE256 29 | #define WC_RSA_PSS 30 | #define WOLFSSL_PSS_LONG_SALT 31 | #define HAVE_ECC 32 | #define WOLFSSL_VALIDATE_ECC_KEYGEN 33 | #define WOLFSSL_ECDSA_SET_K 34 | #define ECC_USER_CURVES 35 | #define HAVE_ECC192 36 | #define HAVE_ECC224 37 | #define HAVE_ECC256 38 | #define HAVE_ECC384 39 | #define HAVE_ECC521 40 | #define WOLFSSL_KEY_GEN 41 | #define WOLFSSL_PUBLIC_MP 42 | #define WC_RNG_SEED_CB 43 | #define FP_MAX_BITS 16384 44 | #define WC_RSA_BLINDING 45 | #define ECC_TIMING_RESISTANT 46 | #define NO_MD5 47 | #define NO_DES3 48 | #define NO_MD4 49 | #define NO_DSA 50 | #define NO_OLD_TLS 51 | #define NO_OLD_RNGNAME 52 | #define NO_OLD_WC_NAMES 53 | #define NO_OLD_SSL_NAMES 54 | #define NO_OLD_SHA_NAMES 55 | #define NO_OLD_MD5_NAME 56 | #define NO_ERROR_STRINGS 57 | 58 | #endif /* _FIPS_READY_USER_SETTINGS_H_ */ 59 | -------------------------------------------------------------------------------- /windows/non_fips/user_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef _NON_FIPS_USER_SETTINGS_H_ 2 | #define _NON_FIPS_USER_SETTINGS_H_ 3 | 4 | #ifndef _WIN32 5 | #error This user_settings.h header is only designed for Windows 6 | #endif 7 | 8 | #define WOLFCRYPT_ONLY 9 | #define WOLFSSL_AESGCM_STREAM 10 | #define HAVE_AESGCM 11 | #define GCM_TABLE_4BIT 12 | #define WOLFSSL_AES_COUNTER 13 | #define WOLFSSL_AES_OFB 14 | #define HAVE_CHACHA 15 | #define HAVE_POLY1305 16 | #define WOLFSSL_SHA384 17 | #define WOLFSSL_SHA512 18 | #define WOLFSSL_SHA3 19 | #define WOLFSSL_SHA224 20 | #define WOLFSSL_NO_SHAKE256 21 | #define NO_MD5 22 | #define HAVE_HKDF 23 | #define NO_OLD_TLS 24 | #define WC_RSA_PSS 25 | #define WOLFSSL_PSS_LONG_SALT 26 | #define HAVE_ECC 27 | #define WOLFSSL_VALIDATE_ECC_KEYGEN 28 | #define WOLFSSL_ECDSA_SET_K 29 | #define ECC_USER_CURVES 30 | #define HAVE_ECC192 31 | #define HAVE_ECC224 32 | #define HAVE_ECC256 33 | #define HAVE_ECC384 34 | #define HAVE_ECC521 35 | #define HAVE_ED25519 36 | #define HAVE_CURVE25519 37 | #define WOLFSSL_KEY_GEN 38 | #define NO_OLD_RNGNAME 39 | #define NO_OLD_WC_NAMES 40 | #define NO_OLD_SSL_NAMES 41 | #define NO_OLD_SHA_NAMES 42 | #define NO_OLD_MD5_NAME 43 | #define NO_ERROR_STRINGS 44 | #define WOLFSSL_PUBLIC_MP 45 | #define FP_MAX_BITS 16384 46 | #define WC_RSA_BLINDING 47 | #define ECC_TIMING_RESISTANT 48 | 49 | /* PKCS7 requirements */ 50 | #define HAVE_PKCS7 51 | #define HAVE_AES_KEYWRAP 52 | #define WOLFSSL_AES_DIRECT 53 | #define HAVE_X963_KDF 54 | 55 | #endif /* _NON_FIPS_USER_SETTINGS_H_ */ 56 | -------------------------------------------------------------------------------- /wolfcrypt/__init__.py: -------------------------------------------------------------------------------- 1 | # __init__.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | from wolfcrypt._version import __version__, __wolfssl_version__ 22 | 23 | __title__ = "wolfcrypt" 24 | __summary__ = "Python module that encapsulates wolfSSL's crypto engine API." 25 | __uri__ = "https://github.com/wolfssl/wolfcrypt-py" 26 | 27 | __author__ = "wolfSSL Inc." 28 | __email__ = "info@wolfssl.com" 29 | 30 | __license__ = "GPLv2 or Commercial License" 31 | __copyright__ = "Copyright (C) 2006-2022 wolfSSL Inc" 32 | 33 | __all__ = [ 34 | "__title__", "__summary__", "__uri__", "__version__", 35 | "__author__", "__email__", "__license__", "__copyright__", 36 | "ciphers", "hashes", "random", "pwdbased" 37 | ] 38 | 39 | import os 40 | import sys 41 | 42 | top_level_py = os.path.basename(sys.argv[0]) 43 | 44 | # The code below is intended to only be used after the CFFI is built, so we 45 | # don't want it invoked whilst building the CFFI with build_ffi.py or setup.py. 46 | if top_level_py not in ["setup.py", "build_ffi.py"]: 47 | from wolfcrypt._ffi import ffi as _ffi 48 | from wolfcrypt._ffi import lib as _lib 49 | 50 | if hasattr(_lib, 'WC_RNG_SEED_CB_ENABLED'): 51 | if _lib.WC_RNG_SEED_CB_ENABLED: 52 | ret = _lib.wc_SetSeed_Cb(_ffi.addressof(_lib, "wc_GenerateSeed")) 53 | if ret < 0: 54 | raise WolfCryptError("wc_SetSeed_Cb failed (%d)" % ret) 55 | if _lib.FIPS_ENABLED and _lib.FIPS_VERSION >= 5: 56 | ret = _lib.wolfCrypt_SetPrivateKeyReadEnable_fips(1, 57 | _lib.WC_KEYTYPE_ALL); 58 | if ret < 0: 59 | raise WolfCryptError("wolfCrypt_SetPrivateKeyReadEnable_fips failed" 60 | " (%d)" % ret) 61 | -------------------------------------------------------------------------------- /wolfcrypt/_version.py: -------------------------------------------------------------------------------- 1 | # When bumping the C library version, reset the POST count to 0 2 | 3 | __wolfssl_version__ = "v5.7.4-stable" 4 | 5 | # We're using implicit post releases [PEP 440] to bump package version 6 | # while maintaining the C library version intact for better reference. 7 | # https://www.python.org/dev/peps/pep-0440/#implicit-post-releases 8 | # 9 | # MAJOR.MINOR.BUILD-POST 10 | 11 | __version__ = "5.7.4-0" 12 | 13 | -------------------------------------------------------------------------------- /wolfcrypt/asn.py: -------------------------------------------------------------------------------- 1 | # asn.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=no-member,no-name-in-module 22 | 23 | from wolfcrypt._ffi import ffi as _ffi 24 | from wolfcrypt._ffi import lib as _lib 25 | from wolfcrypt.exceptions import WolfCryptError 26 | 27 | if _lib.SHA_ENABLED: 28 | from wolfcrypt.hashes import Sha 29 | if _lib.SHA256_ENABLED: 30 | from wolfcrypt.hashes import Sha256 31 | if _lib.SHA384_ENABLED: 32 | from wolfcrypt.hashes import Sha384 33 | if _lib.SHA512_ENABLED: 34 | from wolfcrypt.hashes import Sha512 35 | 36 | if _lib.ASN_ENABLED: 37 | def pem_to_der(pem, pem_type): 38 | der = _ffi.new("DerBuffer**") 39 | ret = _lib.wc_PemToDer(pem, len(pem), pem_type, der, _ffi.NULL, 40 | _ffi.NULL, _ffi.NULL) 41 | if ret != 0: 42 | err = "Error converting from PEM to DER. ({})".format(ret) 43 | raise WolfCryptError(err) 44 | 45 | return _ffi.buffer(der[0][0].buffer, der[0][0].length)[:] 46 | 47 | def der_to_pem(der, pem_type): 48 | pem_length = _lib.wc_DerToPemEx(der, len(der), _ffi.NULL, 0, _ffi.NULL, 49 | pem_type) 50 | if pem_length <= 0: 51 | err = "Error getting required PEM buffer length. ({})".format(pem_length) 52 | raise WolfCryptError(err) 53 | 54 | pem = _ffi.new("byte[%d]" % pem_length) 55 | pem_length = _lib.wc_DerToPemEx(der, len(der), pem, pem_length, 56 | _ffi.NULL, pem_type) 57 | if pem_length <= 0: 58 | err = "Error converting from DER to PEM. ({})".format(pem_length) 59 | raise WolfCryptError(err) 60 | 61 | return _ffi.buffer(pem, pem_length)[:] 62 | 63 | def hash_oid_from_class(hash_cls): 64 | if hash_cls == Sha: 65 | return _lib.SHAh 66 | elif hash_cls == Sha256: 67 | return _lib.SHA256h 68 | elif hash_cls == Sha384: 69 | return _lib.SHA384h 70 | elif hash_cls == Sha512: 71 | return _lib.SHA512h 72 | else: 73 | err = "Unknown hash class {}.".format(hash_cls.__name__) 74 | raise WolfCryptError(err) 75 | 76 | def make_signature(data, hash_cls, key=None): 77 | hash_obj = hash_cls() 78 | hash_obj.update(data) 79 | digest = hash_obj.digest() 80 | 81 | plaintext_sig = _ffi.new("byte[%d]" % _lib.MAX_DER_DIGEST_SZ) 82 | hash_oid = hash_oid_from_class(hash_cls) 83 | plaintext_len = _lib.wc_EncodeSignature(plaintext_sig, digest, 84 | len(digest), hash_oid) 85 | if plaintext_len == 0: 86 | err = "Error calling wc_EncodeSignature. ({})".format(plaintext_len) 87 | raise WolfCryptError(err) 88 | 89 | plaintext_sig = _ffi.buffer(plaintext_sig, plaintext_len)[:] 90 | if key: 91 | return key.sign(plaintext_sig) 92 | else: 93 | return plaintext_sig 94 | 95 | def check_signature(signature, data, hash_cls, pub_key): 96 | computed_signature = make_signature(data, hash_cls) 97 | decrypted_signature = pub_key.verify(signature) 98 | return computed_signature == decrypted_signature 99 | -------------------------------------------------------------------------------- /wolfcrypt/exceptions.py: -------------------------------------------------------------------------------- 1 | # exceptions.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | 22 | class WolfCryptError(Exception): 23 | pass 24 | -------------------------------------------------------------------------------- /wolfcrypt/hashes.py: -------------------------------------------------------------------------------- 1 | # hashes.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=no-member,no-name-in-module, no-self-use 22 | 23 | from wolfcrypt._ffi import ffi as _ffi 24 | from wolfcrypt._ffi import lib as _lib 25 | from wolfcrypt.utils import t2b, b2h 26 | 27 | from wolfcrypt.exceptions import WolfCryptError 28 | 29 | 30 | class _Hash(object): 31 | """ 32 | A **PEP 247: Cryptographic Hash Functions** compliant 33 | **Hash Function Interface**. 34 | """ 35 | def __init__(self, string=None): 36 | self._native_object = _ffi.new(self._native_type) 37 | ret = self._init() 38 | if ret < 0: # pragma: no cover 39 | raise WolfCryptError("Hash init error (%d)" % ret) 40 | 41 | if string: 42 | self.update(string) 43 | 44 | @classmethod 45 | def new(cls, string=None): 46 | """ 47 | Creates a new hashing object and returns it. The optional 48 | **string** parameter, if supplied, will be immediately 49 | hashed into the object's starting state, as if 50 | obj.update(string) was called. 51 | """ 52 | return cls(string) 53 | 54 | def copy(self): 55 | """ 56 | Returns a separate copy of this hashing object. An update 57 | to this copy won't affect the original object. 58 | """ 59 | copy = self.new("") 60 | 61 | _ffi.memmove(copy._native_object, # pylint: disable=protected-access 62 | self._native_object, 63 | self._native_size) 64 | 65 | return copy 66 | 67 | def update(self, string): 68 | """ 69 | Hashes **string** into the current state of the hashing 70 | object. update() can be called any number of times during 71 | a hashing object's lifetime. 72 | """ 73 | string = t2b(string) 74 | 75 | ret = self._update(string) 76 | if ret < 0: # pragma: no cover 77 | raise WolfCryptError("Hash update error (%d)" % ret) 78 | 79 | def digest(self): 80 | """ 81 | Returns the hash value of this hashing object as a string 82 | containing 8-bit data. The object is not altered in any 83 | way by this function; you can continue updating the object 84 | after calling this function. 85 | """ 86 | result = _ffi.new("byte[%d]" % self.digest_size) 87 | 88 | if self._native_object: 89 | obj = _ffi.new(self._native_type) 90 | 91 | _ffi.memmove(obj, self._native_object, self._native_size) 92 | 93 | ret = self._final(obj, result) 94 | if ret < 0: # pragma: no cover 95 | raise WolfCryptError("Hash finalize error (%d)" % ret) 96 | 97 | return _ffi.buffer(result, self.digest_size)[:] 98 | 99 | def hexdigest(self): 100 | """ 101 | Returns the hash value of this hashing object as a string 102 | containing hexadecimal digits. Lowercase letters are used 103 | for the digits 'a' through 'f'. Like the .digest() method, 104 | this method doesn't alter the object. 105 | """ 106 | return b2h(self.digest()) 107 | 108 | 109 | if _lib.SHA_ENABLED: 110 | class Sha(_Hash): 111 | """ 112 | **SHA-1** is a cryptographic hash function standardized by **NIST**. 113 | 114 | It produces an [ **160-bit | 20 bytes** ] message digest. 115 | """ 116 | digest_size = 20 117 | _native_type = "wc_Sha *" 118 | _native_size = _ffi.sizeof("wc_Sha") 119 | 120 | def _init(self): 121 | return _lib.wc_InitSha(self._native_object) 122 | 123 | def _update(self, data): 124 | return _lib.wc_ShaUpdate(self._native_object, data, len(data)) 125 | 126 | def _final(self, obj, ret): 127 | return _lib.wc_ShaFinal(obj, ret) 128 | 129 | 130 | if _lib.SHA256_ENABLED: 131 | class Sha256(_Hash): 132 | """ 133 | **SHA-256** is a cryptographic hash function from the 134 | **SHA-2 family** and is standardized by **NIST**. 135 | 136 | It produces a [ **256-bit | 32 bytes** ] message digest. 137 | """ 138 | digest_size = 32 139 | _native_type = "wc_Sha256 *" 140 | _native_size = _ffi.sizeof("wc_Sha256") 141 | 142 | def _init(self): 143 | return _lib.wc_InitSha256(self._native_object) 144 | 145 | def _update(self, data): 146 | return _lib.wc_Sha256Update(self._native_object, data, len(data)) 147 | 148 | def _final(self, obj, ret): 149 | return _lib.wc_Sha256Final(obj, ret) 150 | 151 | 152 | if _lib.SHA384_ENABLED: 153 | class Sha384(_Hash): 154 | """ 155 | **SHA-384** is a cryptographic hash function from the 156 | **SHA-2 family** and is standardized by **NIST**. 157 | 158 | It produces a [ **384-bit | 48 bytes** ] message digest. 159 | """ 160 | digest_size = 48 161 | _native_type = "wc_Sha384 *" 162 | _native_size = _ffi.sizeof("wc_Sha384") 163 | 164 | def _init(self): 165 | return _lib.wc_InitSha384(self._native_object) 166 | 167 | def _update(self, data): 168 | return _lib.wc_Sha384Update(self._native_object, data, len(data)) 169 | 170 | def _final(self, obj, ret): 171 | return _lib.wc_Sha384Final(obj, ret) 172 | 173 | 174 | if _lib.SHA512_ENABLED: 175 | class Sha512(_Hash): 176 | """ 177 | **SHA-512** is a cryptographic hash function from the 178 | **SHA-2 family** and is standardized by **NIST**. 179 | 180 | It produces a [ **512-bit | 64 bytes** ] message digest. 181 | """ 182 | digest_size = 64 183 | _native_type = "wc_Sha512 *" 184 | _native_size = _ffi.sizeof("wc_Sha512") 185 | 186 | def _init(self): 187 | return _lib.wc_InitSha512(self._native_object) 188 | 189 | def _update(self, data): 190 | return _lib.wc_Sha512Update(self._native_object, data, len(data)) 191 | 192 | def _final(self, obj, ret): 193 | return _lib.wc_Sha512Final(obj, ret) 194 | 195 | if _lib.SHA3_ENABLED: 196 | class Sha3(_Hash): 197 | """ 198 | **SHA3 ** is a cryptographic hash function family 199 | standardized by **NIST**. 200 | 201 | It produces from [ **224-bit | 28 bytes** ] up to [ **512-bit | 64 bytes] message digests. 202 | 203 | Using SHA3-384 by default, unless a different digest size is passed through __init__. 204 | """ 205 | _native_type = "wc_Sha3 *" 206 | _native_size = _ffi.sizeof("wc_Sha3") 207 | SHA3_224_DIGEST_SIZE = 28 208 | SHA3_256_DIGEST_SIZE = 32 209 | SHA3_384_DIGEST_SIZE = 48 210 | SHA3_512_DIGEST_SIZE = 64 211 | 212 | def __init__(self): # pylint: disable=W0231 213 | self._native_object = _ffi.new(self._native_type) 214 | self.digest_size = SHA3_384_DIGEST_SIZE 215 | ret = self._init() 216 | if ret < 0: # pragma: no cover 217 | raise WolfCryptError("Sha3 init error (%d)" % ret) 218 | 219 | def __init__(self, string, size=SHA3_384_DIGEST_SIZE): # pylint: disable=W0231 220 | self._native_object = _ffi.new(self._native_type) 221 | self.digest_size = size 222 | ret = self._init() 223 | if ret < 0: # pragma: no cover 224 | raise WolfCryptError("Sha3 init error (%d)" % ret) 225 | if string: 226 | self.update(string) 227 | 228 | def _init(self): 229 | if (self.digest_size != Sha3.SHA3_224_DIGEST_SIZE and 230 | self.digest_size != Sha3.SHA3_256_DIGEST_SIZE and 231 | self.digest_size != Sha3.SHA3_384_DIGEST_SIZE and 232 | self.digest_size != Sha3.SHA3_512_DIGEST_SIZE): 233 | return -1 234 | if self.digest_size == Sha3.SHA3_224_DIGEST_SIZE: 235 | return _lib.wc_InitSha3_224(self._native_object, _ffi.NULL, 0) 236 | if self.digest_size == Sha3.SHA3_256_DIGEST_SIZE: 237 | return _lib.wc_InitSha3_256(self._native_object, _ffi.NULL, 0) 238 | if self.digest_size == Sha3.SHA3_384_DIGEST_SIZE: 239 | return _lib.wc_InitSha3_384(self._native_object, _ffi.NULL, 0) 240 | if self.digest_size == Sha3.SHA3_512_DIGEST_SIZE: 241 | return _lib.wc_InitSha3_512(self._native_object, _ffi.NULL, 0) 242 | def _update(self, data): 243 | if self.digest_size == Sha3.SHA3_224_DIGEST_SIZE: 244 | return _lib.wc_Sha3_224_Update(self._native_object, data, len(data)) 245 | if self.digest_size == Sha3.SHA3_256_DIGEST_SIZE: 246 | return _lib.wc_Sha3_256_Update(self._native_object, data, len(data)) 247 | if self.digest_size == Sha3.SHA3_384_DIGEST_SIZE: 248 | return _lib.wc_Sha3_384_Update(self._native_object, data, len(data)) 249 | if self.digest_size == Sha3.SHA3_512_DIGEST_SIZE: 250 | return _lib.wc_Sha3_512_Update(self._native_object, data, len(data)) 251 | def _final(self, obj, ret): 252 | if self.digest_size == Sha3.SHA3_224_DIGEST_SIZE: 253 | return _lib.wc_Sha3_224_Final(obj, ret) 254 | if self.digest_size == Sha3.SHA3_256_DIGEST_SIZE: 255 | return _lib.wc_Sha3_256_Final(obj, ret) 256 | if self.digest_size == Sha3.SHA3_384_DIGEST_SIZE: 257 | return _lib.wc_Sha3_384_Final(obj, ret) 258 | if self.digest_size == Sha3.SHA3_512_DIGEST_SIZE: 259 | return _lib.wc_Sha3_512_Final(obj, ret) 260 | 261 | # Hmac types 262 | 263 | if _lib.FIPS_ENABLED and _lib.FIPS_VERSION <= 2: 264 | _TYPE_SHA = 1 265 | _TYPE_SHA256 = 2 266 | _TYPE_SHA384 = 5 267 | _TYPE_SHA512 = 4 268 | else: 269 | _TYPE_SHA = 4 270 | _TYPE_SHA256 = 6 271 | _TYPE_SHA384 = 7 272 | _TYPE_SHA512 = 8 273 | 274 | _HMAC_TYPES = [_TYPE_SHA, _TYPE_SHA256, _TYPE_SHA384, _TYPE_SHA512] 275 | 276 | 277 | if _lib.HMAC_ENABLED: 278 | class _Hmac(_Hash): 279 | """ 280 | A **PEP 247: Cryptographic Hash Functions** compliant 281 | **Keyed Hash Function Interface**. 282 | """ 283 | digest_size = None 284 | _native_type = "Hmac *" 285 | _native_size = _ffi.sizeof("Hmac") 286 | 287 | def __init__(self, key, string=None): # pylint: disable=W0231 288 | key = t2b(key) 289 | 290 | self._native_object = _ffi.new(self._native_type) 291 | ret = self._init(self._type, key) 292 | if ret < 0: # pragma: no cover 293 | raise WolfCryptError("Hmac init error (%d)" % ret) 294 | 295 | if string: 296 | self.update(string) 297 | 298 | @classmethod 299 | def new(cls, key, string=None): # pylint: disable=W0221 300 | """ 301 | Creates a new hashing object and returns it. **key** is 302 | a required parameter containing a string giving the key 303 | to use. The optional **string** parameter, if supplied, 304 | will be immediately hashed into the object's starting 305 | state, as if obj.update(string) was called. 306 | """ 307 | return cls(key, string) 308 | 309 | def _init(self, hmac, key): 310 | if _lib.wc_HmacInit(self._native_object, _ffi.NULL, -2) != 0: 311 | raise WolfCryptError("wc_HmacInit error") 312 | # If the key isn't set, don't call wc_HmacSetKey. This can happen, 313 | # for example, when the HMAC object is being copied. See the copy 314 | # function of _Hash. 315 | ret = 0 316 | if len(key) > 0: 317 | ret = _lib.wc_HmacSetKey(self._native_object, hmac, key, len(key)) 318 | if ret < 0: 319 | err_str = "no error description found" 320 | try: 321 | err_str = _ffi.string(_lib.wc_GetErrorString(ret)).decode() 322 | except: 323 | pass 324 | raise WolfCryptError("wc_HmacSetKey returned {}: {}".format(ret, err_str)) 325 | return ret 326 | 327 | def _update(self, data): 328 | return _lib.wc_HmacUpdate(self._native_object, data, len(data)) 329 | 330 | def _final(self, obj, ret): 331 | return _lib.wc_HmacFinal(obj, ret) 332 | 333 | 334 | if _lib.SHA_ENABLED: 335 | class HmacSha(_Hmac): 336 | """ 337 | A HMAC function using **SHA-1** as it's cryptographic 338 | hash function. 339 | 340 | It produces a [ **512-bit | 64 bytes** ] message digest. 341 | """ 342 | _type = _TYPE_SHA 343 | digest_size = Sha.digest_size 344 | 345 | 346 | if _lib.SHA256_ENABLED: 347 | class HmacSha256(_Hmac): 348 | """ 349 | A HMAC function using **SHA-256** as it's cryptographic 350 | hash function. 351 | 352 | It produces a [ **512-bit | 64 bytes** ] message digest. 353 | """ 354 | _type = _TYPE_SHA256 355 | digest_size = Sha256.digest_size 356 | 357 | 358 | if _lib.SHA384_ENABLED: 359 | class HmacSha384(_Hmac): 360 | """ 361 | A HMAC function using **SHA-384** as it's cryptographic 362 | hash function. 363 | 364 | It produces a [ **512-bit | 64 bytes** ] message digest. 365 | """ 366 | _type = _TYPE_SHA384 367 | digest_size = Sha384.digest_size 368 | 369 | 370 | if _lib.SHA512_ENABLED: 371 | class HmacSha512(_Hmac): 372 | """ 373 | A HMAC function using **SHA-512** as it's cryptographic 374 | hash function. 375 | 376 | It produces a [ **512-bit | 64 bytes** ] message digest. 377 | """ 378 | _type = _TYPE_SHA512 379 | digest_size = Sha512.digest_size 380 | 381 | def hash_type_to_cls(hash_type): 382 | if _lib.SHA_ENABLED and hash_type == _lib.WC_HASH_TYPE_SHA: 383 | hash_cls = Sha 384 | elif _lib.SHA256_ENABLED and hash_type == _lib.WC_HASH_TYPE_SHA256: 385 | hash_cls = Sha256 386 | elif _lib.SHA384_ENABLED and hash_type == _lib.WC_HASH_TYPE_SHA384: 387 | hash_cls = Sha384 388 | elif _lib.SHA512_ENABLED and hash_type == _lib.WC_HASH_TYPE_SHA512: 389 | hash_cls = Sha512 390 | else: 391 | hash_cls = None 392 | 393 | return hash_cls 394 | -------------------------------------------------------------------------------- /wolfcrypt/pwdbased.py: -------------------------------------------------------------------------------- 1 | # pwdbased.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=no-member,no-name-in-module 22 | 23 | from wolfcrypt._ffi import ffi as _ffi 24 | from wolfcrypt._ffi import lib as _lib 25 | 26 | from wolfcrypt.exceptions import WolfCryptError 27 | 28 | if _lib.PWDBASED_ENABLED: 29 | def PBKDF2(password, salt, iterations, key_length, hash_type): 30 | if isinstance(salt, str): 31 | salt = str.encode(salt) 32 | 33 | if isinstance(password, str): 34 | password = str.encode(password) 35 | 36 | key = _ffi.new("byte[%d]" %key_length) 37 | ret = _lib.wc_PBKDF2(key, password, len(password), salt, len(salt), 38 | iterations, key_length, hash_type) 39 | 40 | if ret != 0: 41 | raise WolfCryptError("PBKDF2 error (%d)" % ret) 42 | 43 | return _ffi.buffer(key, key_length)[:] 44 | -------------------------------------------------------------------------------- /wolfcrypt/random.py: -------------------------------------------------------------------------------- 1 | # random.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=no-member,no-name-in-module 22 | 23 | from wolfcrypt._ffi import ffi as _ffi 24 | from wolfcrypt._ffi import lib as _lib 25 | 26 | from wolfcrypt.exceptions import WolfCryptError 27 | 28 | 29 | class Random(object): 30 | """ 31 | A Cryptographically Secure Pseudo Random Number Generator - CSPRNG 32 | """ 33 | 34 | def __init__(self): 35 | self.native_object = _ffi.new("WC_RNG *") 36 | 37 | ret = _lib.wc_InitRng(self.native_object) 38 | if ret < 0: # pragma: no cover 39 | self.native_object = None 40 | raise WolfCryptError("RNG init error (%d)" % ret) 41 | 42 | # making sure _lib.wc_FreeRng outlives WC_RNG instances 43 | _delete = _lib.wc_FreeRng 44 | 45 | def __del__(self): 46 | if self.native_object: 47 | try: 48 | self._delete(self.native_object) 49 | except AttributeError: 50 | # Can occur during interpreter shutdown 51 | pass 52 | 53 | def byte(self): 54 | """ 55 | Generate and return a random byte. 56 | """ 57 | result = _ffi.new('byte[1]') 58 | 59 | ret = _lib.wc_RNG_GenerateByte(self.native_object, result) 60 | if ret < 0: # pragma: no cover 61 | raise WolfCryptError("RNG generate byte error (%d)" % ret) 62 | 63 | return _ffi.buffer(result, 1)[:] 64 | 65 | def bytes(self, length): 66 | """ 67 | Generate and return a random sequence of length bytes. 68 | """ 69 | result = _ffi.new('byte[%d]' % length) 70 | 71 | ret = _lib.wc_RNG_GenerateBlock(self.native_object, result, length) 72 | if ret < 0: # pragma: no cover 73 | raise WolfCryptError("RNG generate block error (%d)" % ret) 74 | 75 | return _ffi.buffer(result, length)[:] 76 | -------------------------------------------------------------------------------- /wolfcrypt/utils.py: -------------------------------------------------------------------------------- 1 | # utils.py 2 | # 3 | # Copyright (C) 2006-2022 wolfSSL Inc. 4 | # 5 | # This file is part of wolfSSL. (formerly known as CyaSSL) 6 | # 7 | # wolfSSL is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # wolfSSL is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 | 21 | # pylint: disable=unused-import, undefined-variable 22 | 23 | import sys 24 | from binascii import hexlify as b2h, unhexlify as h2b # noqa: F401 25 | 26 | 27 | _PY3 = sys.version_info[0] == 3 28 | _TEXT_TYPE = str if _PY3 else unicode # noqa: F821 29 | _BINARY_TYPE = bytes if _PY3 else str 30 | 31 | 32 | def t2b(string): 33 | """ 34 | Converts text to binary. 35 | """ 36 | if isinstance(string, _BINARY_TYPE): 37 | return string 38 | return _TEXT_TYPE(string).encode("utf-8") 39 | --------------------------------------------------------------------------------