├── .github └── workflows │ ├── codeql-analysis.yml │ └── release.yml ├── .gitignore ├── .travis.yml ├── AUTHORS ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── pysodium └── __init__.py ├── setup.py └── test ├── __init__.py └── test_pysodium.py /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [master, ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [master] 9 | schedule: 10 | - cron: '0 13 * * 5' 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v2 20 | with: 21 | # We must fetch at least the immediate parents so that if this is 22 | # a pull request then we can checkout the head. 23 | fetch-depth: 2 24 | 25 | # If this run was triggered by a pull request event, then checkout 26 | # the head of the pull request instead of the merge commit. 27 | - run: git checkout HEAD^2 28 | if: ${{ github.event_name == 'pull_request' }} 29 | 30 | # Initializes the CodeQL tools for scanning. 31 | - name: Initialize CodeQL 32 | uses: github/codeql-action/init@v1 33 | # Override language selection by uncommenting this and choosing your languages 34 | # with: 35 | # languages: go, javascript, csharp, python, cpp, java 36 | 37 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 38 | # If this step fails, then you should remove it and run the build manually (see below) 39 | - name: Autobuild 40 | uses: github/codeql-action/autobuild@v1 41 | 42 | # ℹ️ Command-line programs to run using the OS shell. 43 | # 📚 https://git.io/JvXDl 44 | 45 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 46 | # and modify them (or add more) to build your code if your project 47 | # uses a compiled language 48 | 49 | #- run: | 50 | # make bootstrap 51 | # make release 52 | 53 | - name: Perform CodeQL Analysis 54 | uses: github/codeql-action/analyze@v1 55 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | pypi-publish: 3 | name: Upload release to PyPI 4 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') 5 | runs-on: ubuntu-latest 6 | environment: 7 | name: pypi 8 | url: https://pypi.org/p/pysodium 9 | permissions: 10 | id-token: write 11 | steps: 12 | - uses: actions/checkout@v4 13 | - name: Set up Python 14 | uses: actions/setup-python@v3 15 | with: 16 | python-version: '3.x' 17 | - name: Install dependencies 18 | run: | 19 | python -m pip install --upgrade pip 20 | pip install build 21 | - name: Build package 22 | run: python -m build 23 | - name: Publish package distributions to PyPI 24 | uses: pypa/gh-action-pypi-publish@release/v1 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: artful 2 | language: python 3 | sudo: required 4 | python: 5 | - "2.7" 6 | - "3.5" 7 | - "3.6" 8 | - "3.7" 9 | - "3.8" 10 | 11 | install: 12 | #- sudo add-apt-repository "deb http://us.archive.ubuntu.com/ubuntu/ artful universe multiverse" 13 | #- sudo apt-get update -qq 14 | #- sudo apt-get install -y libsodium13 15 | - wget https://download.libsodium.org/libsodium/releases/LATEST.tar.gz && tar xzf LATEST.tar.gz && pushd libsodium-stable/ && ./configure --prefix=/usr && make && make check && sudo make install && popd 16 | - python setup.py install 17 | 18 | script: 19 | - python -m unittest discover --start-directory test 20 | 21 | notifications: 22 | email: false 23 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Stefan Marsiske s@ctrlc.hu 2 | Bulat Gaifullin 3 | Maximilian Heß 4 | J Bell 5 | Cale Black 6 | Jan Varho 7 | Henri Sivonen 8 | Wes Young 9 | namelessjon 10 | Emmanuel Vadot 11 | Kevin DeLoach 12 | Andreas Bogk 13 | Fredrick Brennan 14 | iachievedit 15 | Tacitus Aedifex 16 | venzen 17 | Blaz Bregar 18 | berndb84 19 | Chris Topher c@creemama.com 20 | Jonathan Levin 21 | Stefan Schaubeck 22 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Wrapper for libsodium library 2 | 3 | Copyright (c) 2013-2014, Marsiske Stefan. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include AUTHORS 2 | include LICENSE.txt 3 | include README.md 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a very simple wrapper around libsodium masquerading as nacl. 2 | 3 | [![Build Status](https://travis-ci.org/stef/pysodium.svg?branch=master)](https://travis-ci.org/stef/pysodium) 4 | 5 | This wrapper requires a pre-installed libsodium from: 6 | 7 | https://github.com/jedisct1/libsodium 8 | 9 | then it provides access to the following functions: 10 | 11 | ``` 12 | crypto_aead_aegis128l_decrypt(ciphertext, ad, nonce, key) 13 | crypto_aead_aegis128l_encrypt(message, ad, nonce, key) 14 | crypto_aead_aegis128l_decrypt_detached(ciphertext, mac, ad, nonce, key) 15 | crypto_aead_aegis128l_encrypt_detached(message, ad, nonce, key) 16 | crypto_aead_aegis256_decrypt(ciphertext, ad, nonce, key) 17 | crypto_aead_aegis256_encrypt(message, ad, nonce, key) 18 | crypto_aead_aegis256_decrypt_detached(ciphertext, mac, ad, nonce, key) 19 | crypto_aead_aegis256_encrypt_detached(message, ad, nonce, key) 20 | crypto_aead_chacha20poly1305_decrypt(ciphertext, ad, nonce, key) 21 | crypto_aead_chacha20poly1305_encrypt(message, ad, nonce, key) 22 | crypto_aead_chacha20poly1305_decrypt_detached(ciphertext, mac, ad, nonce, key) 23 | crypto_aead_chacha20poly1305_encrypt_detached(message, ad, nonce, key) 24 | crypto_aead_chacha20poly1305_ietf_decrypt(ciphertext, ad, nonce, key) 25 | crypto_aead_chacha20poly1305_ietf_encrypt(message, ad, nonce, key) 26 | crypto_aead_chacha20poly1305_ietf_decrypt_detached(ciphertext, mac, ad, nonce, key) 27 | crypto_aead_chacha20poly1305_ietf_encrypt_detached(message, ad, nonce, key) 28 | crypto_aead_xchacha20poly1305_ietf_decrypt(ciphertext, ad, nonce, key) 29 | crypto_aead_xchacha20poly1305_ietf_encrypt(message, ad, nonce, key) 30 | crypto_auth(message, key) 31 | crypto_auth_verify(tag, message, key) 32 | crypto_box_afternm(msg, nonce, k) 33 | crypto_box_beforenm(pk, sk) 34 | crypto_box_detached(msg, nonce, pk, sk) 35 | crypto_box_keypair() 36 | crypto_box(msg, nonce, pk, sk) 37 | crypto_box_open_afternm(c, nonce, k) 38 | crypto_box_open(c, nonce, pk, sk) 39 | crypto_box_open_detached(c, mac, nonce, pk, sk) 40 | crypto_box_seal(msg, pk) 41 | crypto_box_seal_open(c, pk, sk) 42 | crypto_box_seed_keypair(seed) 43 | crypto_generichash_blake2b_salt_personal(message, outlen = crypto_generichash_blake2b_BYTES, key = b'', salt = b'', personal = b'') 44 | crypto_generichash_final(state, outlen=crypto_generichash_BYTES) 45 | crypto_generichash_init(outlen=crypto_generichash_BYTES, k=b'') 46 | crypto_generichash(m, k=b'', outlen=crypto_generichash_BYTES) 47 | crypto_generichash_update(state, m) 48 | crypto_hash_sha256(message) 49 | crypto_hash_sha512(message) 50 | crypto_hash_sha512_init() 51 | crypto_hash_sha512_update(state, data) 52 | crypto_hash_sha512_final(state) 53 | crypto_kx_client_session_keys(client_pk, client_sk, server_pk) 54 | crypto_kx_keypair() 55 | crypto_kx_server_session_keys(server_pk, server_sk, client_pk) 56 | crypto_pwhash(outlen, passwd, salt, opslimit, memlimit, alg) 57 | crypto_pwhash_scryptsalsa208sha256(outlen, passwd, salt, opslimit, memlimit) 58 | crypto_pwhash_scryptsalsa208sha256_str(passwd, opslimit, memlimit) 59 | crypto_pwhash_scryptsalsa208sha256_str_verify(stored, passwd) 60 | crypto_pwhash_str(passwd, opslimit, memlimit) 61 | crypto_pwhash_str_verify(pstr, passwd) 62 | crypto_scalarmult_base(n) 63 | crypto_scalarmult_curve25519_base(n) 64 | crypto_scalarmult_curve25519(n, p) 65 | crypto_secretbox(msg, nonce, k) 66 | crypto_secretbox_detached(msg, nonce, k) 67 | crypto_secretbox_open(c, nonce, k) 68 | crypto_secretbox_open_detached(c, mac, nonce, k) 69 | crypto_secretstream_xchacha20poly1305_keygen(): 70 | crypto_secretstream_xchacha20poly1305_init_push(key): 71 | crypto_secretstream_xchacha20poly1305_init_pull(header, key): 72 | crypto_secretstream_xchacha20poly1305_rekey(state): 73 | crypto_secretstream_xchacha20poly1305_push(state, message, ad, tag): 74 | crypto_secretstream_xchacha20poly1305_pull(state, ciphertext, ad): 75 | crypto_sign_init() 76 | crypto_sign_update(state, m) 77 | crypto_sign_final_create(state, sk) 78 | crypto_sign_final_verify(state, sig, pk) 79 | crypto_sign_detached(m, sk) 80 | crypto_sign_keypair() 81 | crypto_sign(m, sk) 82 | crypto_sign_open(sm, pk) 83 | crypto_sign_pk_to_box_pk(pk) 84 | crypto_sign_seed_keypair(seed) 85 | crypto_sign_sk_to_box_sk(sk) 86 | crypto_sign_sk_to_pk(sk) 87 | crypto_sign_sk_to_seed(sk) 88 | crypto_sign_verify_detached(sig, msg, pk) 89 | crypto_stream_chacha20_xor(message, nonce, key) 90 | crypto_stream_chacha20_xor_ic(message, nonce, initial_counter, key) 91 | crypto_stream_chacha20_ietf_xor(message, nonce, key) 92 | crypto_stream_chacha20_ietf_xor_ic(message, nonce, initial_counter, key) 93 | crypto_stream_xchacha20_xor(message, nonce, key) 94 | crypto_stream_xchacha20_xor_ic(message, nonce, initial_counter, key) 95 | crypto_stream(cnt, nonce=None, key=None) 96 | crypto_stream_xor(msg, cnt, nonce=None, key=None) 97 | randombytes(size) 98 | sodium_increment(bytes) 99 | crypto_core_ristretto255_is_valid_point(p) 100 | crypto_core_ristretto255_from_hash(r) 101 | crypto_scalarmult_ristretto255(n, p) 102 | crypto_scalarmult_ristretto255_base(n) 103 | crypto_core_ristretto255_scalar_random() 104 | crypto_core_ristretto255_scalar_invert(s) 105 | crypto_core_ristretto255_scalar_reduce(s) 106 | crypto_core_ristretto255_add(p, q) 107 | crypto_core_ristretto255_sub(p,q) 108 | crypto_core_ristretto255_random() 109 | crypto_core_ristretto255_scalar_negate(s) 110 | crypto_core_ristretto255_scalar_complement(s) 111 | crypto_core_ristretto255_scalar_add(x,y) 112 | crypto_core_ristretto255_scalar_sub(x,y) 113 | crypto_core_ristretto255_scalar_mul(x,y) 114 | crypto_auth_hmacsha256_keygen 115 | crypto_auth_hmacsha256 116 | crypto_auth_hmacsha256_verify 117 | crypto_auth_hmacsha512_keygen 118 | crypto_auth_hmacsha512 119 | crypto_auth_hmacsha512_verify 120 | crypto_auth_hmacsha512256_keygen 121 | crypto_auth_hmacsha512256 122 | crypto_auth_hmacsha512256_verify 123 | crypto_kdf_derive_from_key(subkey_len, subkey_id, ctx, key) 124 | crypto_kdf_keygen() 125 | crypto_kdf_hkdf_sha256_extract_init(salt=b'') 126 | crypto_kdf_hkdf_sha256_extract_update(state, ikm=b'') 127 | crypto_kdf_hkdf_sha256_extract_final(state) 128 | crypto_kdf_hkdf_sha256_extract(salt=b'', ikm=b'') 129 | crypto_kdf_hkdf_sha256_keygen() 130 | crypto_kdf_hkdf_sha256_expand(outlen, prk, ctx=b'') 131 | crypto_kdf_hkdf_sha512_extract_init(salt=b'') 132 | crypto_kdf_hkdf_sha512_extract_update(state, ikm=b'') 133 | crypto_kdf_hkdf_sha512_extract_final(state) 134 | crypto_kdf_hkdf_sha512_extract(salt=b'', ikm=b'') 135 | crypto_kdf_hkdf_sha512_keygen() 136 | crypto_kdf_hkdf_sha512_expand(outlen, prk, ctx=b'') 137 | ``` 138 | 139 | Constants: 140 | 141 | ``` 142 | crypto_aead_chacha20poly1305_ABYTES 143 | crypto_aead_chacha20poly1305_KEYBYTES 144 | crypto_aead_chacha20poly1305_NPUBBYTES 145 | crypto_aead_chacha20poly1305_ietf_KEYBYTES 146 | crypto_aead_chacha20poly1305_ietf_NPUBBYTES 147 | crypto_aead_chacha20poly1305_ietf_ABYTES 148 | crypto_aead_xchacha20poly1305_ietf_KEYBYTES 149 | crypto_aead_xchacha20poly1305_ietf_NPUBBYTES 150 | crypto_aead_xchacha20poly1305_ietf_ABYTES 151 | crypto_auth_BYTES 152 | crypto_auth_KEYBYTES 153 | crypto_box_BEFORENMBYTES 154 | crypto_box_BOXZEROBYTES 155 | crypto_box_MACBYTES 156 | crypto_box_NONCEBYTES 157 | crypto_box_PUBLICKEYBYTES 158 | crypto_box_SEALBYTES 159 | crypto_box_SECRETKEYBYTES 160 | crypto_box_SEEDBYTES 161 | crypto_box_ZEROBYTES 162 | crypto_generichash_KEYBYTES_MAX 163 | crypto_generichash_BYTES 164 | crypto_generichash_BYTES_MAX 165 | crypto_generichash_BYTES_MIN 166 | crypto_generichash_STATEBYTES 167 | crypto_generichash_blake2b_BYTES 168 | crypto_generichash_blake2b_BYTES_MAX 169 | crypto_generichash_blake2b_BYTES_MIN 170 | crypto_generichash_blake2b_KEYBYTES_MAX 171 | crypto_generichash_blake2b_PERSONALBYTES 172 | crypto_generichash_blake2b_SALTBYTES 173 | crypto_hash_sha256_BYTES 174 | crypto_hash_sha512_BYTES 175 | crypto_hash_sha512_STATEBYTES 176 | crypto_kx_PUBLICKEYBYTES 177 | crypto_kx_SECRETKEYBYTES 178 | crypto_kx_SESSIONKEYBYTES 179 | crypto_pwhash_ALG_DEFAULT 180 | crypto_pwhash_ALG_ARGON2I13 181 | crypto_pwhash_ALG_ARGON2ID13 182 | crypto_pwhash_BYTES_MAX 183 | crypto_pwhash_BYTES_MIN 184 | crypto_pwhash_MEMLIMIT_MAX 185 | crypto_pwhash_MEMLIMIT_MIN 186 | crypto_pwhash_MEMLIMIT_INTERACTIVE 187 | crypto_pwhash_MEMLIMIT_MODERATE 188 | crypto_pwhash_MEMLIMIT_SENSITIVE 189 | crypto_pwhash_OPSLIMIT_MAX 190 | crypto_pwhash_OPSLIMIT_MIN 191 | crypto_pwhash_OPSLIMIT_INTERACTIVE 192 | crypto_pwhash_OPSLIMIT_MODERATE 193 | crypto_pwhash_OPSLIMIT_SENSITIVE 194 | crypto_pwhash_PASSWD_MAX 195 | crypto_pwhash_PASSWD_MIN 196 | crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE 197 | crypto_pwhash_argon2i_MEMLIMIT_MODERATE 198 | crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE 199 | crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE 200 | crypto_pwhash_argon2i_OPSLIMIT_MODERATE 201 | crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE 202 | crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE 203 | crypto_pwhash_argon2id_MEMLIMIT_MODERATE 204 | crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE 205 | crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE 206 | crypto_pwhash_argon2id_OPSLIMIT_MODERATE 207 | crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE 208 | crypto_pwhash_SALTBYTES 209 | crypto_pwhash_STRBYTES 210 | crypto_pwhash_scryptsalsa208sha256_BYTES_MAX 211 | crypto_pwhash_scryptsalsa208sha256_BYTES_MIN 212 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX 213 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN 214 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE 215 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE 216 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX 217 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN 218 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE 219 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE 220 | crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX 221 | crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN 222 | crypto_pwhash_scryptsalsa208sha256_SALTBYTES 223 | crypto_pwhash_scryptsalsa208sha256_STRBYTES 224 | crypto_pwhash_scryptsalsa208sha256_STRPREFIX 225 | crypto_scalarmult_BYTES 226 | crypto_scalarmult_SCALARBYTES 227 | crypto_scalarmult_curve25519_BYTES 228 | crypto_secretbox_BOXZEROBYTES 229 | crypto_secretbox_KEYBYTES 230 | crypto_secretbox_KEYBYTES 231 | crypto_secretbox_MACBYTES 232 | crypto_secretbox_NONCEBYTES 233 | crypto_secretbox_ZEROBYTES 234 | crypto_secretstream_xchacha20poly1305_STATEBYTES 235 | crypto_secretstream_xchacha20poly1305_ABYTES 236 | crypto_secretstream_xchacha20poly1305_HEADERBYTES 237 | crypto_secretstream_xchacha20poly1305_KEYBYTES 238 | crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX 239 | crypto_secretstream_xchacha20poly1305_TAG_MESSAGE 240 | crypto_secretstream_xchacha20poly1305_TAG_PUSH 241 | crypto_secretstream_xchacha20poly1305_TAG_REKEY 242 | crypto_secretstream_xchacha20poly1305_TAG_FINAL 243 | crypto_sign_BYTES 244 | crypto_sign_PUBLICKEYBYTES 245 | crypto_sign_SECRETKEYBYTES 246 | crypto_sign_SEEDBYTES 247 | crypto_sign_ed25519_PUBLICKEYBYTES 248 | crypto_sign_ed25519_SECRETKEYBYTES 249 | crypto_stream_KEYBYTES 250 | crypto_stream_NONCEBYTES 251 | crypto_stream_chacha20_NONCEBYTES 252 | crypto_stream_chacha20_KEYBYTES 253 | crypto_stream_chacha20_ietf_NONCEBYTES 254 | crypto_stream_chacha20_ietf_KEYBYTES 255 | crypto_stream_xchacha20_NONCEBYTES 256 | crypto_stream_xchacha20_KEYBYTES 257 | crypto_core_ristretto255_BYTES 258 | crypto_core_ristretto255_HASHBYTES 259 | crypto_core_ristretto255_SCALARBYTES 260 | crypto_core_ristretto255_NONREDUCEDSCALARBYTES 261 | crypto_auth_hmacsha256_BYTES 262 | crypto_auth_hmacsha256_KEYBYTES 263 | crypto_auth_hmacsha512_BYTES 264 | crypto_auth_hmacsha512_KEYBYTES 265 | crypto_auth_hmacsha512256_BYTES 266 | crypto_auth_hmacsha512256_KEYBYTES 267 | crypto_kdf_BYTES_MIN 268 | crypto_kdf_BYTES_MAX 269 | crypto_kdf_CONTEXTBYTES 270 | crypto_kdf_KEYBYTES 271 | crypto_kdf_hkdf_sha256_KEYBYTES 272 | crypto_kdf_hkdf_sha256_BYTES_MIN 273 | crypto_kdf_hkdf_sha256_BYTES_MAX 274 | crypto_kdf_hkdf_sha256_STATEBYTES 275 | ``` 276 | 277 | 278 | 279 | Note 280 | 281 | most of the the `*_easy` functions are not implemented as the "non-easy" 282 | functions provide already the "easy" interface, which hides the placement of 283 | buffers in memory, which makes little sense in python, so this wrapper handles 284 | this. 285 | -------------------------------------------------------------------------------- /pysodium/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Wrapper for libsodium library 4 | 5 | Copyright (c) 2013-2023, Marsiske Stefan. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, 9 | are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | 14 | * Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | """ 29 | 30 | import ctypes 31 | import ctypes.util 32 | 33 | sodium = ctypes.cdll.LoadLibrary(ctypes.util.find_library('sodium') or ctypes.util.find_library('libsodium')) 34 | if not sodium._name: 35 | raise ValueError('Unable to find libsodium') 36 | 37 | sodium.sodium_version_string.restype = ctypes.c_char_p 38 | 39 | try: 40 | sodium_major = int(sodium.sodium_version_string().decode('utf8').split('.')[0]) 41 | sodium_minor = int(sodium.sodium_version_string().decode('utf8').split('.')[1]) 42 | sodium_patch = int(sodium.sodium_version_string().decode('utf8').split('.')[2]) 43 | except (IndexError, ValueError): 44 | raise ValueError('Unable to parse version string from libsodium') 45 | 46 | def sodium_version_check(major, minor, patch): 47 | """Check if the current libsodium version is greater or equal to the supplied one 48 | """ 49 | if major > sodium_major: 50 | return False 51 | if major == sodium_major and minor > sodium_minor: 52 | return False 53 | if major == sodium_major and minor == sodium_minor and patch > sodium_patch: 54 | return False 55 | return True 56 | 57 | def sodium_version(major, minor, patch): 58 | def decorator(func): 59 | def wrapper(*args, **kwargs): 60 | if sodium_version_check(major, minor, patch) == False: 61 | raise ValueError('Unavailable in this libsodium version') 62 | return func(*args, **kwargs) 63 | return wrapper 64 | return decorator 65 | 66 | def encode_strings(func): 67 | """ 68 | This decorator forces the encoding of str function parameters to UTF-8 69 | to elliminate the differences between Python 3.x and Python 2.x. The only 70 | caveat is that bytes and str are both str types in Python 2.x so it is 71 | possible for the encode() function to fail. It is OK for us to accept that 72 | failure, hence the pass in the except block. 73 | 74 | Use this decorator on any functions that can take strings as parameters 75 | such as crypto_pwhash(). 76 | """ 77 | def wrapper(*args, **kwargs): 78 | largs = [] 79 | for arg in args: 80 | if isinstance(arg, str): 81 | try: 82 | arg = arg.encode(encoding='utf-8') 83 | except: 84 | pass 85 | largs.append(arg) 86 | for k in kwargs.keys(): 87 | if isinstance(kwargs[k], str): 88 | try: 89 | kwargs[k] = kwargs[k].encode(encoding='utf-8') 90 | except: 91 | pass 92 | return func(*largs, **kwargs) 93 | return wrapper 94 | 95 | sodium.crypto_pwhash_scryptsalsa208sha256_strprefix.restype = ctypes.c_char_p 96 | 97 | crypto_auth_KEYBYTES = sodium.crypto_auth_keybytes() 98 | crypto_auth_BYTES = sodium.crypto_auth_bytes() 99 | crypto_box_NONCEBYTES = sodium.crypto_box_noncebytes() 100 | crypto_box_BEFORENMBYTES = sodium.crypto_box_beforenmbytes() 101 | crypto_box_PUBLICKEYBYTES = sodium.crypto_box_publickeybytes() 102 | crypto_box_SECRETKEYBYTES = sodium.crypto_box_secretkeybytes() 103 | crypto_box_ZEROBYTES = sodium.crypto_box_zerobytes() 104 | crypto_box_BOXZEROBYTES = sodium.crypto_box_boxzerobytes() 105 | crypto_box_MACBYTES = sodium.crypto_box_macbytes() 106 | crypto_box_SEALBYTES = sodium.crypto_box_sealbytes() 107 | crypto_box_SEEDBYTES = sodium.crypto_box_seedbytes() 108 | crypto_secretbox_KEYBYTES = sodium.crypto_secretbox_keybytes() 109 | crypto_secretbox_NONCEBYTES = sodium.crypto_secretbox_noncebytes() 110 | crypto_secretbox_ZEROBYTES = sodium.crypto_secretbox_zerobytes() 111 | crypto_secretbox_BOXZEROBYTES = sodium.crypto_secretbox_boxzerobytes() 112 | crypto_secretbox_MACBYTES = sodium.crypto_secretbox_macbytes() 113 | crypto_sign_PUBLICKEYBYTES = sodium.crypto_sign_publickeybytes() 114 | crypto_sign_SECRETKEYBYTES = sodium.crypto_sign_secretkeybytes() 115 | crypto_sign_SEEDBYTES = sodium.crypto_sign_seedbytes() 116 | crypto_sign_BYTES = sodium.crypto_sign_bytes() 117 | crypto_sign_ed25519_SECRETKEYBYTES = sodium.crypto_sign_ed25519_secretkeybytes() 118 | crypto_sign_ed25519_PUBLICKEYBYTES = sodium.crypto_sign_ed25519_publickeybytes() 119 | crypto_stream_KEYBYTES = sodium.crypto_stream_keybytes() 120 | crypto_stream_NONCEBYTES = sodium.crypto_stream_noncebytes() 121 | crypto_stream_chacha20_NONCEBYTES = sodium.crypto_stream_chacha20_noncebytes() 122 | crypto_stream_chacha20_KEYBYTES = sodium.crypto_stream_chacha20_keybytes() 123 | crypto_stream_chacha20_ietf_NONCEBYTES = sodium.crypto_stream_chacha20_ietf_noncebytes() 124 | crypto_stream_chacha20_ietf_KEYBYTES = sodium.crypto_stream_chacha20_ietf_keybytes() 125 | crypto_stream_xchacha20_NONCEBYTES = sodium.crypto_stream_xchacha20_noncebytes() 126 | crypto_stream_xchacha20_KEYBYTES = sodium.crypto_stream_xchacha20_keybytes() 127 | crypto_generichash_KEYBYTES_MAX = sodium.crypto_generichash_keybytes_max() 128 | crypto_generichash_BYTES = sodium.crypto_generichash_bytes() 129 | crypto_generichash_BYTES_MIN = sodium.crypto_generichash_bytes_min() 130 | crypto_generichash_BYTES_MAX = sodium.crypto_generichash_bytes_max() 131 | crypto_generichash_STATEBYTES = sodium.crypto_generichash_statebytes() 132 | crypto_scalarmult_curve25519_BYTES = sodium.crypto_scalarmult_curve25519_bytes() 133 | crypto_scalarmult_BYTES = sodium.crypto_scalarmult_bytes() 134 | crypto_scalarmult_SCALARBYTES = sodium.crypto_scalarmult_curve25519_scalarbytes() 135 | crypto_generichash_blake2b_KEYBYTES_MAX = sodium.crypto_generichash_blake2b_keybytes_max() 136 | crypto_generichash_blake2b_BYTES = sodium.crypto_generichash_blake2b_bytes() 137 | crypto_generichash_blake2b_BYTES_MIN = sodium.crypto_generichash_blake2b_bytes_min() 138 | crypto_generichash_blake2b_BYTES_MAX = sodium.crypto_generichash_blake2b_bytes_max() 139 | crypto_generichash_blake2b_SALTBYTES = sodium.crypto_generichash_blake2b_saltbytes() 140 | crypto_generichash_blake2b_PERSONALBYTES = sodium.crypto_generichash_blake2b_personalbytes() 141 | crypto_pwhash_scryptsalsa208sha256_SALTBYTES = sodium.crypto_pwhash_scryptsalsa208sha256_saltbytes() 142 | crypto_pwhash_scryptsalsa208sha256_STRBYTES = sodium.crypto_pwhash_scryptsalsa208sha256_strbytes() 143 | crypto_pwhash_scryptsalsa208sha256_STRPREFIX = sodium.crypto_pwhash_scryptsalsa208sha256_strprefix() 144 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE = sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_interactive() 145 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE = sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_interactive() 146 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE = sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive() 147 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE = sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive() 148 | crypto_hash_sha256_BYTES = sodium.crypto_hash_sha256_bytes() 149 | crypto_hash_sha512_BYTES = sodium.crypto_hash_sha512_bytes() 150 | crypto_hash_sha512_STATEBYTES = sodium.crypto_hash_sha512_statebytes() 151 | crypto_aead_chacha20poly1305_KEYBYTES = sodium.crypto_aead_chacha20poly1305_keybytes() 152 | crypto_aead_chacha20poly1305_NPUBBYTES = sodium.crypto_aead_chacha20poly1305_npubbytes() 153 | crypto_aead_chacha20poly1305_NONCEBYTES = crypto_aead_chacha20poly1305_NPUBBYTES 154 | crypto_aead_chacha20poly1305_ABYTES = sodium.crypto_aead_chacha20poly1305_abytes() 155 | crypto_kdf_BYTES_MIN = sodium.crypto_kdf_bytes_min() 156 | crypto_kdf_BYTES_MAX = sodium.crypto_kdf_bytes_max() 157 | crypto_kdf_CONTEXTBYTES = sodium.crypto_kdf_contextbytes() 158 | crypto_kdf_KEYBYTES = sodium.crypto_kdf_keybytes() 159 | 160 | if sodium_version_check(1, 0, 9): 161 | crypto_aead_chacha20poly1305_ietf_KEYBYTES = sodium.crypto_aead_chacha20poly1305_ietf_keybytes() 162 | crypto_aead_chacha20poly1305_ietf_NPUBBYTES = sodium.crypto_aead_chacha20poly1305_ietf_npubbytes() 163 | crypto_aead_chacha20poly1305_ietf_ABYTES = sodium.crypto_aead_chacha20poly1305_ietf_abytes() 164 | crypto_pwhash_SALTBYTES = sodium.crypto_pwhash_saltbytes() 165 | crypto_pwhash_STRBYTES = sodium.crypto_pwhash_strbytes() 166 | crypto_pwhash_OPSLIMIT_INTERACTIVE = sodium.crypto_pwhash_opslimit_interactive() 167 | crypto_pwhash_MEMLIMIT_INTERACTIVE = sodium.crypto_pwhash_memlimit_interactive() 168 | crypto_pwhash_OPSLIMIT_MODERATE = sodium.crypto_pwhash_opslimit_moderate() 169 | crypto_pwhash_MEMLIMIT_MODERATE = sodium.crypto_pwhash_memlimit_moderate() 170 | crypto_pwhash_OPSLIMIT_SENSITIVE = sodium.crypto_pwhash_opslimit_sensitive() 171 | crypto_pwhash_MEMLIMIT_SENSITIVE = sodium.crypto_pwhash_memlimit_sensitive() 172 | crypto_pwhash_ALG_DEFAULT = sodium.crypto_pwhash_alg_default() 173 | crypto_pwhash_ALG_ARGON2I13 = sodium.crypto_pwhash_alg_argon2i13() 174 | crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE = sodium.crypto_pwhash_argon2i_opslimit_interactive() 175 | crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE = sodium.crypto_pwhash_argon2i_memlimit_interactive() 176 | crypto_pwhash_argon2i_OPSLIMIT_MODERATE = sodium.crypto_pwhash_argon2i_opslimit_moderate() 177 | crypto_pwhash_argon2i_MEMLIMIT_MODERATE = sodium.crypto_pwhash_argon2i_memlimit_moderate() 178 | crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE = sodium.crypto_pwhash_argon2i_opslimit_sensitive() 179 | crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE = sodium.crypto_pwhash_argon2i_memlimit_sensitive() 180 | else: 181 | crypto_pwhash_ALG_DEFAULT = None 182 | crypto_aead_chacha20poly1305_ietf_KEYBYTES = 32 183 | crypto_aead_chacha20poly1305_ietf_NPUBBYTES = 12 184 | crypto_aead_chacha20poly1305_ietf_ABYTES = 16 185 | crypto_pwhash_BYTES_MAX = 4294967295 186 | crypto_pwhash_BYTES_MIN = 16 187 | crypto_pwhash_MEMLIMIT_MAX = 4398046510080 188 | crypto_pwhash_MEMLIMIT_MIN = 1 189 | crypto_pwhash_OPSLIMIT_MAX = 4294967295 190 | crypto_pwhash_OPSLIMIT_MIN = 3 191 | crypto_pwhash_PASSWD_MAX = 4294967295 192 | crypto_pwhash_PASSWD_MIN = 0 193 | 194 | crypto_aead_chacha20poly1305_ietf_NONCEBYTES = crypto_aead_chacha20poly1305_ietf_NPUBBYTES 195 | 196 | if sodium_version_check(1, 0, 12): 197 | crypto_kx_PUBLICKEYBYTES = sodium.crypto_kx_publickeybytes() 198 | crypto_kx_SECRETKEYBYTES = sodium.crypto_kx_secretkeybytes() 199 | crypto_kx_SESSIONKEYBYTES = sodium.crypto_kx_sessionkeybytes() 200 | crypto_aead_xchacha20poly1305_ietf_KEYBYTES = sodium.crypto_aead_xchacha20poly1305_ietf_keybytes() 201 | crypto_aead_xchacha20poly1305_ietf_NPUBBYTES = sodium.crypto_aead_xchacha20poly1305_ietf_npubbytes() 202 | crypto_aead_xchacha20poly1305_ietf_NONCEBYTES = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES 203 | crypto_aead_xchacha20poly1305_ietf_ABYTES = sodium.crypto_aead_xchacha20poly1305_ietf_abytes() 204 | sodium.crypto_pwhash_bytes_max.restype=ctypes.c_uint 205 | sodium.crypto_pwhash_opslimit_max.restype=ctypes.c_uint 206 | sodium.crypto_pwhash_memlimit_max.restype=ctypes.c_uint 207 | sodium.crypto_pwhash_passwd_max.restype=ctypes.c_uint 208 | sodium.crypto_pwhash_scryptsalsa208sha256_bytes_max.restype=ctypes.c_uint 209 | sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_max.restype=ctypes.c_uint 210 | sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_max.restype=ctypes.c_ulonglong 211 | sodium.crypto_pwhash_scryptsalsa208sha256_passwd_max.restype=ctypes.c_uint 212 | crypto_pwhash_BYTES_MAX = sodium.crypto_pwhash_bytes_max() 213 | crypto_pwhash_BYTES_MIN = sodium.crypto_pwhash_bytes_min() 214 | crypto_pwhash_MEMLIMIT_MAX = sodium.crypto_pwhash_memlimit_max() 215 | crypto_pwhash_MEMLIMIT_MIN = sodium.crypto_pwhash_memlimit_min() 216 | crypto_pwhash_OPSLIMIT_MAX = sodium.crypto_pwhash_opslimit_max() 217 | crypto_pwhash_OPSLIMIT_MIN = sodium.crypto_pwhash_opslimit_min() 218 | crypto_pwhash_PASSWD_MAX = sodium.crypto_pwhash_passwd_max() 219 | crypto_pwhash_PASSWD_MIN = sodium.crypto_pwhash_passwd_min() 220 | crypto_pwhash_scryptsalsa208sha256_BYTES_MAX = sodium.crypto_pwhash_scryptsalsa208sha256_bytes_max() 221 | crypto_pwhash_scryptsalsa208sha256_BYTES_MIN = sodium.crypto_pwhash_scryptsalsa208sha256_bytes_min() 222 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX = sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_max() 223 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN = sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_min() 224 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX = sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_max() 225 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN = sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_min() 226 | crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX = sodium.crypto_pwhash_scryptsalsa208sha256_passwd_max() 227 | crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN = sodium.crypto_pwhash_scryptsalsa208sha256_passwd_min() 228 | else: 229 | crypto_pwhash_scryptsalsa208sha256_BYTES_MIN = 16 230 | crypto_pwhash_scryptsalsa208sha256_BYTES_MAX = 4294967264 231 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX = 68719476736 232 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN = 16777216 233 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN = 32768 234 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX =4294967295 235 | crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX = 4294967295 236 | crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN = 0 237 | 238 | if sodium_version_check(1, 0, 13): 239 | crypto_pwhash_ALG_ARGON2ID13 = sodium.crypto_pwhash_alg_argon2id13() 240 | crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE = sodium.crypto_pwhash_argon2id_opslimit_interactive() 241 | crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE = sodium.crypto_pwhash_argon2id_memlimit_interactive() 242 | crypto_pwhash_argon2id_OPSLIMIT_MODERATE = sodium.crypto_pwhash_argon2id_opslimit_moderate() 243 | crypto_pwhash_argon2id_MEMLIMIT_MODERATE = sodium.crypto_pwhash_argon2id_memlimit_moderate() 244 | crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE = sodium.crypto_pwhash_argon2id_opslimit_sensitive() 245 | crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE = sodium.crypto_pwhash_argon2id_memlimit_sensitive() 246 | 247 | if sodium_version_check(1, 0, 15): 248 | crypto_secretstream_xchacha20poly1305_STATEBYTES = sodium.crypto_secretstream_xchacha20poly1305_statebytes() 249 | crypto_secretstream_xchacha20poly1305_ABYTES = sodium.crypto_secretstream_xchacha20poly1305_abytes() 250 | crypto_secretstream_xchacha20poly1305_HEADERBYTES = sodium.crypto_secretstream_xchacha20poly1305_headerbytes() 251 | crypto_secretstream_xchacha20poly1305_KEYBYTES = sodium.crypto_secretstream_xchacha20poly1305_keybytes() 252 | sodium.crypto_secretstream_xchacha20poly1305_messagebytes_max.restype = ctypes.c_size_t 253 | crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = sodium.crypto_secretstream_xchacha20poly1305_messagebytes_max() 254 | crypto_secretstream_xchacha20poly1305_TAG_MESSAGE = sodium.crypto_secretstream_xchacha20poly1305_tag_message() 255 | crypto_secretstream_xchacha20poly1305_TAG_PUSH = sodium.crypto_secretstream_xchacha20poly1305_tag_push() 256 | crypto_secretstream_xchacha20poly1305_TAG_REKEY = sodium.crypto_secretstream_xchacha20poly1305_tag_rekey() 257 | crypto_secretstream_xchacha20poly1305_TAG_FINAL = sodium.crypto_secretstream_xchacha20poly1305_tag_final() 258 | 259 | if sodium_version_check(1, 0, 18): 260 | crypto_core_ristretto255_BYTES = sodium.crypto_core_ristretto255_bytes() 261 | crypto_core_ristretto255_HASHBYTES = sodium.crypto_core_ristretto255_hashbytes() 262 | crypto_core_ristretto255_SCALARBYTES = sodium.crypto_core_ristretto255_scalarbytes() 263 | crypto_core_ristretto255_NONREDUCEDSCALARBYTES = sodium.crypto_core_ristretto255_nonreducedscalarbytes() 264 | crypto_auth_hmacsha256_BYTES = sodium.crypto_auth_hmacsha256_bytes() 265 | crypto_auth_hmacsha256_KEYBYTES = sodium.crypto_auth_hmacsha256_keybytes() 266 | crypto_hash_sha256_STATEBYTES = sodium.crypto_hash_sha256_statebytes() 267 | crypto_auth_hmacsha512_BYTES = sodium.crypto_auth_hmacsha512_bytes() 268 | crypto_auth_hmacsha512_KEYBYTES = sodium.crypto_auth_hmacsha512_keybytes() 269 | crypto_hash_sha512_STATEBYTES = sodium.crypto_hash_sha512_statebytes() 270 | crypto_auth_hmacsha512256_BYTES = sodium.crypto_auth_hmacsha512256_bytes() 271 | crypto_auth_hmacsha512256_KEYBYTES = sodium.crypto_auth_hmacsha512256_keybytes() 272 | 273 | if sodium_version_check(1, 0, 19): 274 | crypto_kdf_hkdf_sha256_KEYBYTES = sodium.crypto_kdf_hkdf_sha256_keybytes() 275 | crypto_kdf_hkdf_sha256_BYTES_MIN = sodium.crypto_kdf_hkdf_sha256_bytes_min() 276 | crypto_kdf_hkdf_sha256_BYTES_MAX = sodium.crypto_kdf_hkdf_sha256_bytes_max() 277 | crypto_kdf_hkdf_sha256_STATEBYTES = sodium.crypto_kdf_hkdf_sha256_statebytes() 278 | crypto_kdf_hkdf_sha512_KEYBYTES = sodium.crypto_kdf_hkdf_sha512_keybytes() 279 | crypto_kdf_hkdf_sha512_BYTES_MIN = sodium.crypto_kdf_hkdf_sha512_bytes_min() 280 | crypto_kdf_hkdf_sha512_BYTES_MAX = sodium.crypto_kdf_hkdf_sha512_bytes_max() 281 | crypto_aead_aegis128l_KEYBYTES = sodium.crypto_aead_aegis128l_keybytes() 282 | crypto_aead_aegis128l_NPUBBYTES = sodium.crypto_aead_aegis128l_npubbytes() 283 | crypto_aead_aegis128l_NONCEBYTES = crypto_aead_aegis128l_NPUBBYTES 284 | crypto_aead_aegis128l_ABYTES = sodium.crypto_aead_aegis128l_abytes() 285 | sodium.crypto_aead_aegis128l_messagebytes_max.restype = ctypes.c_size_t 286 | crypto_aead_aegis128l_MESSAGEBYTES_MAX = sodium.crypto_aead_aegis128l_messagebytes_max() 287 | crypto_aead_aegis256_KEYBYTES = sodium.crypto_aead_aegis256_keybytes() 288 | crypto_aead_aegis256_NPUBBYTES = sodium.crypto_aead_aegis256_npubbytes() 289 | crypto_aead_aegis256_NONCEBYTES = crypto_aead_aegis256_NPUBBYTES 290 | crypto_aead_aegis256_ABYTES = sodium.crypto_aead_aegis256_abytes() 291 | sodium.crypto_aead_aegis256_messagebytes_max.restype = ctypes.c_size_t 292 | crypto_aead_aegis256_MESSAGEBYTES_MAX = sodium.crypto_aead_aegis256_messagebytes_max() 293 | 294 | if sodium_version_check(1, 0, 20): 295 | crypto_kdf_hkdf_sha512_STATEBYTES = sodium.crypto_kdf_hkdf_sha512_statebytes() 296 | 297 | sodium_init = sodium.sodium_init 298 | 299 | class CryptoSignState(ctypes.Structure): 300 | _pack_ = 1 301 | _fields_ = [ 302 | ('state', ctypes.c_uint64 * 8), 303 | ('count', ctypes.c_uint64 * 2), 304 | ('buf', ctypes.c_uint8 * 128) 305 | ] 306 | 307 | def __check(code): 308 | if code != 0: 309 | raise ValueError 310 | 311 | 312 | def pad_buf(buf, length, name = 'buf'): 313 | buflen = len(buf) 314 | if buflen > length: 315 | raise ValueError("Cannot pad %s (len: %d - expected %d or less)" % (name, buflen, length)) 316 | 317 | padding = length - buflen 318 | if padding > 0: 319 | return buf + b"\x00"*padding 320 | else: 321 | return buf 322 | 323 | # int crypto_scalarmult_base(unsigned char *q, const unsigned char *n); 324 | def crypto_scalarmult_base(n): 325 | if n is None: 326 | raise ValueError("invalid parameters") 327 | if len(n) != crypto_scalarmult_SCALARBYTES: raise ValueError("truncated scalar") 328 | q = ctypes.create_string_buffer(crypto_scalarmult_BYTES) 329 | __check(sodium.crypto_scalarmult_base(q, n)) 330 | return q.raw 331 | 332 | def crypto_scalarmult_curve25519(n, p): 333 | if None in (n,p): 334 | raise ValueError("invalid parameters") 335 | if len(n) != crypto_scalarmult_SCALARBYTES: raise ValueError("truncated scalar") 336 | if len(p) != crypto_scalarmult_BYTES: raise ValueError("truncated point") 337 | buf = ctypes.create_string_buffer(crypto_scalarmult_BYTES) 338 | __check(sodium.crypto_scalarmult_curve25519(buf, n, p)) 339 | return buf.raw 340 | 341 | 342 | def crypto_scalarmult_curve25519_base(n): 343 | if n is None: 344 | raise ValueError("invalid parameters") 345 | if len(n) != crypto_scalarmult_SCALARBYTES: raise ValueError("truncated scalar") 346 | buf = ctypes.create_string_buffer(crypto_scalarmult_BYTES) 347 | __check(sodium.crypto_scalarmult_curve25519_base(buf, n)) 348 | return buf.raw 349 | 350 | # crypto_stream_chacha20_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k) 351 | def crypto_stream_chacha20_xor(message, nonce, key): 352 | if len(nonce) != crypto_stream_chacha20_NONCEBYTES: raise ValueError("truncated nonce") 353 | if len(key) != crypto_stream_chacha20_KEYBYTES: raise ValueError("truncated key") 354 | 355 | mlen = ctypes.c_longlong(len(message)) 356 | 357 | c = ctypes.create_string_buffer(len(message)) 358 | 359 | __check(sodium.crypto_stream_chacha20_xor(c, message, mlen, nonce, key)) 360 | 361 | return c.raw 362 | 363 | # crypto_stream_chacha20_xor_ic(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, uint64_t ic, const unsigned char *k) 364 | def crypto_stream_chacha20_xor_ic(message, nonce, initial_counter, key): 365 | if len(nonce) != crypto_stream_chacha20_NONCEBYTES: raise ValueError("truncated nonce") 366 | if len(key) != crypto_stream_chacha20_KEYBYTES: raise ValueError("truncated key") 367 | 368 | mlen = ctypes.c_longlong(len(message)) 369 | ic = ctypes.c_uint64(initial_counter) 370 | 371 | c = ctypes.create_string_buffer(len(message)) 372 | 373 | __check(sodium.crypto_stream_chacha20_xor_ic(c, message, mlen, nonce, ic, key)) 374 | 375 | return c.raw 376 | 377 | # crypto_stream_chacha20_ietf_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k) 378 | def crypto_stream_chacha20_ietf_xor(message, nonce, key): 379 | if len(nonce) != crypto_stream_chacha20_ietf_NONCEBYTES: raise ValueError("truncated nonce") 380 | if len(key) != crypto_stream_chacha20_ietf_KEYBYTES: raise ValueError("truncated key") 381 | 382 | mlen = ctypes.c_longlong(len(message)) 383 | 384 | c = ctypes.create_string_buffer(len(message)) 385 | 386 | __check(sodium.crypto_stream_chacha20_ietf_xor(c, message, mlen, nonce, key)) 387 | 388 | return c.raw 389 | 390 | # crypto_stream_chacha20_ietf_xor_ic(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, uint32_t ic, const unsigned char *k) 391 | def crypto_stream_chacha20_ietf_xor_ic(message, nonce, initial_counter, key): 392 | if len(nonce) != crypto_stream_chacha20_ietf_NONCEBYTES: raise ValueError("truncated nonce") 393 | if len(key) != crypto_stream_chacha20_ietf_KEYBYTES: raise ValueError("truncated key") 394 | 395 | mlen = ctypes.c_longlong(len(message)) 396 | ic = ctypes.c_uint32(initial_counter) 397 | 398 | c = ctypes.create_string_buffer(len(message)) 399 | 400 | __check(sodium.crypto_stream_chacha20_ietf_xor_ic(c, message, mlen, nonce, ic, key)) 401 | 402 | return c.raw 403 | 404 | # crypto_stream_xchacha20_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k) 405 | def crypto_stream_xchacha20_xor(message, nonce, key): 406 | if len(nonce) != crypto_stream_xchacha20_NONCEBYTES: raise ValueError("truncated nonce") 407 | if len(key) != crypto_stream_xchacha20_KEYBYTES: raise ValueError("truncated key") 408 | 409 | mlen = ctypes.c_longlong(len(message)) 410 | 411 | c = ctypes.create_string_buffer(len(message)) 412 | 413 | __check(sodium.crypto_stream_xchacha20_xor(c, message, mlen, nonce, key)) 414 | 415 | return c.raw 416 | 417 | # crypto_stream_xchacha20_xor_ic(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, uint64_t ic, const unsigned char *k) 418 | def crypto_stream_xchacha20_xor_ic(message, nonce, initial_counter, key): 419 | if len(nonce) != crypto_stream_xchacha20_NONCEBYTES: raise ValueError("truncated nonce") 420 | if len(key) != crypto_stream_xchacha20_KEYBYTES: raise ValueError("truncated key") 421 | 422 | mlen = ctypes.c_longlong(len(message)) 423 | ic = ctypes.c_uint64(initial_counter) 424 | 425 | c = ctypes.create_string_buffer(len(message)) 426 | 427 | __check(sodium.crypto_stream_xchacha20_xor_ic(c, message, mlen, nonce, ic, key)) 428 | 429 | return c.raw 430 | 431 | # crypto_aead_chacha20poly1305_encrypt(unsigned char *c, unsigned long long *clen, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k); 432 | def crypto_aead_chacha20poly1305_encrypt(message, ad, nonce, key): 433 | if len(nonce) != crypto_aead_chacha20poly1305_NONCEBYTES: raise ValueError("truncated nonce") 434 | if len(key) != crypto_aead_chacha20poly1305_KEYBYTES: raise ValueError("truncated key") 435 | 436 | mlen = ctypes.c_ulonglong(len(message)) 437 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 438 | 439 | c = ctypes.create_string_buffer(mlen.value + crypto_aead_chacha20poly1305_ABYTES) 440 | clen = ctypes.c_ulonglong(0) 441 | 442 | __check(sodium.crypto_aead_chacha20poly1305_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key)) 443 | return c.raw 444 | 445 | 446 | # crypto_aead_chacha20poly1305_decrypt(unsigned char *m, unsigned long long *mlen, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) 447 | def crypto_aead_chacha20poly1305_decrypt(ciphertext, ad, nonce, key): 448 | if len(nonce) != crypto_aead_chacha20poly1305_NONCEBYTES: raise ValueError("truncated nonce") 449 | if len(key) != crypto_aead_chacha20poly1305_KEYBYTES: raise ValueError("truncated key") 450 | 451 | m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_chacha20poly1305_ABYTES) 452 | mlen = ctypes.c_ulonglong(0) 453 | clen = ctypes.c_ulonglong(len(ciphertext)) 454 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 455 | __check(sodium.crypto_aead_chacha20poly1305_decrypt(m, ctypes.byref(mlen), None, ciphertext, clen, ad, adlen, nonce, key)) 456 | return m.raw 457 | 458 | # crypto_aead_chacha20poly1305_encrypt_detached(unsigned char *c, unsigned char *mac, unsigned long long *maclen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k) 459 | @sodium_version(1, 0, 9) 460 | def crypto_aead_chacha20poly1305_encrypt_detached(message, ad, nonce, key): 461 | """ Return ciphertext, mac tag """ 462 | if len(nonce) != crypto_aead_chacha20poly1305_NONCEBYTES: raise ValueError("truncated nonce") 463 | if len(key) != crypto_aead_chacha20poly1305_KEYBYTES: raise ValueError("truncated key") 464 | 465 | mlen = ctypes.c_ulonglong(len(message)) 466 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 467 | c = ctypes.create_string_buffer(mlen.value) 468 | maclen_p = ctypes.c_ulonglong(crypto_aead_chacha20poly1305_ABYTES) 469 | mac = ctypes.create_string_buffer(maclen_p.value) 470 | 471 | __check(sodium.crypto_aead_chacha20poly1305_encrypt_detached(c, mac, ctypes.byref(maclen_p), message, mlen, ad, adlen, None, nonce, key)) 472 | return c.raw, mac.raw 473 | 474 | # crypto_aead_chacha20poly1305_decrypt_detached(unsigned char *m, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *mac, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) 475 | @sodium_version(1, 0, 9) 476 | def crypto_aead_chacha20poly1305_decrypt_detached(ciphertext, mac, ad, nonce, key): 477 | """ Return message if successful or -1 (ValueError) if not successful""" 478 | if len(nonce) != crypto_aead_chacha20poly1305_NONCEBYTES: raise ValueError("truncated nonce") 479 | if len(key) != crypto_aead_chacha20poly1305_KEYBYTES: raise ValueError("truncated key") 480 | if len(mac) != crypto_aead_chacha20poly1305_ABYTES: 481 | raise ValueError("mac length != %i" % crypto_aead_chacha20poly1305_ABYTES) 482 | 483 | clen = ctypes.c_ulonglong(len(ciphertext)) 484 | m = ctypes.create_string_buffer(clen.value) 485 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 486 | __check(sodium.crypto_aead_chacha20poly1305_decrypt_detached(m, None, ciphertext, clen, mac, ad, adlen, nonce, key)) 487 | return m.raw 488 | 489 | # crypto_aead_aegis128l_encrypt(unsigned char *c, unsigned long long *clen, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k); 490 | @sodium_version(1, 0, 19) 491 | def crypto_aead_aegis128l_encrypt(message, ad, nonce, key): 492 | if len(nonce) != crypto_aead_aegis128l_NONCEBYTES: raise ValueError("truncated nonce") 493 | if len(key) != crypto_aead_aegis128l_KEYBYTES: raise ValueError("truncated key") 494 | 495 | mlen = ctypes.c_ulonglong(len(message)) 496 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 497 | 498 | c = ctypes.create_string_buffer(mlen.value + crypto_aead_aegis128l_ABYTES) 499 | clen = ctypes.c_ulonglong(0) 500 | 501 | __check(sodium.crypto_aead_aegis128l_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key)) 502 | return c.raw 503 | 504 | 505 | # crypto_aead_aegis128l_decrypt(unsigned char *m, unsigned long long *mlen, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) 506 | @sodium_version(1, 0, 19) 507 | def crypto_aead_aegis128l_decrypt(ciphertext, ad, nonce, key): 508 | if len(nonce) != crypto_aead_aegis128l_NONCEBYTES: raise ValueError("truncated nonce") 509 | if len(key) != crypto_aead_aegis128l_KEYBYTES: raise ValueError("truncated key") 510 | 511 | m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_aegis128l_ABYTES) 512 | mlen = ctypes.c_ulonglong(0) 513 | clen = ctypes.c_ulonglong(len(ciphertext)) 514 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 515 | __check(sodium.crypto_aead_aegis128l_decrypt(m, ctypes.byref(mlen), None, ciphertext, clen, ad, adlen, nonce, key)) 516 | return m.raw 517 | 518 | # crypto_aead_aegis128l_encrypt_detached(unsigned char *c, unsigned char *mac, unsigned long long *maclen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k) 519 | @sodium_version(1, 0, 19) 520 | def crypto_aead_aegis128l_encrypt_detached(message, ad, nonce, key): 521 | """ Return ciphertext, mac tag """ 522 | if len(nonce) != crypto_aead_aegis128l_NONCEBYTES: raise ValueError("truncated nonce") 523 | if len(key) != crypto_aead_aegis128l_KEYBYTES: raise ValueError("truncated key") 524 | 525 | mlen = ctypes.c_ulonglong(len(message)) 526 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 527 | c = ctypes.create_string_buffer(mlen.value) 528 | maclen_p = ctypes.c_ulonglong(crypto_aead_aegis128l_ABYTES) 529 | mac = ctypes.create_string_buffer(maclen_p.value) 530 | 531 | __check(sodium.crypto_aead_aegis128l_encrypt_detached(c, mac, ctypes.byref(maclen_p), message, mlen, ad, adlen, None, nonce, key)) 532 | return c.raw, mac.raw 533 | 534 | # crypto_aead_aegis128l_decrypt_detached(unsigned char *m, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *mac, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) 535 | @sodium_version(1, 0, 19) 536 | def crypto_aead_aegis128l_decrypt_detached(ciphertext, mac, ad, nonce, key): 537 | """ Return message if successful or -1 (ValueError) if not successful""" 538 | if len(nonce) != crypto_aead_aegis128l_NONCEBYTES: raise ValueError("truncated nonce") 539 | if len(key) != crypto_aead_aegis128l_KEYBYTES: raise ValueError("truncated key") 540 | if len(mac) != crypto_aead_aegis128l_ABYTES: 541 | raise ValueError("mac length != %i" % crypto_aead_aegis128l_ABYTES) 542 | 543 | clen = ctypes.c_ulonglong(len(ciphertext)) 544 | m = ctypes.create_string_buffer(clen.value) 545 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 546 | __check(sodium.crypto_aead_aegis128l_decrypt_detached(m, None, ciphertext, clen, mac, ad, adlen, nonce, key)) 547 | return m.raw 548 | 549 | # crypto_aead_aegis256_encrypt(unsigned char *c, unsigned long long *clen, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k); 550 | @sodium_version(1, 0, 19) 551 | def crypto_aead_aegis256_encrypt(message, ad, nonce, key): 552 | if len(nonce) != crypto_aead_aegis256_NONCEBYTES: raise ValueError("truncated nonce") 553 | if len(key) != crypto_aead_aegis256_KEYBYTES: raise ValueError("truncated key") 554 | 555 | mlen = ctypes.c_ulonglong(len(message)) 556 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 557 | 558 | c = ctypes.create_string_buffer(mlen.value + crypto_aead_aegis256_ABYTES) 559 | clen = ctypes.c_ulonglong(0) 560 | 561 | __check(sodium.crypto_aead_aegis256_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key)) 562 | return c.raw 563 | 564 | 565 | # crypto_aead_aegis256_decrypt(unsigned char *m, unsigned long long *mlen, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) 566 | @sodium_version(1, 0, 19) 567 | def crypto_aead_aegis256_decrypt(ciphertext, ad, nonce, key): 568 | if len(nonce) != crypto_aead_aegis256_NONCEBYTES: raise ValueError("truncated nonce") 569 | if len(key) != crypto_aead_aegis256_KEYBYTES: raise ValueError("truncated key") 570 | 571 | m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_aegis256_ABYTES) 572 | mlen = ctypes.c_ulonglong(0) 573 | clen = ctypes.c_ulonglong(len(ciphertext)) 574 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 575 | __check(sodium.crypto_aead_aegis256_decrypt(m, ctypes.byref(mlen), None, ciphertext, clen, ad, adlen, nonce, key)) 576 | return m.raw 577 | 578 | # crypto_aead_aegis256_encrypt_detached(unsigned char *c, unsigned char *mac, unsigned long long *maclen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k) 579 | @sodium_version(1, 0, 19) 580 | def crypto_aead_aegis256_encrypt_detached(message, ad, nonce, key): 581 | """ Return ciphertext, mac tag """ 582 | if len(nonce) != crypto_aead_aegis256_NONCEBYTES: raise ValueError("truncated nonce") 583 | if len(key) != crypto_aead_aegis256_KEYBYTES: raise ValueError("truncated key") 584 | 585 | mlen = ctypes.c_ulonglong(len(message)) 586 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 587 | c = ctypes.create_string_buffer(mlen.value) 588 | maclen_p = ctypes.c_ulonglong(crypto_aead_aegis256_ABYTES) 589 | mac = ctypes.create_string_buffer(maclen_p.value) 590 | 591 | __check(sodium.crypto_aead_aegis256_encrypt_detached(c, mac, ctypes.byref(maclen_p), message, mlen, ad, adlen, None, nonce, key)) 592 | return c.raw, mac.raw 593 | 594 | # crypto_aead_aegis256_decrypt_detached(unsigned char *m, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *mac, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) 595 | @sodium_version(1, 0, 19) 596 | def crypto_aead_aegis256_decrypt_detached(ciphertext, mac, ad, nonce, key): 597 | """ Return message if successful or -1 (ValueError) if not successful""" 598 | if len(nonce) != crypto_aead_aegis256_NONCEBYTES: raise ValueError("truncated nonce") 599 | if len(key) != crypto_aead_aegis256_KEYBYTES: raise ValueError("truncated key") 600 | if len(mac) != crypto_aead_aegis256_ABYTES: 601 | raise ValueError("mac length != %i" % crypto_aead_aegis256_ABYTES) 602 | 603 | clen = ctypes.c_ulonglong(len(ciphertext)) 604 | m = ctypes.create_string_buffer(clen.value) 605 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 606 | __check(sodium.crypto_aead_aegis256_decrypt_detached(m, None, ciphertext, clen, mac, ad, adlen, nonce, key)) 607 | return m.raw 608 | 609 | # crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c, unsigned long long *clen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k) 610 | @sodium_version(1, 0, 4) 611 | def crypto_aead_chacha20poly1305_ietf_encrypt(message, ad, nonce, key): 612 | if len(nonce) != crypto_aead_chacha20poly1305_ietf_NONCEBYTES: raise ValueError("truncated nonce") 613 | if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key") 614 | 615 | mlen = ctypes.c_ulonglong(len(message)) 616 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 617 | c = ctypes.create_string_buffer(mlen.value + crypto_aead_chacha20poly1305_ietf_ABYTES) 618 | clen = ctypes.c_ulonglong(0) 619 | 620 | __check(sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key)) 621 | return c.raw 622 | 623 | # crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m, unsigned long long *mlen, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) 624 | @sodium_version(1, 0, 4) 625 | def crypto_aead_chacha20poly1305_ietf_decrypt(ciphertext, ad, nonce, key): 626 | if len(nonce) != crypto_aead_chacha20poly1305_ietf_NONCEBYTES: raise ValueError("truncated nonce") 627 | if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key") 628 | 629 | m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_chacha20poly1305_ietf_ABYTES) 630 | mlen = ctypes.c_ulonglong(0) 631 | clen = ctypes.c_ulonglong(len(ciphertext)) 632 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 633 | __check(sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m, ctypes.byref(mlen), None, ciphertext, clen, ad, adlen, nonce, key)) 634 | return m.raw 635 | 636 | # crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char *c, unsigned char *mac, unsigned long long *maclen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k) 637 | @sodium_version(1, 0, 9) 638 | def crypto_aead_chacha20poly1305_ietf_encrypt_detached(message, ad, nonce, key): 639 | """ Return ciphertext, mac tag """ 640 | if len(nonce) != crypto_aead_chacha20poly1305_ietf_NONCEBYTES: raise ValueError("truncated nonce") 641 | if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key") 642 | 643 | mlen = ctypes.c_ulonglong(len(message)) 644 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 645 | c = ctypes.create_string_buffer(mlen.value) 646 | maclen_p = ctypes.c_ulonglong(crypto_aead_chacha20poly1305_ietf_ABYTES) 647 | mac = ctypes.create_string_buffer(maclen_p.value) 648 | 649 | __check(sodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, ctypes.byref(maclen_p), message, mlen, ad, adlen, None, nonce, key)) 650 | return c.raw, mac.raw 651 | 652 | # crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char *m, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *mac, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) 653 | @sodium_version(1, 0, 9) 654 | def crypto_aead_chacha20poly1305_ietf_decrypt_detached(ciphertext, mac, ad, nonce, key): 655 | """ Return message if successful or -1 (ValueError) if not successful""" 656 | if len(nonce) != crypto_aead_chacha20poly1305_ietf_NONCEBYTES: raise ValueError("truncated nonce") 657 | if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key") 658 | if len(mac) != crypto_aead_chacha20poly1305_ietf_ABYTES: 659 | raise ValueError("mac length != %i" % crypto_aead_chacha20poly1305_ietf_ABYTES) 660 | 661 | clen = ctypes.c_ulonglong(len(ciphertext)) 662 | m = ctypes.create_string_buffer(clen.value) 663 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 664 | __check(sodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, None, ciphertext, clen, mac, ad, adlen, nonce, key)) 665 | return m.raw 666 | 667 | #crypto_aead_xchacha20poly1305_ietf_encrypt(ciphertext, &ciphertext_len, 668 | # message, message_len, 669 | # additional_data, additional_data_len, 670 | # null, nonce, key); 671 | @sodium_version(1, 0, 12) 672 | def crypto_aead_xchacha20poly1305_ietf_encrypt(message, ad, nonce, key): 673 | if len(nonce) != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: raise ValueError("truncated nonce") 674 | if len(key) != crypto_aead_xchacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key") 675 | mlen = ctypes.c_ulonglong(len(message)) 676 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 677 | c = ctypes.create_string_buffer(mlen.value + crypto_aead_xchacha20poly1305_ietf_ABYTES) 678 | clen = ctypes.c_ulonglong(0) 679 | 680 | __check(sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(c, ctypes.byref(clen), 681 | message, mlen, 682 | ad, adlen, 683 | None, nonce, key)) 684 | return c.raw 685 | 686 | #crypto_aead_xchacha20poly1305_ietf_decrypt(decrypted, &decrypted_len, 687 | # null, 688 | # ciphertext, ciphertext_len, 689 | # additional_data, additional_data_len, 690 | # nonce, key); 691 | @sodium_version(1, 0, 12) 692 | def crypto_aead_xchacha20poly1305_ietf_decrypt(ciphertext, ad, nonce, key): 693 | if len(nonce) != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: raise ValueError("truncated nonce") 694 | if len(key) != crypto_aead_xchacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key") 695 | 696 | m = ctypes.create_string_buffer(len(ciphertext) - crypto_aead_xchacha20poly1305_ietf_ABYTES) 697 | mlen = ctypes.c_ulonglong(0) 698 | clen = ctypes.c_ulonglong(len(ciphertext)) 699 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 700 | __check(sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(m, ctypes.byref(mlen), 701 | None, 702 | ciphertext, clen, 703 | ad, adlen, 704 | nonce, key)) 705 | return m.raw 706 | 707 | # crypto_auth(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *k) 708 | def crypto_auth(m, k): 709 | if m is None or k is None: 710 | raise ValueError("invalid parameters") 711 | if len(k) != crypto_auth_KEYBYTES: 712 | raise ValueError("invalid key") 713 | buf = ctypes.create_string_buffer(crypto_auth_BYTES) 714 | __check(sodium.crypto_auth(buf, m, ctypes.c_ulonglong(len(m)), k)) 715 | return buf.raw 716 | 717 | # crypto_auth_verify(const unsigned char *h, const unsigned char *in, unsigned long long inlen, const unsigned char *k) 718 | def crypto_auth_verify(h, m, k): 719 | if h is None or m is None or k is None: 720 | raise ValueError("invalid parameters") 721 | if len(k) != crypto_auth_KEYBYTES: 722 | raise ValueError("invalid key") 723 | if len(h) != crypto_auth_BYTES: 724 | raise ValueError("invalid tag") 725 | __check(sodium.crypto_auth_verify(h, m, ctypes.c_ulonglong(len(m)), k)) 726 | 727 | 728 | # void crypto_auth_hmacsha256_keygen(unsigned char k[crypto_auth_hmacsha256_KEYBYTES]); 729 | def crypto_auth_hmacsha256_keygen(): 730 | k = ctypes.create_string_buffer(crypto_auth_hmacsha256_KEYBYTES) 731 | sodium.crypto_auth_hmacsha256_keygen(k) 732 | return k.raw 733 | 734 | 735 | # int crypto_auth_hmacsha256(unsigned char *out, 736 | # const unsigned char *in, 737 | # unsigned long long inlen, 738 | # const unsigned char *k); 739 | def crypto_auth_hmacsha256(m, k): 740 | if not len(k) == crypto_auth_hmacsha256_KEYBYTES: 741 | raise ValueError("invalid parameters") 742 | buf = ctypes.create_string_buffer(crypto_auth_hmacsha256_BYTES) 743 | msg = ctypes.create_string_buffer(m) 744 | key = ctypes.create_string_buffer(k) 745 | __check( 746 | sodium.crypto_auth_hmacsha256( 747 | ctypes.byref(buf), 748 | ctypes.byref(msg), 749 | ctypes.c_ulonglong(len(m)), 750 | ctypes.byref(key), 751 | ) 752 | ) 753 | return buf.raw 754 | 755 | 756 | # int crypto_auth_hmacsha256_verify(const unsigned char *h, 757 | # const unsigned char *in, 758 | # unsigned long long inlen, 759 | # const unsigned char *k); 760 | def crypto_auth_hmacsha256_verify(h, m, k): 761 | if not len(k) == crypto_auth_hmacsha256_KEYBYTES: 762 | raise ValueError("invalid parameters") 763 | hmac = ctypes.create_string_buffer(h) 764 | msg = ctypes.create_string_buffer(m) 765 | mlen = ctypes.c_ulonglong(len(m)) 766 | key = ctypes.create_string_buffer(k) 767 | __check( 768 | sodium.crypto_auth_hmacsha256_verify( 769 | ctypes.byref(hmac), ctypes.byref(msg), mlen, ctypes.byref(key) 770 | ) 771 | ) 772 | 773 | 774 | # void crypto_auth_hmacsha512_keygen(unsigned char k[crypto_auth_hmacsha512_KEYBYTES]); 775 | def crypto_auth_hmacsha512_keygen(): 776 | k = ctypes.create_string_buffer(crypto_auth_hmacsha512_KEYBYTES) 777 | sodium.crypto_auth_hmacsha512_keygen(k) 778 | return k.raw 779 | 780 | 781 | # int crypto_auth_hmacsha512(unsigned char *out, 782 | # const unsigned char *in, 783 | # unsigned long long inlen, 784 | # const unsigned char *k); 785 | def crypto_auth_hmacsha512(m, k): 786 | if not len(k) == crypto_auth_hmacsha512_KEYBYTES: 787 | raise ValueError("invalid parameters") 788 | buf = ctypes.create_string_buffer(crypto_auth_hmacsha512_BYTES) 789 | msg = ctypes.create_string_buffer(m) 790 | key = ctypes.create_string_buffer(k) 791 | __check( 792 | sodium.crypto_auth_hmacsha512( 793 | ctypes.byref(buf), 794 | ctypes.byref(msg), 795 | ctypes.c_ulonglong(len(m)), 796 | ctypes.byref(key), 797 | ) 798 | ) 799 | return buf.raw 800 | 801 | 802 | # int crypto_auth_hmacsha512_verify(const unsigned char *h, 803 | # const unsigned char *in, 804 | # unsigned long long inlen, 805 | # const unsigned char *k); 806 | def crypto_auth_hmacsha512_verify(h, m, k): 807 | if not len(k) == crypto_auth_hmacsha512_KEYBYTES: 808 | raise ValueError("invalid parameters") 809 | hmac = ctypes.create_string_buffer(h) 810 | msg = ctypes.create_string_buffer(m) 811 | mlen = ctypes.c_ulonglong(len(m)) 812 | key = ctypes.create_string_buffer(k) 813 | __check( 814 | sodium.crypto_auth_hmacsha512_verify( 815 | ctypes.byref(hmac), ctypes.byref(msg), mlen, ctypes.byref(key) 816 | ) 817 | ) 818 | 819 | 820 | # void crypto_auth_hmacsha512256_keygen(unsigned char k[crypto_auth_hmacsha512256_KEYBYTES]); 821 | def crypto_auth_hmacsha512256_keygen(): 822 | k = ctypes.create_string_buffer(crypto_auth_hmacsha512256_KEYBYTES) 823 | sodium.crypto_auth_hmacsha512256_keygen(k) 824 | return k.raw 825 | 826 | 827 | # int crypto_auth_hmacsha512256(unsigned char *out, 828 | # const unsigned char *in, 829 | # unsigned long long inlen, 830 | # const unsigned char *k); 831 | def crypto_auth_hmacsha512256(m, k): 832 | if not len(k) == crypto_auth_hmacsha512256_KEYBYTES: 833 | raise ValueError("invalid parameters") 834 | buf = ctypes.create_string_buffer(crypto_auth_hmacsha512256_BYTES) 835 | msg = ctypes.create_string_buffer(m) 836 | key = ctypes.create_string_buffer(k) 837 | __check( 838 | sodium.crypto_auth_hmacsha512256( 839 | ctypes.byref(buf), 840 | ctypes.byref(msg), 841 | ctypes.c_ulonglong(len(m)), 842 | ctypes.byref(key), 843 | ) 844 | ) 845 | return buf.raw 846 | 847 | 848 | # int crypto_auth_hmacsha512256_verify(const unsigned char *h, 849 | # const unsigned char *in, 850 | # unsigned long long inlen, 851 | # const unsigned char *k); 852 | def crypto_auth_hmacsha512256_verify(h, m, k): 853 | if not len(k) == crypto_auth_hmacsha512256_KEYBYTES: 854 | raise ValueError("invalid parameters") 855 | hmac = ctypes.create_string_buffer(h) 856 | msg = ctypes.create_string_buffer(m) 857 | mlen = ctypes.c_ulonglong(len(m)) 858 | key = ctypes.create_string_buffer(k) 859 | __check( 860 | sodium.crypto_auth_hmacsha512256_verify( 861 | ctypes.byref(hmac), ctypes.byref(msg), mlen, ctypes.byref(key) 862 | ) 863 | ) 864 | 865 | 866 | # crypto_generichash(unsigned char *out, size_t outlen, const unsigned char *in, unsigned long long inlen, const unsigned char *key, size_t keylen) 867 | @encode_strings 868 | def crypto_generichash(m, k=b'', outlen=crypto_generichash_BYTES): 869 | buf = ctypes.create_string_buffer(outlen) 870 | __check(sodium.crypto_generichash(buf, ctypes.c_size_t(outlen), m, ctypes.c_ulonglong(len(m)), k, ctypes.c_size_t(len(k)))) 871 | return buf.raw 872 | 873 | 874 | # crypto_generichash_init(crypto_generichash_state *state, const unsigned char *key, const size_t keylen, const size_t outlen); 875 | @encode_strings 876 | def crypto_generichash_init(outlen=crypto_generichash_BYTES, k=b''): 877 | state = ctypes.create_string_buffer(crypto_generichash_STATEBYTES) 878 | __check(sodium.crypto_generichash_init(ctypes.byref(state), k, ctypes.c_size_t(len(k)), ctypes.c_size_t(outlen))) 879 | return state 880 | 881 | 882 | # crypto_generichash_update(crypto_generichash_state *state, const unsigned char *in, unsigned long long inlen); 883 | @encode_strings 884 | def crypto_generichash_update(state, m): 885 | if len(state) != crypto_generichash_STATEBYTES: raise ValueError("invalid state") 886 | __check(sodium.crypto_generichash_update(ctypes.byref(state), m, ctypes.c_ulonglong(len(m)))) 887 | return state 888 | 889 | 890 | # crypto_generichash_final(crypto_generichash_state *state, unsigned char *out, const size_t outlen); 891 | def crypto_generichash_final(state, outlen=crypto_generichash_BYTES): 892 | if len(state) != crypto_generichash_STATEBYTES: raise ValueError("invalid state") 893 | buf = ctypes.create_string_buffer(outlen) 894 | __check(sodium.crypto_generichash_final(ctypes.byref(state), buf, ctypes.c_size_t(outlen))) 895 | return buf.raw 896 | 897 | def crypto_generichash_blake2b_salt_personal(message, outlen = crypto_generichash_blake2b_BYTES, key = b'', salt = b'', personal = b''): 898 | keylen = len(key) 899 | 900 | if keylen != 0 and not crypto_generichash_blake2b_BYTES_MIN <= keylen <= crypto_generichash_blake2b_KEYBYTES_MAX: 901 | raise ValueError("%d <= len(key) <= %d - %d received" % (crypto_generichash_blake2b_BYTES_MIN, crypto_generichash_blake2b_KEYBYTES_MAX, keylen)) 902 | 903 | salt = pad_buf(salt, crypto_generichash_blake2b_SALTBYTES, 'salt') 904 | personal = pad_buf(personal, crypto_generichash_blake2b_PERSONALBYTES, 'personal') 905 | 906 | buf = ctypes.create_string_buffer(outlen) 907 | outlen = ctypes.c_size_t(outlen) 908 | inlen = ctypes.c_ulonglong(len(message)) 909 | keylen = ctypes.c_size_t(keylen) 910 | 911 | __check(sodium.crypto_generichash_blake2b_salt_personal(buf, outlen, message, inlen, key, keylen, salt, personal)) 912 | return buf.raw 913 | 914 | 915 | def randombytes(size): 916 | buf = ctypes.create_string_buffer(size) 917 | sodium.randombytes(buf, ctypes.c_ulonglong(size)) 918 | return buf.raw 919 | 920 | 921 | def crypto_box_keypair(): 922 | pk = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES) 923 | sk = ctypes.create_string_buffer(crypto_box_SECRETKEYBYTES) 924 | __check(sodium.crypto_box_keypair(pk, sk)) 925 | return pk.raw, sk.raw 926 | 927 | # int crypto_box_seed_keypair(unsigned char *pk, unsigned char *sk, 928 | # const unsigned char *seed); 929 | def crypto_box_seed_keypair(seed): 930 | if seed is None: 931 | raise ValueError("invalid parameters") 932 | if len(seed) != crypto_box_SEEDBYTES: raise ValueError("invalid seed size") 933 | 934 | pk = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES) 935 | sk = ctypes.create_string_buffer(crypto_box_SECRETKEYBYTES) 936 | __check(sodium.crypto_box_seed_keypair(pk, sk, seed)) 937 | return pk.raw, sk.raw 938 | 939 | def crypto_box_beforenm(pk, sk): 940 | if pk is None or sk is None: 941 | raise ValueError("invalid parameters") 942 | if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size") 943 | if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size") 944 | c = ctypes.create_string_buffer(crypto_secretbox_KEYBYTES) 945 | __check(sodium.crypto_box_beforenm(c, pk, sk)) 946 | return c.raw 947 | 948 | def crypto_box(msg, nonce, pk, sk): 949 | if None in (msg, nonce, pk, sk): 950 | raise ValueError("invalid parameters") 951 | if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size") 952 | if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size") 953 | if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size") 954 | c = ctypes.create_string_buffer(crypto_box_MACBYTES + len(msg)) 955 | __check(sodium.crypto_box_easy(c, msg, ctypes.c_ulonglong(len(msg)), nonce, pk, sk)) 956 | return c.raw 957 | 958 | def crypto_box_afternm(msg, nonce, k): 959 | if None in (msg, nonce, k): 960 | raise ValueError("invalid parameters") 961 | if len(k) != crypto_box_BEFORENMBYTES: raise ValueError("k incorrect size") 962 | if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size") 963 | c = ctypes.create_string_buffer(crypto_box_MACBYTES + len(msg)) 964 | __check(sodium.crypto_box_easy_afternm(c, msg, ctypes.c_ulonglong(len(msg)), nonce, k)) 965 | return c.raw 966 | 967 | def crypto_box_open(c, nonce, pk, sk): 968 | if None in (c, nonce, pk, sk): 969 | raise ValueError("invalid parameters") 970 | if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size") 971 | if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size") 972 | if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size") 973 | msg = ctypes.create_string_buffer(len(c) - crypto_box_MACBYTES) 974 | __check(sodium.crypto_box_open_easy(msg, c, ctypes.c_ulonglong(len(c)), nonce, pk, sk)) 975 | return msg.raw 976 | 977 | def crypto_box_open_afternm(c, nonce, k): 978 | if None in (c, nonce, k): 979 | raise ValueError("invalid parameters") 980 | if len(k) != crypto_box_BEFORENMBYTES: raise ValueError("k incorrect size") 981 | if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size") 982 | msg = ctypes.create_string_buffer(len(c) - crypto_box_MACBYTES) 983 | __check(sodium.crypto_box_open_easy_afternm(msg, c, ctypes.c_ulonglong(len(c)), nonce, k)) 984 | return msg.raw 985 | 986 | def crypto_secretbox(msg, nonce, k): 987 | if None in (msg, nonce, k): 988 | raise ValueError("invalid parameters") 989 | if len(k) != crypto_secretbox_KEYBYTES: raise ValueError("k incorrect size") 990 | if len(nonce) != crypto_secretbox_NONCEBYTES: raise ValueError("nonce incorrect size") 991 | padded = b"\x00" * crypto_secretbox_ZEROBYTES + msg 992 | c = ctypes.create_string_buffer(len(padded)) 993 | __check(sodium.crypto_secretbox(c, padded, ctypes.c_ulonglong(len(padded)), nonce, k)) 994 | return c.raw[crypto_secretbox_BOXZEROBYTES:] 995 | 996 | 997 | def crypto_secretbox_open(c, nonce, k): 998 | if None in (c, nonce, k): 999 | raise ValueError("invalid parameters") 1000 | if len(k) != crypto_secretbox_KEYBYTES: raise ValueError("k incorrect size") 1001 | if len(nonce) != crypto_secretbox_NONCEBYTES: raise ValueError("nonce incorrect size") 1002 | padded = b"\x00" * crypto_secretbox_BOXZEROBYTES + c 1003 | msg = ctypes.create_string_buffer(len(padded)) 1004 | __check(sodium.crypto_secretbox_open(msg, padded, ctypes.c_ulonglong(len(padded)), nonce, k)) 1005 | return msg.raw[crypto_secretbox_ZEROBYTES:] 1006 | 1007 | # int crypto_box_seal(unsigned char *c, const unsigned char *m, 1008 | # unsigned long long mlen, const unsigned char *pk); 1009 | 1010 | @sodium_version(1, 0, 3) 1011 | def crypto_box_seal(msg, k): 1012 | if msg is None or k is None: 1013 | raise ValueError("invalid parameters") 1014 | if len(k) != crypto_box_PUBLICKEYBYTES: raise ValueError("k incorrect size") 1015 | c = ctypes.create_string_buffer(len(msg)+crypto_box_SEALBYTES) 1016 | __check(sodium.crypto_box_seal(c, msg, ctypes.c_ulonglong(len(msg)), k)) 1017 | return c.raw 1018 | 1019 | # int crypto_box_seal_open(unsigned char *m, const unsigned char *c, 1020 | # unsigned long long clen, 1021 | # const unsigned char *pk, const unsigned char *sk); 1022 | 1023 | @sodium_version(1, 0, 3) 1024 | def crypto_box_seal_open(c, pk, sk): 1025 | if None in (c, pk, sk): 1026 | raise ValueError("invalid parameters") 1027 | if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size") 1028 | if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size") 1029 | msg = ctypes.create_string_buffer(len(c)-crypto_box_SEALBYTES) 1030 | __check(sodium.crypto_box_seal_open(msg, c, ctypes.c_ulonglong(len(c)), pk, sk)) 1031 | return msg.raw 1032 | 1033 | # int crypto_secretbox_detached(unsigned char *c, unsigned char *mac, 1034 | # const unsigned char *m, 1035 | # unsigned long long mlen, 1036 | # const unsigned char *n, 1037 | # const unsigned char *k); 1038 | 1039 | def crypto_secretbox_detached(msg, nonce, k): 1040 | if None in (msg, nonce, k): raise ValueError("invalid parameters") 1041 | if len(k) != crypto_secretbox_KEYBYTES: raise ValueError("key incorrect size") 1042 | if len(nonce) != crypto_secretbox_NONCEBYTES: raise ValueError("nonce incorrect size") 1043 | c = ctypes.create_string_buffer(len(msg)) 1044 | mac = ctypes.create_string_buffer(crypto_secretbox_MACBYTES) 1045 | __check(sodium.crypto_secretbox_detached(c, mac, msg, ctypes.c_ulonglong(len(msg)), nonce, k)) 1046 | return c.raw, mac.raw 1047 | 1048 | 1049 | # int crypto_secretbox_open_detached(unsigned char *m, 1050 | # const unsigned char *c, 1051 | # const unsigned char *mac, 1052 | # unsigned long long clen, 1053 | # const unsigned char *n, 1054 | # const unsigned char *k); 1055 | 1056 | def crypto_secretbox_open_detached(c, mac, nonce, k): 1057 | if None in (c, mac, nonce, k): 1058 | raise ValueError("invalid parameters") 1059 | if len(k) != crypto_secretbox_KEYBYTES: raise ValueError("key incorrect size") 1060 | if len(nonce) != crypto_secretbox_NONCEBYTES: raise ValueError("nonce incorrect size") 1061 | msg = ctypes.create_string_buffer(len(c)) 1062 | __check(sodium.crypto_secretbox_open_detached(msg, c, mac, ctypes.c_ulonglong(len(c)), nonce, k)) 1063 | return msg.raw 1064 | 1065 | 1066 | # int crypto_box_detached(unsigned char *c, unsigned char *mac, 1067 | # const unsigned char *m, unsigned long long mlen, 1068 | # const unsigned char *n, const unsigned char *pk, 1069 | # const unsigned char *sk); 1070 | 1071 | def crypto_box_detached(msg, nonce, pk, sk): 1072 | if None in (msg, nonce, pk, sk): raise ValueError("invalid parameters") 1073 | if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size") 1074 | if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size") 1075 | if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size") 1076 | c = ctypes.create_string_buffer(len(msg)) 1077 | mac = ctypes.create_string_buffer(crypto_box_MACBYTES) 1078 | __check(sodium.crypto_box_detached(c, mac, msg, ctypes.c_ulonglong(len(msg)), nonce, pk, sk)) 1079 | return c.raw, mac.raw 1080 | 1081 | # int crypto_box_open_detached(unsigned char *m, const unsigned char *c, 1082 | # const unsigned char *mac, 1083 | # unsigned long long clen, 1084 | # const unsigned char *n, 1085 | # const unsigned char *pk, 1086 | # const unsigned char *sk); 1087 | 1088 | def crypto_box_open_detached(c, mac, nonce, pk, sk): 1089 | if None in (c, mac, nonce, pk, sk): 1090 | raise ValueError("invalid parameters") 1091 | if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size") 1092 | if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size") 1093 | if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size") 1094 | msg = ctypes.create_string_buffer(len(c)) 1095 | __check(sodium.crypto_box_open_detached(msg, c, mac, ctypes.c_ulonglong(len(c)), nonce, pk, sk)) 1096 | return msg.raw 1097 | 1098 | 1099 | # void crypto_secretstream_xchacha20poly1305_keygen (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) 1100 | @sodium_version(1, 0, 15) 1101 | def crypto_secretstream_xchacha20poly1305_keygen(): 1102 | key = ctypes.create_string_buffer(crypto_secretstream_xchacha20poly1305_KEYBYTES) 1103 | sodium.crypto_secretstream_xchacha20poly1305_keygen(ctypes.byref(key)) 1104 | return key.raw 1105 | 1106 | 1107 | # int crypto_secretstream_xchacha20poly1305_init_push(crypto_secretstream_xchacha20poly1305_state *state, 1108 | # unsigned char out[crypto_secretstream_xchacha20poly1305_HEADERBYTES], 1109 | # const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) 1110 | @sodium_version(1, 0, 15) 1111 | def crypto_secretstream_xchacha20poly1305_init_push(key): 1112 | if key == None: 1113 | raise ValueError("invalid parameters") 1114 | if not (len(key) == crypto_secretstream_xchacha20poly1305_KEYBYTES): raise ValueError("Truncated key") 1115 | 1116 | state = ctypes.create_string_buffer(crypto_secretstream_xchacha20poly1305_STATEBYTES) 1117 | header = ctypes.create_string_buffer(crypto_secretstream_xchacha20poly1305_HEADERBYTES) 1118 | __check(sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, key)) 1119 | return state.raw, header.raw 1120 | 1121 | # int crypto_secretstream_xchacha20poly1305_init_pull(crypto_secretstream_xchacha20poly1305_state *state, 1122 | # const unsigned char in[crypto_secretstream_xchacha20poly1305_HEADERBYTES], 1123 | # const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) 1124 | @sodium_version(1, 0, 15) 1125 | def crypto_secretstream_xchacha20poly1305_init_pull(header, key): 1126 | if None in (header, key): 1127 | raise ValueError("invalid parameters") 1128 | if not (len(header) == crypto_secretstream_xchacha20poly1305_HEADERBYTES): raise ValueError("Truncated header") 1129 | if not (len(key) == crypto_secretstream_xchacha20poly1305_KEYBYTES): raise ValueError("Truncated key") 1130 | 1131 | state = ctypes.create_string_buffer(crypto_secretstream_xchacha20poly1305_STATEBYTES) 1132 | __check(sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, key)) 1133 | return state.raw 1134 | 1135 | #void crypto_secretstream_xchacha20poly1305_rekey (crypto_secretstream_xchacha20poly1305_state *state) 1136 | @sodium_version(1, 0, 15) 1137 | def crypto_secretstream_xchacha20poly1305_rekey(state): 1138 | if state == None: 1139 | raise ValueError("invalid parameters") 1140 | if not (len(state) == crypto_secretstream_xchacha20poly1305_STATEBYTES): raise ValueError("Truncated state") 1141 | 1142 | sodium.crypto_secretstream_xchacha20poly1305_rekey(state) 1143 | 1144 | #int crypto_secretstream_xchacha20poly1305_push (crypto_secretstream_xchacha20poly1305_state *state, 1145 | # unsigned char *out, 1146 | # unsigned long long *outlen_p, 1147 | # const unsigned char *m, 1148 | # unsigned long long mlen, 1149 | # const unsigned char *ad, 1150 | # unsigned long long adlen, 1151 | # unsigned char tag) 1152 | 1153 | @sodium_version(1, 0, 15) 1154 | def crypto_secretstream_xchacha20poly1305_push(state, message, ad, tag): 1155 | if None in (state, message): 1156 | raise ValueError("invalid parameters") 1157 | if not (len(state) == crypto_secretstream_xchacha20poly1305_STATEBYTES): raise ValueError("Truncated state") 1158 | 1159 | mlen = ctypes.c_ulonglong(len(message)) 1160 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 1161 | c = ctypes.create_string_buffer(mlen.value + crypto_secretstream_xchacha20poly1305_ABYTES) 1162 | clen = ctypes.c_ulonglong(0) 1163 | 1164 | __check(sodium.crypto_secretstream_xchacha20poly1305_push( 1165 | state, # crypto_secretstream_xchacha20poly1305_state *state, 1166 | c, # unsigned char *out 1167 | ctypes.byref(clen), # unsigned long long *outlen_p, 1168 | message, # const unsigned char *m, 1169 | mlen, # unsigned long long mlen, 1170 | ad, # const unsigned char *ad, 1171 | adlen, # unsigned long long adlen, 1172 | tag)) # unsigned char tag) 1173 | return c.raw 1174 | 1175 | 1176 | #crypto_secretstream_xchacha20poly1305_pull (crypto_secretstream_xchacha20poly1305_state *state, 1177 | # unsigned char *m, 1178 | # unsigned long long *mlen_p, 1179 | # unsigned char *tag_p, 1180 | # const unsigned char *in, 1181 | # unsigned long long inlen, 1182 | # const unsigned char *ad, 1183 | # unsigned long long adlen) 1184 | @sodium_version(1, 0, 15) 1185 | def crypto_secretstream_xchacha20poly1305_pull(state, ciphertext, ad): 1186 | if None in (state, ciphertext): 1187 | raise ValueError("invalid parameters") 1188 | if not (len(state) == crypto_secretstream_xchacha20poly1305_STATEBYTES): raise ValueError("Truncated state") 1189 | if len(ciphertext) < crypto_secretstream_xchacha20poly1305_ABYTES: 1190 | raise ValueError("truncated cyphertext") 1191 | 1192 | m = ctypes.create_string_buffer(len(ciphertext) - crypto_secretstream_xchacha20poly1305_ABYTES) 1193 | mlen = ctypes.c_ulonglong(0) 1194 | tag = ctypes.c_ubyte(0) 1195 | clen = ctypes.c_ulonglong(len(ciphertext)) 1196 | adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0) 1197 | 1198 | __check(sodium.crypto_secretstream_xchacha20poly1305_pull( 1199 | state, 1200 | m, # char *m, 1201 | ctypes.byref(mlen), # long long *mlen_p, 1202 | ctypes.byref(tag), # char *tag_p, 1203 | ciphertext, # unsigned char *in, 1204 | clen, # long long inlen, 1205 | ad, # unsigned char *ad, 1206 | adlen # long long adlen) 1207 | )) 1208 | return m.raw, tag.value 1209 | 1210 | def crypto_sign_keypair(): 1211 | pk = ctypes.create_string_buffer(crypto_sign_PUBLICKEYBYTES) 1212 | sk = ctypes.create_string_buffer(crypto_sign_SECRETKEYBYTES) 1213 | __check(sodium.crypto_sign_keypair(pk, sk)) 1214 | return pk.raw, sk.raw 1215 | 1216 | 1217 | def crypto_sign_seed_keypair(seed): 1218 | if len(seed) != crypto_sign_SEEDBYTES: raise ValueError("invalid seed size") 1219 | pk = ctypes.create_string_buffer(crypto_sign_PUBLICKEYBYTES) 1220 | sk = ctypes.create_string_buffer(crypto_sign_SECRETKEYBYTES) 1221 | __check(sodium.crypto_sign_seed_keypair(pk, sk, seed)) 1222 | return pk.raw, sk.raw 1223 | 1224 | def crypto_sign(m, sk): 1225 | if m is None or sk is None: 1226 | raise ValueError("invalid parameters") 1227 | if not (len(sk) == crypto_sign_SECRETKEYBYTES): raise ValueError('Truncated secret key') 1228 | 1229 | smsg = ctypes.create_string_buffer(len(m) + crypto_sign_BYTES) 1230 | smsglen = ctypes.c_ulonglong() 1231 | __check(sodium.crypto_sign(smsg, ctypes.byref(smsglen), m, ctypes.c_ulonglong(len(m)), sk)) 1232 | return smsg.raw 1233 | 1234 | 1235 | def crypto_sign_detached(m, sk): 1236 | if m is None or sk is None: 1237 | raise ValueError("invalid parameters") 1238 | if not (len(sk) == crypto_sign_SECRETKEYBYTES): raise ValueError('Truncated secret key') 1239 | sig = ctypes.create_string_buffer(crypto_sign_BYTES) 1240 | # second parm is for output of signature len (optional, ignored if NULL) 1241 | __check(sodium.crypto_sign_detached(sig, ctypes.c_void_p(0), m, ctypes.c_ulonglong(len(m)), sk)) 1242 | return sig.raw 1243 | 1244 | 1245 | def crypto_sign_open(sm, pk): 1246 | if sm is None or pk is None: 1247 | raise ValueError("invalid parameters") 1248 | if not (len(pk) == crypto_sign_PUBLICKEYBYTES): raise ValueError('Truncated public key') 1249 | msg = ctypes.create_string_buffer(len(sm)) 1250 | msglen = ctypes.c_ulonglong() 1251 | __check(sodium.crypto_sign_open(msg, ctypes.byref(msglen), sm, ctypes.c_ulonglong(len(sm)), pk)) 1252 | return msg.raw[:msglen.value] 1253 | 1254 | 1255 | def crypto_sign_verify_detached(sig, msg, pk): 1256 | if None in (sig, msg, pk): 1257 | raise ValueError 1258 | if len(sig) != crypto_sign_BYTES: 1259 | raise ValueError("invalid sign") 1260 | if not (len(pk) == crypto_sign_PUBLICKEYBYTES): raise ValueError('Truncated public key') 1261 | __check(sodium.crypto_sign_verify_detached(sig, msg, ctypes.c_ulonglong(len(msg)), pk)) 1262 | 1263 | 1264 | # crypto_sign_init(crypto_sign_state *state); 1265 | @sodium_version(1, 0, 12) 1266 | def crypto_sign_init(): 1267 | state = CryptoSignState() 1268 | __check(sodium.crypto_sign_init(ctypes.byref(state))) 1269 | return state 1270 | 1271 | 1272 | # crypto_sign_update(crypto_sign_state *state, const unsigned char *m, unsigned long long mlen); 1273 | @sodium_version(1, 0, 12) 1274 | def crypto_sign_update(state, m): 1275 | if(not isinstance(state, CryptoSignState)): 1276 | raise TypeError("state is not CryptoSignState") 1277 | if m is None: 1278 | raise ValueError("invalid parameters") 1279 | __check(sodium.crypto_sign_update(ctypes.byref(state), m, ctypes.c_ulonglong(len(m)))) 1280 | 1281 | 1282 | # crypto_sign_final_create(crypto_sign_state *state, unsigned char *sig, unsigned long long *siglen_p, const unsigned char *sk); 1283 | @sodium_version(1, 0, 12) 1284 | def crypto_sign_final_create(state, sk): 1285 | if(not isinstance(state, CryptoSignState)): 1286 | raise TypeError("state is not CryptoSignState") 1287 | if sk is None: 1288 | raise ValueError("invalid parameters") 1289 | if len(sk) != crypto_sign_SECRETKEYBYTES: 1290 | raise ValueError("invalid secret key") 1291 | buf = ctypes.create_string_buffer(crypto_sign_BYTES) 1292 | __check(sodium.crypto_sign_final_create(ctypes.byref(state), buf, ctypes.c_void_p(0), sk)) 1293 | return buf.raw 1294 | 1295 | 1296 | # crypto_sign_final_verify(crypto_sign_state *state, unsigned char *sig, const unsigned char *sk); 1297 | @sodium_version(1, 0, 12) 1298 | def crypto_sign_final_verify(state, sig, pk): 1299 | if(not isinstance(state, CryptoSignState)): 1300 | raise TypeError("state is not CryptoSignState") 1301 | if None in (sig, pk): 1302 | raise ValueError("invalid parameters") 1303 | if len(sig) != crypto_sign_BYTES: 1304 | raise ValueError("invalid signature") 1305 | if len(pk) != crypto_sign_PUBLICKEYBYTES: 1306 | raise ValueError("invalid public key") 1307 | __check(sodium.crypto_sign_final_verify(ctypes.byref(state), sig, pk)) 1308 | 1309 | 1310 | # int crypto_stream_salsa20(unsigned char *c, unsigned long long clen, 1311 | # const unsigned char *n, const unsigned char *k); 1312 | def crypto_stream(cnt, nonce=None, key=None): 1313 | res = ctypes.create_string_buffer(cnt) 1314 | if not nonce: 1315 | nonce = randombytes(crypto_stream_NONCEBYTES) 1316 | if not key: 1317 | key = randombytes(crypto_stream_KEYBYTES) 1318 | __check(sodium.crypto_stream(res, ctypes.c_ulonglong(cnt), nonce, key)) 1319 | return res.raw 1320 | 1321 | 1322 | # crypto_stream_salsa20_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, 1323 | # const unsigned char *n, const unsigned char *k) 1324 | def crypto_stream_xor(msg, cnt, nonce, key): 1325 | res = ctypes.create_string_buffer(cnt) 1326 | if len(nonce) != crypto_stream_NONCEBYTES: raise ValueError("invalid nonce") 1327 | if len(key) != crypto_stream_KEYBYTES: raise ValueError("invalid key") 1328 | __check(sodium.crypto_stream_xor(res, msg, ctypes.c_ulonglong(cnt), nonce, key)) 1329 | return res.raw 1330 | 1331 | 1332 | def crypto_sign_pk_to_box_pk(pk): 1333 | if pk is None: 1334 | raise ValueError 1335 | if not (len(pk) == crypto_sign_PUBLICKEYBYTES): raise ValueError('Truncated public key') 1336 | res = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES) 1337 | __check(sodium.crypto_sign_ed25519_pk_to_curve25519(ctypes.byref(res), pk)) 1338 | return res.raw 1339 | 1340 | 1341 | def crypto_sign_sk_to_box_sk(sk): 1342 | if sk is None: 1343 | raise ValueError 1344 | if not (len(sk) == crypto_sign_SECRETKEYBYTES): raise ValueError('Truncated secret key') 1345 | res = ctypes.create_string_buffer(crypto_box_SECRETKEYBYTES) 1346 | __check(sodium.crypto_sign_ed25519_sk_to_curve25519(ctypes.byref(res), sk)) 1347 | return res.raw 1348 | 1349 | def crypto_sign_sk_to_seed(sk): 1350 | if sk is None: 1351 | raise ValueError 1352 | if not (len(sk) == crypto_sign_SECRETKEYBYTES): raise ValueError('Truncated secret key') 1353 | seed = ctypes.create_string_buffer(crypto_sign_SEEDBYTES) 1354 | __check(sodium.crypto_sign_ed25519_sk_to_seed(ctypes.byref(seed), sk)) 1355 | return seed.raw 1356 | 1357 | # int crypto_pwhash(unsigned char * const out, 1358 | # unsigned long long outlen, 1359 | # const char * const passwd, 1360 | # unsigned long long passwdlen, 1361 | # const unsigned char * const salt, 1362 | # unsigned long long opslimit, 1363 | # size_t memlimit, int alg); 1364 | @sodium_version(1, 0, 9) 1365 | @encode_strings 1366 | def crypto_pwhash(outlen, passwd, salt, opslimit, memlimit, alg=crypto_pwhash_ALG_DEFAULT): 1367 | if None in (outlen, passwd, salt, opslimit, memlimit): 1368 | raise ValueError("invalid parameters") 1369 | if len(salt) != crypto_pwhash_SALTBYTES: raise ValueError("invalid salt") 1370 | if not (crypto_pwhash_BYTES_MIN <= outlen <= crypto_pwhash_BYTES_MAX): raise ValueError("invalid hash len") 1371 | if not (crypto_pwhash_PASSWD_MIN <= len(passwd) <= crypto_pwhash_PASSWD_MAX): raise ValueError("invalid passwd len") 1372 | if not (crypto_pwhash_OPSLIMIT_MIN <= opslimit <= crypto_pwhash_OPSLIMIT_MAX): raise ValueError("invalid opslimit") 1373 | if not (crypto_pwhash_MEMLIMIT_MIN <= memlimit <= crypto_pwhash_MEMLIMIT_MAX): raise ValueError("invalid memlimit") 1374 | 1375 | out = ctypes.create_string_buffer(outlen) 1376 | __check(sodium.crypto_pwhash(ctypes.byref(out), ctypes.c_ulonglong(outlen), passwd, ctypes.c_ulonglong(len(passwd)), salt, ctypes.c_ulonglong(opslimit), ctypes.c_size_t(memlimit), ctypes.c_int(alg))) 1377 | return out.raw 1378 | 1379 | # int crypto_pwhash_str(char out[crypto_pwhash_STRBYTES], 1380 | # const char * const passwd, 1381 | # unsigned long long passwdlen, 1382 | # unsigned long long opslimit, 1383 | # size_t memlimit); 1384 | @sodium_version(1, 0, 9) 1385 | @encode_strings 1386 | def crypto_pwhash_str(passwd, opslimit, memlimit): 1387 | if None in (passwd, opslimit, memlimit): 1388 | raise ValueError("invalid parameters") 1389 | if not (crypto_pwhash_PASSWD_MIN <= len(passwd) <= crypto_pwhash_PASSWD_MAX): raise ValueError("invalid passwd len") 1390 | if not (crypto_pwhash_OPSLIMIT_MIN <= opslimit <= crypto_pwhash_OPSLIMIT_MAX): raise ValueError("invalid opslimit") 1391 | if not (crypto_pwhash_MEMLIMIT_MIN <= memlimit <= crypto_pwhash_MEMLIMIT_MAX): raise ValueError("invalid memlimit") 1392 | out = ctypes.create_string_buffer(crypto_pwhash_STRBYTES) 1393 | __check(sodium.crypto_pwhash_str(ctypes.byref(out), passwd, ctypes.c_ulonglong(len(passwd)), ctypes.c_ulonglong(opslimit), ctypes.c_size_t(memlimit))) 1394 | return out.raw 1395 | 1396 | # int crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES], 1397 | # const char * const passwd, 1398 | # unsigned long long passwdlen); 1399 | @sodium_version(1, 0, 9) 1400 | @encode_strings 1401 | def crypto_pwhash_str_verify(pstr, passwd): 1402 | if None in (pstr, passwd) or len(pstr) != crypto_pwhash_STRBYTES: 1403 | raise ValueError("invalid parameters") 1404 | if not (crypto_pwhash_PASSWD_MIN < len(passwd) <= crypto_pwhash_PASSWD_MAX): raise ValueError("invalid passwd len") 1405 | return sodium.crypto_pwhash_str_verify(pstr, passwd, ctypes.c_ulonglong(len(passwd))) == 0 1406 | 1407 | # int crypto_pwhash_scryptsalsa208sha256(unsigned char * const out, 1408 | # unsigned long long outlen, 1409 | # const char * const passwd, 1410 | # unsigned long long passwdlen, 1411 | # const unsigned char * const salt, 1412 | # unsigned long long opslimit, 1413 | # size_t memlimit); 1414 | def crypto_pwhash_scryptsalsa208sha256(outlen, passwd, salt, opslimit, memlimit): 1415 | if None in (outlen, passwd, salt, opslimit, memlimit): 1416 | raise ValueError 1417 | 1418 | if len(salt) != crypto_pwhash_scryptsalsa208sha256_SALTBYTES: raise ValueError("invalid salt") 1419 | if not (crypto_pwhash_scryptsalsa208sha256_BYTES_MIN <= outlen <= crypto_pwhash_scryptsalsa208sha256_BYTES_MAX): raise ValueError("invalid hash len") 1420 | if not (crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN <= len(passwd) <= crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX): raise ValueError("invalid passwd len") 1421 | if not (crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN <= opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX): raise ValueError("invalid opslimit") 1422 | if not (crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN <= memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX): raise ValueError("invalid memlimit") 1423 | 1424 | out = ctypes.create_string_buffer(outlen) 1425 | __check(sodium.crypto_pwhash_scryptsalsa208sha256(out, ctypes.c_ulonglong(outlen), passwd, ctypes.c_ulonglong(len(passwd)), salt, ctypes.c_ulonglong(opslimit), ctypes.c_size_t(memlimit))) 1426 | return out.raw 1427 | 1428 | # int crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES], 1429 | # const char * const passwd, 1430 | # unsigned long long passwdlen, 1431 | # unsigned long long opslimit, 1432 | # size_t memlimit); 1433 | def crypto_pwhash_scryptsalsa208sha256_str(passwd, opslimit, memlimit): 1434 | if None in (passwd, opslimit, memlimit): 1435 | raise ValueError 1436 | if not (crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN <= len(passwd) <= crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX): raise ValueError("invalid passwd len") 1437 | if not (crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN <= opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX): raise ValueError("invalid opslimit") 1438 | if not (crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN <= memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX): raise ValueError("invalid memlimit") 1439 | out = ctypes.create_string_buffer(crypto_pwhash_scryptsalsa208sha256_STRBYTES) 1440 | __check(sodium.crypto_pwhash_scryptsalsa208sha256_str(out, passwd, ctypes.c_ulonglong(len(passwd)), ctypes.c_ulonglong(opslimit), ctypes.c_size_t(memlimit))) 1441 | return out.raw 1442 | 1443 | #int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], 1444 | # const char * const passwd, 1445 | # unsigned long long passwdlen); 1446 | def crypto_pwhash_scryptsalsa208sha256_str_verify(stored, passwd): 1447 | if stored is None or passwd is None: 1448 | raise ValueError 1449 | if not (crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN <= len(passwd) <= crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX): raise ValueError("invalid passwd len") 1450 | if len(stored) != crypto_pwhash_scryptsalsa208sha256_STRBYTES: raise ValueError('invalid str size') 1451 | 1452 | __check(sodium.crypto_pwhash_scryptsalsa208sha256_str_verify(stored, passwd, ctypes.c_ulonglong(len(passwd)))) 1453 | 1454 | # int crypto_sign_ed25519_sk_to_pk(unsigned char *pk, const unsigned char *sk) 1455 | def crypto_sign_sk_to_pk(sk): 1456 | if sk is None or len(sk) != crypto_sign_ed25519_SECRETKEYBYTES: 1457 | raise ValueError 1458 | res = ctypes.create_string_buffer(crypto_sign_ed25519_PUBLICKEYBYTES) 1459 | __check(sodium.crypto_sign_ed25519_sk_to_pk(ctypes.byref(res), sk)) 1460 | return res.raw 1461 | 1462 | # int crypto_hash_sha256(unsigned char *out, const unsigned char *in, 1463 | # unsigned long long inlen); 1464 | def crypto_hash_sha256(message): 1465 | if message is None: 1466 | raise ValueError("invalid parameters") 1467 | out = ctypes.create_string_buffer(crypto_hash_sha256_BYTES) 1468 | __check(sodium.crypto_hash_sha256(out, message, ctypes.c_ulonglong(len(message)))) 1469 | return out.raw 1470 | 1471 | # int crypto_hash_sha512(unsigned char *out, const unsigned char *in, 1472 | # unsigned long long inlen); 1473 | def crypto_hash_sha512(message): 1474 | if message is None: 1475 | raise ValueError("invalid parameters") 1476 | out = ctypes.create_string_buffer(crypto_hash_sha512_BYTES) 1477 | __check(sodium.crypto_hash_sha512(out, message, ctypes.c_ulonglong(len(message)))) 1478 | return out.raw 1479 | 1480 | # int crypto_hash_sha512_init(crypto_hash_sha512_state *state) 1481 | def crypto_hash_sha512_init(): 1482 | state = ctypes.create_string_buffer(crypto_hash_sha512_STATEBYTES) 1483 | __check(sodium.crypto_hash_sha512_init(state)) 1484 | return state 1485 | 1486 | # int crypto_hash_sha512_update(crypto_hash_sha512_state *state, const unsigned char *in, unsigned long long inlen) 1487 | def crypto_hash_sha512_update(state, data): 1488 | __check(sodium.crypto_hash_sha512_update(state,data,ctypes.c_ulonglong(len(data)))) 1489 | return state 1490 | 1491 | # int crypto_hash_sha512_final(crypto_hash_sha512_state *state, unsigned char *out) 1492 | def crypto_hash_sha512_final(state): 1493 | out = ctypes.create_string_buffer(crypto_hash_sha512_BYTES) 1494 | __check(sodium.crypto_hash_sha512_final(state, out)) 1495 | return out.raw 1496 | 1497 | # int crypto_kdf_derive_from_key(unsigned char *subkey, size_t subkey_len, 1498 | # uint64_t subkey_id, 1499 | # const char ctx[crypto_kdf_CONTEXTBYTES], 1500 | # const unsigned char key[crypto_kdf_KEYBYTES]) 1501 | def crypto_kdf_derive_from_key(subkey_len, subkey_id, ctx, key): 1502 | if len(ctx) != crypto_kdf_CONTEXTBYTES: raise ValueError("invalid context") 1503 | if len(key) != crypto_kdf_KEYBYTES: raise ValueError("invalid key") 1504 | if not (crypto_kdf_BYTES_MIN <= subkey_len <= crypto_kdf_BYTES_MAX): raise ValueError("invalid subkey len") 1505 | subkey = ctypes.create_string_buffer(subkey_len) 1506 | si = ctypes.c_uint64(subkey_id) 1507 | __check(sodium.crypto_kdf_derive_from_key(subkey, ctypes.c_size_t(subkey_len), si, ctx, key)) 1508 | return subkey.raw 1509 | 1510 | # void crypto_kdf_keygen(unsigned char k[crypto_kdf_KEYBYTES]) 1511 | def crypto_kdf_keygen(): 1512 | k = ctypes.create_string_buffer(crypto_kdf_KEYBYTES) 1513 | sodium.crypto_kdf_keygen(k) 1514 | return k.raw 1515 | 1516 | # int crypto_kdf_hkdf_sha256_extract_init(crypto_kdf_hkdf_sha256_state *state, 1517 | # const unsigned char *salt, size_t salt_len) 1518 | @sodium_version(1, 0, 19) 1519 | def crypto_kdf_hkdf_sha256_extract_init(salt=b''): 1520 | state = ctypes.create_string_buffer(crypto_kdf_hkdf_sha256_STATEBYTES) 1521 | __check(sodium.crypto_kdf_hkdf_sha256_extract_init(state, salt, ctypes.c_size_t(len(salt)))) 1522 | return state 1523 | 1524 | # int crypto_kdf_hkdf_sha256_extract_update(crypto_kdf_hkdf_sha256_state *state, 1525 | # const unsigned char *ikm, size_t ikm_len) 1526 | @sodium_version(1, 0, 19) 1527 | def crypto_kdf_hkdf_sha256_extract_update(state, ikm=b''): 1528 | if len(state) != crypto_kdf_hkdf_sha256_STATEBYTES: raise ValueError("invalid state") 1529 | __check(sodium.crypto_kdf_hkdf_sha256_extract_update(state, ikm, ctypes.c_size_t(len(ikm)))) 1530 | return state 1531 | 1532 | # int crypto_kdf_hkdf_sha256_extract_final(crypto_kdf_hkdf_sha256_state *state, 1533 | # unsigned char prk[crypto_kdf_hkdf_sha256_KEYBYTES]) 1534 | @sodium_version(1, 0, 19) 1535 | def crypto_kdf_hkdf_sha256_extract_final(state): 1536 | if len(state) != crypto_kdf_hkdf_sha256_STATEBYTES: raise ValueError("invalid state") 1537 | prk = ctypes.create_string_buffer(crypto_kdf_hkdf_sha256_KEYBYTES) 1538 | __check(sodium.crypto_kdf_hkdf_sha256_extract_final(state, prk)) 1539 | return prk.raw 1540 | 1541 | # int crypto_kdf_hkdf_sha256_extract( 1542 | # unsigned char prk[crypto_kdf_hkdf_sha256_KEYBYTES], 1543 | # const unsigned char *salt, size_t salt_len, const unsigned char *ikm, 1544 | # size_t ikm_len) 1545 | @sodium_version(1, 0, 19) 1546 | def crypto_kdf_hkdf_sha256_extract(salt=b'', ikm=b''): 1547 | prk = ctypes.create_string_buffer(crypto_kdf_hkdf_sha256_KEYBYTES) 1548 | __check(sodium.crypto_kdf_hkdf_sha256_extract(prk, salt, ctypes.c_size_t(len(salt)), ikm, ctypes.c_size_t(len(ikm)))) 1549 | return prk.raw 1550 | 1551 | # void crypto_kdf_hkdf_sha256_keygen(unsigned char prk[crypto_kdf_hkdf_sha256_KEYBYTES]) 1552 | @sodium_version(1, 0, 19) 1553 | def crypto_kdf_hkdf_sha256_keygen(): 1554 | k = ctypes.create_string_buffer(crypto_kdf_hkdf_sha256_KEYBYTES) 1555 | sodium.crypto_kdf_hkdf_sha256_keygen(k) 1556 | return k.raw 1557 | 1558 | # int crypto_kdf_hkdf_sha256_expand(unsigned char *out, size_t out_len, 1559 | # const char *ctx, size_t ctx_len, 1560 | # const unsigned char prk[crypto_kdf_hkdf_sha256_KEYBYTES]) 1561 | @sodium_version(1, 0, 19) 1562 | def crypto_kdf_hkdf_sha256_expand(outlen, prk, ctx=b''): 1563 | if not (crypto_kdf_hkdf_sha256_BYTES_MIN <= outlen <= crypto_kdf_hkdf_sha256_BYTES_MAX): raise ValueError("invalid output len") 1564 | if len(prk) != crypto_kdf_hkdf_sha256_KEYBYTES: raise ValueError("invalid prk") 1565 | out = ctypes.create_string_buffer(outlen) 1566 | __check(sodium.crypto_kdf_hkdf_sha256_expand(out, ctypes.c_size_t(outlen), ctx, ctypes.c_size_t(len(ctx)), prk)) 1567 | return out.raw 1568 | 1569 | # int crypto_kdf_hkdf_sha512_extract_init(crypto_kdf_hkdf_sha512_state *state, 1570 | # const unsigned char *salt, size_t salt_len) 1571 | @sodium_version(1, 0, 20) 1572 | def crypto_kdf_hkdf_sha512_extract_init(salt=b''): 1573 | state = ctypes.create_string_buffer(crypto_kdf_hkdf_sha512_STATEBYTES) 1574 | __check(sodium.crypto_kdf_hkdf_sha512_extract_init(state, salt, ctypes.c_size_t(len(salt)))) 1575 | return state 1576 | 1577 | # int crypto_kdf_hkdf_sha512_extract_update(crypto_kdf_hkdf_sha512_state *state, 1578 | # const unsigned char *ikm, size_t ikm_len) 1579 | @sodium_version(1, 0, 20) 1580 | def crypto_kdf_hkdf_sha512_extract_update(state, ikm=b''): 1581 | if len(state) != crypto_kdf_hkdf_sha512_STATEBYTES: raise ValueError("invalid state") 1582 | __check(sodium.crypto_kdf_hkdf_sha512_extract_update(state, ikm, ctypes.c_size_t(len(ikm)))) 1583 | return state 1584 | 1585 | # int crypto_kdf_hkdf_sha512_extract_final(crypto_kdf_hkdf_sha512_state *state, 1586 | # unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES]) 1587 | @sodium_version(1, 0, 20) 1588 | def crypto_kdf_hkdf_sha512_extract_final(state): 1589 | if len(state) != crypto_kdf_hkdf_sha512_STATEBYTES: raise ValueError("invalid state") 1590 | prk = ctypes.create_string_buffer(crypto_kdf_hkdf_sha512_KEYBYTES) 1591 | __check(sodium.crypto_kdf_hkdf_sha512_extract_final(state, prk)) 1592 | return prk.raw 1593 | 1594 | # int crypto_kdf_hkdf_sha512_extract( 1595 | # unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES], 1596 | # const unsigned char *salt, size_t salt_len, const unsigned char *ikm, 1597 | # size_t ikm_len) 1598 | @sodium_version(1, 0, 19) 1599 | def crypto_kdf_hkdf_sha512_extract(salt=b'', ikm=b''): 1600 | prk = ctypes.create_string_buffer(crypto_kdf_hkdf_sha512_KEYBYTES) 1601 | __check(sodium.crypto_kdf_hkdf_sha512_extract(prk, salt, ctypes.c_size_t(len(salt)), ikm, ctypes.c_size_t(len(ikm)))) 1602 | return prk.raw 1603 | 1604 | # void crypto_kdf_hkdf_sha512_keygen(unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES]) 1605 | @sodium_version(1, 0, 19) 1606 | def crypto_kdf_hkdf_sha512_keygen(): 1607 | k = ctypes.create_string_buffer(crypto_kdf_hkdf_sha512_KEYBYTES) 1608 | sodium.crypto_kdf_hkdf_sha512_keygen(k) 1609 | return k.raw 1610 | 1611 | # int crypto_kdf_hkdf_sha512_expand(unsigned char *out, size_t out_len, 1612 | # const char *ctx, size_t ctx_len, 1613 | # const unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES]) 1614 | @sodium_version(1, 0, 19) 1615 | def crypto_kdf_hkdf_sha512_expand(outlen, prk, ctx=b''): 1616 | if not (crypto_kdf_hkdf_sha512_BYTES_MIN <= outlen <= crypto_kdf_hkdf_sha512_BYTES_MAX): raise ValueError("invalid output len") 1617 | if len(prk) != crypto_kdf_hkdf_sha512_KEYBYTES: raise ValueError("invalid prk") 1618 | out = ctypes.create_string_buffer(outlen) 1619 | __check(sodium.crypto_kdf_hkdf_sha512_expand(out, ctypes.c_size_t(outlen), ctx, ctypes.c_size_t(len(ctx)), prk)) 1620 | return out.raw 1621 | 1622 | # int crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], 1623 | # unsigned char sk[crypto_kx_SECRETKEYBYTES]); 1624 | @sodium_version(1, 0, 12) 1625 | def crypto_kx_keypair(): 1626 | pk = ctypes.create_string_buffer(crypto_kx_PUBLICKEYBYTES) 1627 | sk = ctypes.create_string_buffer(crypto_kx_SECRETKEYBYTES) 1628 | __check(sodium.crypto_kx_keypair(pk, sk)) 1629 | return pk.raw, sk.raw 1630 | 1631 | # int crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], 1632 | # unsigned char tx[crypto_kx_SESSIONKEYBYTES], 1633 | # const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES], 1634 | # const unsigned char client_sk[crypto_kx_SECRETKEYBYTES], 1635 | # const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES]); 1636 | @sodium_version(1, 0, 12) 1637 | def crypto_kx_client_session_keys(client_pk, client_sk, server_pk): 1638 | if None in (client_pk, client_sk, server_pk): 1639 | raise ValueError("invalid parameters") 1640 | if not (len(client_pk) == crypto_kx_PUBLICKEYBYTES): raise ValueError("Invalid client public key") 1641 | if not (len(client_sk) == crypto_kx_SECRETKEYBYTES): raise ValueError("Invalid client secret key") 1642 | if not (len(server_pk) == crypto_kx_PUBLICKEYBYTES): raise ValueError("Invalid server public key") 1643 | 1644 | rx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES) 1645 | tx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES) 1646 | __check(sodium.crypto_kx_client_session_keys(rx, tx, client_pk, client_sk, server_pk)) 1647 | return rx.raw, tx.raw 1648 | 1649 | # int crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], 1650 | # unsigned char tx[crypto_kx_SESSIONKEYBYTES], 1651 | # const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES], 1652 | # const unsigned char server_sk[crypto_kx_SECRETKEYBYTES], 1653 | # const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES]); 1654 | @sodium_version(1, 0, 12) 1655 | def crypto_kx_server_session_keys(server_pk, server_sk, client_pk): 1656 | if None in (server_pk, server_sk, client_pk): 1657 | raise ValueError("invalid parameters") 1658 | if not (len(server_pk) == crypto_kx_PUBLICKEYBYTES): raise ValueError("Invalid server public key") 1659 | if not (len(server_sk) == crypto_kx_SECRETKEYBYTES): raise ValueError("Invalid server secret key") 1660 | if not (len(client_pk) == crypto_kx_PUBLICKEYBYTES): raise ValueError("Invalid client public key") 1661 | 1662 | rx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES) 1663 | tx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES) 1664 | __check(sodium.crypto_kx_server_session_keys(rx, tx, server_pk, server_sk, client_pk)) 1665 | return rx.raw, tx.raw 1666 | 1667 | # void sodium_increment(unsigned char *n, const size_t nlen) 1668 | @sodium_version(1, 0, 4) 1669 | def sodium_increment(n): 1670 | sodium.sodium_increment(n, ctypes.c_size_t(len(n))) 1671 | 1672 | 1673 | # int crypto_core_ristretto255_is_valid_point(const unsigned char *p); 1674 | @sodium_version(1, 0, 18) 1675 | def crypto_core_ristretto255_is_valid_point(p): 1676 | return sodium.crypto_core_ristretto255_is_valid_point(p) == 1 1677 | 1678 | # int crypto_core_ristretto255_from_hash(unsigned char *p, const unsigned char *r); 1679 | @sodium_version(1, 0, 18) 1680 | def crypto_core_ristretto255_from_hash(r): 1681 | if len(r) != crypto_core_ristretto255_HASHBYTES: raise ValueError("Invalid parameter, must be {} bytes".format(crypto_core_ristretto255_HASHBYTES)) 1682 | p = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES) 1683 | __check(sodium.crypto_core_ristretto255_from_hash(p,r)) 1684 | return p.raw 1685 | 1686 | # int crypto_scalarmult_ristretto255(unsigned char *q, const unsigned char *n, const unsigned char *p); 1687 | @sodium_version(1, 0, 18) 1688 | def crypto_scalarmult_ristretto255(n, p): 1689 | if None in (n,p): 1690 | raise ValueError("invalid parameters") 1691 | if len(n) != crypto_core_ristretto255_SCALARBYTES: raise ValueError("truncated scalar") 1692 | if len(p) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point") 1693 | buf = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES) 1694 | __check(sodium.crypto_scalarmult_ristretto255(buf, n, p)) 1695 | return buf.raw 1696 | 1697 | # int crypto_scalarmult_ristretto255_base(unsigned char *q, const unsigned char *n); 1698 | @sodium_version(1, 0, 18) 1699 | def crypto_scalarmult_ristretto255_base(n): 1700 | if n is None: 1701 | raise ValueError("invalid parameters") 1702 | if len(n) != crypto_core_ristretto255_SCALARBYTES: raise ValueError("truncated scalar") 1703 | buf = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES) 1704 | __check(sodium.crypto_scalarmult_ristretto255_base(buf, n)) 1705 | return buf.raw 1706 | 1707 | # void crypto_core_ristretto255_scalar_random(unsigned char *r); 1708 | @sodium_version(1, 0, 18) 1709 | def crypto_core_ristretto255_scalar_random(): 1710 | r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES) 1711 | sodium.crypto_core_ristretto255_scalar_random(r) 1712 | return r.raw 1713 | 1714 | # int crypto_core_ristretto255_scalar_invert(unsigned char *recip, const unsigned char *s); 1715 | @sodium_version(1, 0, 18) 1716 | def crypto_core_ristretto255_scalar_invert(s): 1717 | if not s or len(s)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES)) 1718 | r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES) 1719 | __check(sodium.crypto_core_ristretto255_scalar_invert(r,s)) 1720 | return r.raw 1721 | 1722 | # void crypto_core_ristretto255_scalar_reduce(unsigned char *r, const unsigned char *s); 1723 | @sodium_version(1, 0, 18) 1724 | def crypto_core_ristretto255_scalar_reduce(s): 1725 | if not s or len(s)!=crypto_core_ristretto255_NONREDUCEDSCALARBYTES: raise ValueError("Invalid parameter: must be {} bytes".format(crypto_core_ristretto255_NONREDUCEDSCALARBYTES)) 1726 | r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES) 1727 | sodium.crypto_core_ristretto255_scalar_reduce(r,s) 1728 | return r.raw 1729 | 1730 | # int crypto_core_ristretto255_add(unsigned char *r, const unsigned char *p, const unsigned char *q) 1731 | @sodium_version(1, 0, 18) 1732 | def crypto_core_ristretto255_add(p, q): 1733 | if len(p) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point p") 1734 | if len(q) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point q") 1735 | r = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES) 1736 | __check(sodium.crypto_core_ristretto255_add(r, p, q)) 1737 | return r.raw 1738 | 1739 | # int crypto_core_ristretto255_sub(unsigned char *r, const unsigned char *p, const unsigned char *q) 1740 | @sodium_version(1, 0, 18) 1741 | def crypto_core_ristretto255_sub(p,q): 1742 | if len(p) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point p") 1743 | if len(q) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point q") 1744 | r = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES) 1745 | __check(sodium.crypto_core_ristretto255_sub(r, p, q)) 1746 | return r.raw 1747 | 1748 | # void crypto_core_ristretto255_random(unsigned char *p) 1749 | @sodium_version(1, 0, 18) 1750 | def crypto_core_ristretto255_random(): 1751 | p = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES) 1752 | sodium.crypto_core_ristretto255_random(p) 1753 | return p.raw 1754 | 1755 | # void crypto_core_ristretto255_scalar_negate(unsigned char *neg, const unsigned char *s) 1756 | @sodium_version(1, 0, 18) 1757 | def crypto_core_ristretto255_scalar_negate(s): 1758 | if not s or len(s)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES)) 1759 | r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES) 1760 | sodium.crypto_core_ristretto255_scalar_negate(r,s) 1761 | return r.raw 1762 | 1763 | # void crypto_core_ristretto255_scalar_complement(unsigned char *comp, const unsigned char *s) 1764 | @sodium_version(1, 0, 18) 1765 | def crypto_core_ristretto255_scalar_complement(s): 1766 | if not s or len(s)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES)) 1767 | r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES) 1768 | sodium.crypto_core_ristretto255_scalar_complement(r,s) 1769 | return r.raw 1770 | 1771 | # void crypto_core_ristretto255_scalar_add(unsigned char *z, const unsigned char *x, const unsigned char *y) 1772 | @sodium_version(1, 0, 18) 1773 | def crypto_core_ristretto255_scalar_add(x,y): 1774 | if not x or len(x)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES)) 1775 | if not y or len(y)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES)) 1776 | r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES) 1777 | sodium.crypto_core_ristretto255_scalar_add(r,x,y) 1778 | return r.raw 1779 | 1780 | # void crypto_core_ristretto255_scalar_sub(unsigned char *z, const unsigned char *x, const unsigned char *y) 1781 | @sodium_version(1, 0, 18) 1782 | def crypto_core_ristretto255_scalar_sub(x,y): 1783 | if not x or len(x)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES)) 1784 | if not y or len(y)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES)) 1785 | r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES) 1786 | sodium.crypto_core_ristretto255_scalar_sub(r,x,y) 1787 | return r.raw 1788 | 1789 | # void crypto_core_ristretto255_scalar_mul(unsigned char *z, const unsigned char *x, const unsigned char *y) 1790 | @sodium_version(1, 0, 18) 1791 | def crypto_core_ristretto255_scalar_mul(x,y): 1792 | if not x or len(x)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES)) 1793 | if not y or len(y)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES)) 1794 | r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES) 1795 | sodium.crypto_core_ristretto255_scalar_mul(r,x,y) 1796 | return r.raw 1797 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from setuptools import setup, find_packages 3 | 4 | 5 | # Utility function to read the README file. 6 | # Used for the long_description. It's nice, because now 1) we have a top level 7 | # README file and 2) it's easier to type in the README file than to put a raw 8 | # string in below ... 9 | def read(fname): 10 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 11 | 12 | setup( 13 | name="pysodium", 14 | version="0.7.18", 15 | author="Stefan Marsiske", 16 | author_email="s@ctrlc.hu", 17 | description="python libsodium wrapper", 18 | license="BSD", 19 | keywords="cryptography API NaCl libsodium", 20 | url="https://github.com/stef/pysodium", 21 | packages=find_packages(exclude=['test*']), 22 | long_description=read('README.md'), 23 | requires=["libsodium"], 24 | classifiers=["Development Status :: 4 - Beta", 25 | "License :: OSI Approved :: BSD License", 26 | "Topic :: Security :: Cryptography", 27 | "Topic :: Security"], 28 | ) 29 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/test_pysodium.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | """ 3 | Wrapper for libsodium library 4 | 5 | Copyright (c) 2013-2014, Marsiske Stefan. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, 9 | are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | 14 | * Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | """ 29 | 30 | import unittest 31 | import binascii 32 | import pysodium 33 | 34 | 35 | class TestPySodium(unittest.TestCase): 36 | def test_crypto_stream(self): 37 | pysodium.crypto_stream(8) 38 | pysodium.crypto_stream(16) 39 | pysodium.crypto_stream(32) 40 | 41 | def test_crypto_stream_xor(self): 42 | nonce = b'\x00' * pysodium.crypto_stream_NONCEBYTES 43 | key = b'\x00' * pysodium.crypto_stream_KEYBYTES 44 | pysodium.crypto_stream_xor(b'howdy', len(b'howdy'), nonce, key) 45 | pysodium.crypto_stream_xor(b'howdy' * 16, len(b'howdy') * 16, nonce, key) 46 | 47 | def test_crypto_generichash(self): 48 | r=pysodium.crypto_generichash(b'howdy') 49 | pysodium.crypto_generichash(b'howdy', outlen=4) 50 | r6=pysodium.crypto_generichash(b'howdy', outlen=6) 51 | pysodium.crypto_generichash(b'howdy', outlen=8) 52 | state = pysodium.crypto_generichash_init() 53 | pysodium.crypto_generichash_update(state, b'howdy') 54 | r1=pysodium.crypto_generichash_final(state) 55 | 56 | state = pysodium.crypto_generichash_init(outlen=6) 57 | pysodium.crypto_generichash_update(state, b'howdy') 58 | r61=pysodium.crypto_generichash_final(state, outlen=6) 59 | self.assertEqual(r, r1) 60 | self.assertEqual(r6, r61) 61 | 62 | self.assertNotEqual(pysodium.crypto_generichash( 'salt0'), pysodium.crypto_generichash( 'salt1')) 63 | self.assertNotEqual(pysodium.crypto_generichash(b'salt0'), pysodium.crypto_generichash(b'salt1')) 64 | def test_crypto_auth_hmac_256_512_512256(self): 65 | """Taken from https://www.rfc-editor.org/rfc/rfc4231#section-4""" 66 | vectors = [ 67 | { 68 | "k": b"\x0b" * 20 + b"\x00" * 12, 69 | "m": b"Hi There", 70 | "256": bytes.fromhex( 71 | "b0344c61d8db38535ca8afceaf0bf12b" 72 | "881dc200c9833da726e9376c2e32cff7" 73 | ), 74 | "512": bytes.fromhex( 75 | "87aa7cdea5ef619d4ff0b4241a1d6cb0" 76 | "2379f4e2ce4ec2787ad0b30545e17cde" 77 | "daa833b7d6b8a702038b274eaea3f4e4" 78 | "be9d914eeb61f1702e696c203a126854" 79 | ), 80 | "512256": bytes.fromhex( 81 | "87aa7cdea5ef619d4ff0b4241a1d6cb0" 82 | "2379f4e2ce4ec2787ad0b30545e17cde" 83 | ), 84 | }, 85 | { 86 | "k": b"Jefe" + b"\x00" * 28, 87 | "m": b"what do ya want for nothing?", 88 | "256": bytes.fromhex( 89 | "5bdcc146bf60754e6a042426089575c7" 90 | "5a003f089d2739839dec58b964ec3843" 91 | ), 92 | "512": bytes.fromhex( 93 | "164b7a7bfcf819e2e395fbe73b56e0a3" 94 | "87bd64222e831fd610270cd7ea250554" 95 | "9758bf75c05a994a6d034f65f8f0e6fd" 96 | "caeab1a34d4a6b4b636e070a38bce737" 97 | ), 98 | "512256": bytes.fromhex( 99 | "164b7a7bfcf819e2e395fbe73b56e0a3" 100 | "87bd64222e831fd610270cd7ea250554" 101 | ), 102 | }, 103 | ] 104 | 105 | for v in vectors: 106 | self.assertEqual(pysodium.crypto_auth_hmacsha256(v["m"], v["k"]), v["256"]) 107 | self.assertEqual(pysodium.crypto_auth_hmacsha512(v["m"], v["k"]), v["512"]) 108 | self.assertEqual( 109 | pysodium.crypto_auth_hmacsha512256(v["m"], v["k"]), v["512256"] 110 | ) 111 | try: 112 | pysodium.crypto_auth_hmacsha256_verify(v["256"], v["m"], v["k"]) 113 | pysodium.crypto_auth_hmacsha512_verify(v["512"], v["m"], v["k"]) 114 | pysodium.crypto_auth_hmacsha512256_verify(v["512256"], v["m"], v["k"]) 115 | except Exception as e: 116 | self.assertTrue(False, f"verification fail: {e}") 117 | 118 | msg = b"pull request plz" 119 | try: 120 | key = pysodium.crypto_auth_hmacsha256_keygen() 121 | hmac = pysodium.crypto_auth_hmacsha256(msg, key) 122 | pysodium.crypto_auth_hmacsha256_verify(hmac, msg, key) 123 | 124 | except Exception: 125 | self.assertTrue(False) 126 | 127 | try: 128 | key = pysodium.crypto_auth_hmacsha256_keygen() 129 | hmac = pysodium.crypto_auth_hmacsha256(msg, key) 130 | pysodium.crypto_auth_hmacsha256_verify(hmac, msg, key) 131 | 132 | except Exception: 133 | self.assertTrue(False) 134 | 135 | try: 136 | key = pysodium.crypto_auth_hmacsha256_keygen() 137 | hmac = pysodium.crypto_auth_hmacsha256(msg, key) 138 | pysodium.crypto_auth_hmacsha256_verify(hmac, msg, key) 139 | 140 | except Exception: 141 | self.assertTrue(False) 142 | 143 | def test_crypto_box_pk_from_sk(self): 144 | pk1, sk = pysodium.crypto_box_keypair() 145 | pk2 = pysodium.crypto_scalarmult_curve25519_base(sk) 146 | self.assertEqual(pk1, pk2) 147 | 148 | def test_crypto_box_seal(self): 149 | if not pysodium.sodium_version_check(1, 0, 3): return 150 | pk, sk = pysodium.crypto_box_keypair() 151 | c = pysodium.crypto_box_seal(b"howdy", pk) 152 | self.assertEqual(pysodium.crypto_box_seal_open(c, pk, sk), b'howdy') 153 | 154 | def test_crypto_box_open(self): 155 | m = b"howdy" 156 | pk, sk = pysodium.crypto_box_keypair() 157 | n = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) 158 | c = pysodium.crypto_box(m, n, pk, sk) 159 | plaintext = pysodium.crypto_box_open(c, n, pk, sk) 160 | self.assertEqual(m, plaintext) 161 | 162 | def test_crypto_box_open_afternm(self): 163 | m = b"howdy" 164 | pk, sk = pysodium.crypto_box_keypair() 165 | k = pysodium.crypto_box_beforenm(pk, sk) 166 | n = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) 167 | c = pysodium.crypto_box_afternm(m, n, k) 168 | self.assertEqual(c, c) 169 | plaintext = pysodium.crypto_box_open_afternm(c, n, k) 170 | self.assertEqual(m, plaintext) 171 | 172 | def test_crypto_secretbox_open_detached(self): 173 | m = b"howdy" 174 | n = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) 175 | k = pysodium.randombytes(pysodium.crypto_secretbox_KEYBYTES) 176 | c, mac = pysodium.crypto_secretbox_detached(m, n, k) 177 | mplain = pysodium.crypto_secretbox_open_detached(c, mac, n, k) 178 | self.assertEqual(m, mplain) 179 | changed = b"\0"*len(c) 180 | self.assertRaises(ValueError, pysodium.crypto_secretbox_open_detached, changed, mac, n, k) 181 | 182 | def test_crypto_box_open_detached(self): 183 | pk, sk = pysodium.crypto_box_keypair() 184 | n = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) 185 | c, mac = pysodium.crypto_box_detached(b"howdy", n, pk, sk) 186 | r = pysodium.crypto_box_open_detached(c, mac, n, pk, sk) 187 | self.assertEqual(r, b"howdy") 188 | changed = b"\0"*len(c) 189 | self.assertRaises(ValueError, pysodium.crypto_box_open_detached,changed, mac, n, pk, sk) 190 | 191 | def test_crypto_secretbox_open(self): 192 | k = pysodium.randombytes(pysodium.crypto_secretbox_KEYBYTES) 193 | n = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) 194 | c = pysodium.crypto_secretbox(b"howdy", n, k) 195 | pysodium.crypto_secretbox_open(c, n, k) 196 | 197 | def test_crypto_secretstream_xchacha20poly1305_keygen(self): 198 | if not pysodium.sodium_version_check(1, 0, 15): return 199 | 200 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 201 | self.assertEqual(len(key), 32) 202 | 203 | # The following 3 tests verify that no exceptions are raised. Cannot check these 204 | # in any more detail as doing so would require internal knowledge of the state and 205 | # header structures, which may change. This can be assumed to be correct as long 206 | # as 'pull' test passes, it's decrypted values matches the original plain text. 207 | def test_crypto_secretstream_xchacha20poly1305_init_push(self): 208 | if not pysodium.sodium_version_check(1, 0, 15): return 209 | 210 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 211 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 212 | 213 | def test_crypto_secretstream_xchacha20poly1305_init_pull(self): 214 | if not pysodium.sodium_version_check(1, 0, 15): return 215 | 216 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 217 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 218 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) 219 | 220 | def test_crypto_secretstream_xchacha20poly1305_push(self): 221 | if not pysodium.sodium_version_check(1, 0, 15): return 222 | 223 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 224 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 225 | ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, 0) 226 | #---- 227 | 228 | def test_crypto_secretstream_xchacha20poly1305_pull(self): 229 | if not pysodium.sodium_version_check(1, 0, 15): return 230 | 231 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 232 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 233 | ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 234 | 235 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) 236 | msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None) 237 | 238 | self.assertEqual(msg, b"howdy") 239 | self.assertEqual(tag, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 240 | 241 | def test_crypto_secretstream_xchacha20poly1305_pull_changed_ad(self): 242 | if not pysodium.sodium_version_check(1, 0, 15): return 243 | 244 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 245 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 246 | ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", b"some data", pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 247 | 248 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) 249 | self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext, b"different data") 250 | 251 | 252 | def test_crypto_secretstream_xchacha20poly1305_pull_incorrect_key(self): 253 | if not pysodium.sodium_version_check(1, 0, 15): return 254 | 255 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 256 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 257 | ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 258 | 259 | bad_key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 260 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, bad_key) 261 | self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext, None) 262 | 263 | def test_crypto_secretstream_xchacha20poly1305_pull_multiple(self): 264 | if not pysodium.sodium_version_check(1, 0, 15): return 265 | 266 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 267 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 268 | 269 | ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0) 270 | ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 271 | 272 | # Verify decryption 273 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) 274 | msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None) 275 | msg2, tag2 = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext2, None) 276 | 277 | self.assertEqual(msg, b"Correct Horse Battery Staple") 278 | self.assertEqual(tag, 0) 279 | 280 | self.assertEqual(msg2, b"howdy") 281 | self.assertEqual(tag2, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 282 | 283 | def test_crypto_secretstream_xchacha20poly1305_pull_corrupted(self): 284 | if not pysodium.sodium_version_check(1, 0, 15): return 285 | 286 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 287 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 288 | 289 | ad = 'additional data' 290 | ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", ad, 0) 291 | 292 | # Verify error is raised if cypher text is changed 293 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) 294 | self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext + 'this is a corruption'.encode(), ad) 295 | 296 | # Verify error is raised if additional data is changed 297 | ad2 = 'this is not the same' 298 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) 299 | self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext, ad2) 300 | 301 | 302 | def test_crypto_secretstream_xchacha20poly1305_rekey(self): 303 | if not pysodium.sodium_version_check(1, 0, 15): return 304 | 305 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 306 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 307 | 308 | # Encrypt two messages with intermediate re-key 309 | ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0) 310 | pysodium.crypto_secretstream_xchacha20poly1305_rekey(state) 311 | ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 312 | 313 | # Verify by decrypting them 314 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) 315 | msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None) 316 | pysodium.crypto_secretstream_xchacha20poly1305_rekey(state2) 317 | msg2, tag2 = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext2, None) 318 | 319 | self.assertEqual(msg, b"Correct Horse Battery Staple") 320 | self.assertEqual(tag, 0) 321 | 322 | self.assertEqual(msg2, b"howdy") 323 | self.assertEqual(tag2, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 324 | 325 | def test_crypto_secretstream_xchacha20poly1305_missing_rekey(self): 326 | if not pysodium.sodium_version_check(1, 0, 15): return 327 | 328 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 329 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 330 | 331 | # Encrypt two messages with intermediate re-key 332 | ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0) 333 | pysodium.crypto_secretstream_xchacha20poly1305_rekey(state) 334 | ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 335 | 336 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) 337 | msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None) 338 | # re-key should be here, so following call should fail 339 | self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext2, None) 340 | 341 | def test_crypto_secretstream_xchacha20poly1305_out_of_order_messeges(self): 342 | if not pysodium.sodium_version_check(1, 0, 15): return 343 | 344 | key = pysodium.crypto_secretstream_xchacha20poly1305_keygen() 345 | state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key) 346 | 347 | ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0) 348 | ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 349 | 350 | # Decrypting the second message first should fail 351 | state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key) 352 | self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext2, None) 353 | 354 | def test_crypto_scalarmult_base(self): 355 | # In the C code, crypto_scalarmult_base just delegates to 356 | # crypto_scalarmult_curve25519_base. If libsodium changes the preferred 357 | # algorithm, this answer will change. 358 | k = binascii.unhexlify(b"e38e290880cee71a0cbb7b09328fd034c1fe4bd8838b19ab303a64a8c6b01456") 359 | expected = binascii.unhexlify(b"4aa82c2514ed88eb46085369a45ddd0db997e53bfee877c4556ab49a1581e545") 360 | actual = pysodium.crypto_scalarmult_base(k) 361 | self.assertEqual(expected, actual) 362 | 363 | def test_crypto_scalarmult_curve25519_base(self): 364 | s = pysodium.crypto_scalarmult_curve25519_base(pysodium.randombytes(pysodium.crypto_scalarmult_BYTES)) 365 | r = pysodium.crypto_scalarmult_curve25519_base(pysodium.randombytes(pysodium.crypto_scalarmult_BYTES)) 366 | pysodium.crypto_scalarmult_curve25519(s, r) 367 | 368 | def test_crypto_sign_open(self): 369 | pk, sk = pysodium.crypto_sign_keypair() 370 | signed = pysodium.crypto_sign(b'howdy', sk) 371 | changed = signed[:pysodium.crypto_sign_BYTES] + b'0' + signed[pysodium.crypto_sign_BYTES + 1:] 372 | pysodium.crypto_sign_open(signed, pk) 373 | self.assertRaises(ValueError, pysodium.crypto_sign_open, changed, pk) 374 | 375 | def test_crypto_sign_seed_keypair(self): 376 | seed = pysodium.crypto_generichash(b'howdy', outlen=pysodium.crypto_sign_SEEDBYTES) 377 | pk, sk = pysodium.crypto_sign_seed_keypair(seed) 378 | pk2, sk2 = pysodium.crypto_sign_seed_keypair(seed) 379 | self.assertEqual(pk, pk2) 380 | self.assertEqual(sk, sk2) 381 | 382 | def test_aead_aegis128l(self): 383 | if not pysodium.sodium_version_check(1, 0, 19): return 384 | key = binascii.unhexlify(b"4290bcb154173531f314af57f3be3b50") 385 | input_ = binascii.unhexlify(b"86d09974840bded2a5ca") 386 | nonce = binascii.unhexlify(b"087b5f9fadfb515388394f8035482608") 387 | ad = binascii.unhexlify(b"87e229d4500845a079c0") 388 | ct = binascii.unhexlify(b"a4fa71e3508259ff98e9e2874d98f97b7b3e14a033b835f25e335735385f604afe227394ad9032c1bcea") 389 | output = pysodium.crypto_aead_aegis128l_encrypt(input_, ad, nonce, key) 390 | self.assertEqual(bytes.hex(ct), bytes.hex(output)) 391 | output = pysodium.crypto_aead_aegis128l_decrypt(output, ad, nonce, key) 392 | self.assertEqual(output, input_) 393 | 394 | def test_aead_aegis256(self): 395 | if not pysodium.sodium_version_check(1, 0, 19): return 396 | key = binascii.unhexlify(b"4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007") 397 | input_ = binascii.unhexlify(b"86d09974840bded2a5ca") 398 | nonce = binascii.unhexlify(b"087b5f9fadfb515388394f8035482608e17b07153e560e301406cfad9f12c164") 399 | ad = binascii.unhexlify(b"87e229d4500845a079c0") 400 | ct = binascii.unhexlify(b"5b0b85a1a45a52e0950b2336fa9df3aacd14862fc4e7f670eafd04d6697be30973fa0f6c82cdfbfb1b7a") 401 | output = pysodium.crypto_aead_aegis256_encrypt(input_, ad, nonce, key) 402 | self.assertEqual(bytes.hex(ct), bytes.hex(output)) 403 | output = pysodium.crypto_aead_aegis256_decrypt(output, ad, nonce, key) 404 | self.assertEqual(output, input_) 405 | 406 | def test_aead_chacha20poly1305(self): 407 | key = binascii.unhexlify(b"4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007") 408 | input_ = binascii.unhexlify(b"86d09974840bded2a5ca") 409 | nonce = binascii.unhexlify(b"cd7cf67be39c794a") 410 | ct_common = b"e3e446f7ede9a19b62a4" 411 | for ad, ct in [ 412 | (binascii.unhexlify(b"87e229d4500845a079c0"), b"677dabf4e3d24b876bb284753896e1d6"), 413 | (None, b"69e7789bcd954e658ed38423e23161dc"), 414 | ]: 415 | output = pysodium.crypto_aead_chacha20poly1305_encrypt(input_, ad, nonce, key) 416 | self.assertEqual(binascii.unhexlify(ct_common + ct), output) 417 | output = pysodium.crypto_aead_chacha20poly1305_decrypt(output, ad, nonce, key) 418 | self.assertEqual(output, input_) 419 | 420 | def test_aead_chacha20poly1305_detached(self): 421 | if not pysodium.sodium_version_check(1, 0, 9): return 422 | key = binascii.unhexlify(b"4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007") 423 | input_ = binascii.unhexlify(b"86d09974840bded2a5ca") 424 | nonce = binascii.unhexlify(b"cd7cf67be39c794a") 425 | for ad, ct in [ 426 | (binascii.unhexlify(b"87e229d4500845a079c0"), b"677dabf4e3d24b876bb284753896e1d6"), 427 | (None, b"69e7789bcd954e658ed38423e23161dc"), 428 | ]: 429 | output, mac = pysodium.crypto_aead_chacha20poly1305_encrypt_detached(input_, ad, nonce, key) 430 | self.assertEqual(binascii.unhexlify(b"e3e446f7ede9a19b62a4"), output) 431 | self.assertEqual(binascii.unhexlify(ct), mac) 432 | output = pysodium.crypto_aead_chacha20poly1305_decrypt_detached(output, mac, ad, nonce, key) 433 | self.assertEqual(output, input_) 434 | 435 | def test_aead_chacha20poly1305_ietf(self): 436 | if not pysodium.sodium_version_check(1, 0, 4): return 437 | key = binascii.unhexlify(b"4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007") 438 | input_ = binascii.unhexlify(b"86d09974840bded2a5ca") 439 | nonce = binascii.unhexlify(b"cd7cf67be39c794acd7cf67b") 440 | for ad in [binascii.unhexlify(b"87e229d4500845a079c0"), None]: 441 | output = pysodium.crypto_aead_chacha20poly1305_ietf_encrypt(input_, ad, nonce, key) 442 | output = pysodium.crypto_aead_chacha20poly1305_ietf_decrypt(output, ad, nonce, key) 443 | self.assertEqual(output, input_) 444 | 445 | def test_aead_chacha20poly1305_ietf_detached(self): 446 | if not pysodium.sodium_version_check(1, 0, 9): return 447 | key = binascii.unhexlify(b"4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007") 448 | input_ = binascii.unhexlify(b"86d09974840bded2a5ca") 449 | nonce = binascii.unhexlify(b"cd7cf67be39c794acd7cf67b") 450 | for ad, ct in [ 451 | (binascii.unhexlify(b"87e229d4500845a079c0"), b"09394ed41cf16d3c0820c5e0caf8a7bf"), 452 | (None, b"07bf99e3c0d8aaac48c04e1f93b12a63"), 453 | ]: 454 | output, mac = pysodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached(input_, ad, nonce, key) 455 | self.assertEqual(binascii.unhexlify(b"eef4c561bdda5ef7e044"), output) 456 | self.assertEqual(binascii.unhexlify(ct), mac) 457 | output = pysodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached(output, mac, ad, nonce, key) 458 | self.assertEqual(output, input_) 459 | 460 | def test_aead_xchacha20poly1305_ietf(self): 461 | if not pysodium.sodium_version_check(1, 0, 12): return 462 | key = binascii.unhexlify(b"4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007") 463 | input_ = binascii.unhexlify(b"86d09974840bded2a5ca") 464 | nonce = binascii.unhexlify(b"cd7cf67be39c794acd7cf67bcd7cf67be39c794acd7cf67b") 465 | for ad in [binascii.unhexlify(b"87e229d4500845a079c0"), None]: 466 | output = pysodium.crypto_aead_xchacha20poly1305_ietf_encrypt(input_, ad, nonce, key) 467 | output = pysodium.crypto_aead_xchacha20poly1305_ietf_decrypt(output, ad, nonce, key) 468 | self.assertEqual(output, input_) 469 | 470 | def test_crypto_stream_chacha20_xor(self): 471 | key = binascii.unhexlify(b"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") 472 | nonce = binascii.unhexlify(b"0001020304050607") 473 | input_ = b'\x00' * 256 474 | output = pysodium.crypto_stream_chacha20_xor(input_, nonce, key) 475 | self.assertEqual(binascii.unhexlify(b"f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9"), 476 | output) 477 | 478 | def test_crypto_stream_chacha20_xor_ic(self): 479 | key = binascii.unhexlify(b"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") 480 | nonce = binascii.unhexlify(b"0001020304050607") 481 | input_ = b'\x00' * 128 482 | ic = 2 483 | output = pysodium.crypto_stream_chacha20_xor_ic(input_, nonce, ic, key) 484 | self.assertEqual(binascii.unhexlify(b"9db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9"), output) 485 | 486 | def test_crypto_stream_chacha20_ietf_xor(self): 487 | key = binascii.unhexlify(b"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") 488 | nonce = binascii.unhexlify(b"000000090000004a00000000") 489 | input_ = b'\x00' * 256 490 | output = pysodium.crypto_stream_chacha20_ietf_xor(input_, nonce, key) 491 | self.assertEqual(binascii.unhexlify(b"8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939a75584c52d690a35d410f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e0a88837739d7bf4ef8ccacb0ea2bb9d69d56c394aa351dfda5bf459f0a2e9fe8e721f89255f9c486bf21679c683d4f9c5cf2fa27865526005b06ca374c86af3bdcbfbdcb83be65862ed5c20eae5a43241d6a92da6dca9a156be25297f51c27188a861e93cc3aeb129a76598baccd27453ac6941b4b4e1e5153a9fee95d1ba00e"), 492 | output) 493 | 494 | def test_crypto_stream_chacha20_ietf_xor_ic(self): 495 | key = binascii.unhexlify(b"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") 496 | nonce = binascii.unhexlify(b"000000090000004a00000000") 497 | input_ = b'\x00' * 128 498 | ic = 2 499 | output = pysodium.crypto_stream_chacha20_ietf_xor_ic(input_, nonce, ic, key) 500 | self.assertEqual(binascii.unhexlify(b"0a88837739d7bf4ef8ccacb0ea2bb9d69d56c394aa351dfda5bf459f0a2e9fe8e721f89255f9c486bf21679c683d4f9c5cf2fa27865526005b06ca374c86af3bdcbfbdcb83be65862ed5c20eae5a43241d6a92da6dca9a156be25297f51c27188a861e93cc3aeb129a76598baccd27453ac6941b4b4e1e5153a9fee95d1ba00e"), output) 501 | 502 | def test_crypto_stream_xchacha20_xor(self): 503 | # test vectors taken from: 504 | # https://github.com/jedisct1/libsodium/blob/609e42be75589f91179d218e24f5e35a7124abfd/test/default/xchacha20.c#L102 505 | key = binascii.unhexlify("9d23bd4149cb979ccf3c5c94dd217e9808cb0e50cd0f67812235eaaf601d6232") 506 | nonce = binascii.unhexlify("c047548266b7c370d33566a2425cbf30d82d1eaf5294109e") 507 | out = binascii.unhexlify("a21209096594de8c5667b1d13ad93f744106d054df210e4782cd396fec692d3515a20bf351eec011a92c367888bc464c32f0807acd6c203a247e0db854148468e9f96bee4cf718d68d5f637cbd5a376457788e6fae90fc31097cfc") 508 | output = pysodium.crypto_stream_xchacha20_xor(out, nonce, key) 509 | self.assertEqual(b'\x00'*len(output), output) 510 | 511 | def test_crypto_stream_xchacha20_xor_ic(self): 512 | key = binascii.unhexlify("9d23bd4149cb979ccf3c5c94dd217e9808cb0e50cd0f67812235eaaf601d6232") 513 | nonce = binascii.unhexlify("c047548266b7c370d33566a2425cbf30d82d1eaf5294109e") 514 | out = binascii.unhexlify("a21209096594de8c5667b1d13ad93f744106d054df210e4782cd396fec692d3515a20bf351eec011a92c367888bc464c32f0807acd6c203a247e0db854148468e9f96bee4cf718d68d5f637cbd5a376457788e6fae90fc31097cfc") 515 | output = pysodium.crypto_stream_xchacha20_xor_ic(out, nonce, 0, key) 516 | self.assertEqual(b'\x00'*len(output), output) 517 | 518 | def test_crypto_blake2b(self): 519 | message = binascii.unhexlify(b'54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67') 520 | key = binascii.unhexlify(b'000102030405060708090a0b0c0d0e0f') 521 | 522 | # Test vectors generated from the blake2b reference implementation 523 | self.assertEqual(pysodium.crypto_generichash_blake2b_salt_personal(message, key = key), binascii.unhexlify(b'0f44eda51dba98442425d486b89962647c1a6e0e8b98a93e7090bf849a5156da')) 524 | self.assertEqual(pysodium.crypto_generichash_blake2b_salt_personal(message, personal = key), binascii.unhexlify(b'8c68aecca4b50e91aebaf8c53bde15b68c01b13d571a772fcb8b432affa52a7c')) 525 | self.assertEqual(pysodium.crypto_generichash_blake2b_salt_personal(message, salt = key), binascii.unhexlify(b'43b7feaa91019d0d5b492357fb923211af827d6126af28ccc1874e70bc2177f8')) 526 | self.assertEqual(pysodium.crypto_generichash_blake2b_salt_personal(message, personal = key[0:8]), binascii.unhexlify(b'31353589b3f179cda74387fbe1deca94f004661f05cde2295a16c0a8d8ead79b')) 527 | self.assertEqual(pysodium.crypto_generichash_blake2b_salt_personal(message, salt = key[0:8]), binascii.unhexlify(b'11c29bf7b91b8500a463f27e215dc83afdb71ed5e959f0847e339769c4835fc7')) 528 | self.assertEqual(pysodium.crypto_generichash_blake2b_salt_personal(message, personal = key, key = key), binascii.unhexlify(b'5a0b3db4bf2dab71485211447fc2014391228cc6c1acd2f3031050a9a32ca407')) 529 | 530 | 531 | def test_crypto_pwhash(self): 532 | if not pysodium.sodium_version_check(1, 0, 9): return 533 | pw = "Correct Horse Battery Staple" 534 | salt = binascii.unhexlify(b'0f58b94c7a369fd8a9a7083e4cd75266') 535 | out = pysodium.crypto_pwhash(pysodium.crypto_auth_KEYBYTES, pw, salt, pysodium.crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE, pysodium.crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE, pysodium.crypto_pwhash_ALG_ARGON2I13) 536 | self.assertEqual(binascii.hexlify(out), b'79db3095517c7358449d84ee3b2f81f0e9907fbd4e0bae4e0bcc6c79821427dc') 537 | 538 | def test_crypto_pwhash_storage(self): 539 | if not pysodium.sodium_version_check(1, 0, 9): return 540 | pw = "Correct Horse Battery Staple" 541 | pstr = pysodium.crypto_pwhash_str(pw, pysodium.crypto_pwhash_OPSLIMIT_INTERACTIVE, pysodium.crypto_pwhash_MEMLIMIT_INTERACTIVE) 542 | self.assertTrue(pysodium.crypto_pwhash_str_verify(pstr, pw)) 543 | 544 | def test_crypto_pwhash_scryptsalsa208sha256(self): 545 | passwd = b'Correct Horse Battery Staple' 546 | other_passwd = b'correct horse battery staple' 547 | salt = binascii.unhexlify(b'4206baae5578933d7cfb315b1c257cc7af162965a91a74ccbb1cfa1d747eb691') 548 | other_salt = binascii.unhexlify(b'4206baae5578933d7cfb315b1c257cc7af162965a91a74ccbb1cfa1d747eb692') 549 | 550 | # Use very small limits to avoid burning resources in CI 551 | mem_limit = 16777216 552 | ops_limit = 32768 553 | 554 | key16 = pysodium.crypto_pwhash_scryptsalsa208sha256(16, passwd, salt, ops_limit, mem_limit) 555 | self.assertEqual(len(key16), 16) 556 | self.assertEqual(key16, b'U\x18aL\xcf\xc9\xa3\xf6(\x8f\xed)\xeej8\xdf') 557 | 558 | key = pysodium.crypto_pwhash_scryptsalsa208sha256(32, passwd, salt, ops_limit, mem_limit) 559 | self.assertEqual(len(key), 32) 560 | self.assertEqual(key, b'U\x18aL\xcf\xc9\xa3\xf6(\x8f\xed)\xeej8\xdfG\x82hf+vu\xcd\x9c\xdb\xbcmt\xf7\xf1\x10') 561 | 562 | self.assertNotEqual(key, pysodium.crypto_pwhash_scryptsalsa208sha256(32, passwd, other_salt, ops_limit, mem_limit)) 563 | self.assertNotEqual(key, pysodium.crypto_pwhash_scryptsalsa208sha256(32, other_passwd, salt, ops_limit, mem_limit)) 564 | 565 | def test_crypto_pwhash_scryptsalsa208sha256_str(self): 566 | passwd = b'Correct Horse Battery Staple' 567 | 568 | # Use very small limits to avoid burning resources in CI 569 | mem_limit = 16777216 570 | ops_limit = 32768 571 | 572 | storage_string = pysodium.crypto_pwhash_scryptsalsa208sha256_str(passwd, ops_limit, mem_limit) 573 | self.assertTrue(storage_string.startswith(pysodium.crypto_pwhash_scryptsalsa208sha256_STRPREFIX)) 574 | 575 | self.assertNotEqual(storage_string, pysodium.crypto_pwhash_scryptsalsa208sha256_str(passwd, ops_limit, mem_limit), "Each call should compute a new random salt.") 576 | 577 | def test_crypto_pwhash_scryptsalsa208sha256_str_verify(self): 578 | passwd = b'Correct Horse Battery Staple' 579 | other_passwd = b'correct horse battery staple' 580 | 581 | # Use very small limits to avoid burning resources in CI 582 | mem_limit = 16777216 583 | ops_limit = 32768 584 | 585 | storage_string = pysodium.crypto_pwhash_scryptsalsa208sha256_str(passwd, ops_limit, mem_limit) 586 | 587 | pysodium.crypto_pwhash_scryptsalsa208sha256_str_verify(storage_string, passwd) 588 | 589 | self.assertRaises(ValueError, pysodium.crypto_pwhash_scryptsalsa208sha256_str_verify, storage_string, other_passwd) 590 | self.assertRaises(ValueError, pysodium.crypto_pwhash_scryptsalsa208sha256_str_verify, storage_string[:-1], passwd) 591 | self.assertRaises(ValueError, pysodium.crypto_pwhash_scryptsalsa208sha256_str_verify, storage_string + b'a', passwd) 592 | 593 | def test_crypto_sign_sk_to_pk(self): 594 | pk, sk = pysodium.crypto_sign_keypair() 595 | pk2 = pysodium.crypto_sign_sk_to_pk(sk) 596 | self.assertEqual(pk, pk2) 597 | 598 | def test_crypto_sign_sk_to_seed(self): 599 | seed1 = pysodium.crypto_generichash(b'howdy', outlen=pysodium.crypto_sign_SEEDBYTES) 600 | _, sk = pysodium.crypto_sign_seed_keypair(seed1) 601 | seed2 = pysodium.crypto_sign_sk_to_seed(sk) 602 | self.assertEqual(seed1, seed2) 603 | 604 | def test_AsymCrypto_With_Seeded_Keypair(self): 605 | msg = b"correct horse battery staple" 606 | nonce = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) 607 | pk, sk = pysodium.crypto_box_seed_keypair(b"\x00" * pysodium.crypto_box_SEEDBYTES) 608 | 609 | c = pysodium.crypto_box(msg, nonce, pk, sk) 610 | m = pysodium.crypto_box_open(c, nonce, pk, sk) 611 | 612 | self.assertEqual(msg, m) 613 | 614 | def test_crypto_hash_sha256(self): 615 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha256(b"test")), 616 | "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08") 617 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha256(b"howdy")), 618 | "0f1128046248f83dc9b9ab187e16fad0ff596128f1524d05a9a77c4ad932f10a") 619 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha256(b"Correct Horse Battery Staple")), 620 | "af139fa284364215adfa49c889ab7feddc5e5d1c52512ffb2cfc9baeb67f220e") 621 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha256(b"pysodium")), 622 | "0a53ef9bc1bea173118a42bbbe8300abb6bbef83139046940e9593d9559a5df7") 623 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha256(b"\x80")), 624 | "76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71") 625 | 626 | def test_crypto_hash_sha512(self): 627 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha512(b"test")), 628 | "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff") 629 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha512(b"howdy")), 630 | "905caca5c4685f296c5491d38660d7720ee87bef08f829332e905593522907674de8490de46c969d2c585b40af40439b387562d6f776023507753d1a9554ebbb") 631 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha512(b"Correct Horse Battery Staple")), 632 | "0675070bda47bef936f0b65ae721d90f82ca137841df4d7cae27776501ae4b446ab926d64dc1d282c8758ac0eb02cc4aa11b2452d4f8ffeb795023b797fe2b80") 633 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha512(b"pysodium")), 634 | "ecbc6f4ffdb6e6dcbe6e6beecf0b8e05c11b0cc8a56f2b4098cd613585749fcca5ed1cfda3518e33a5d2c63746ee2857ff6857b9a2eeda4cc208c1e7fd89cc17") 635 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha512(b"\x80")), 636 | "dfe8ef54110b3324d3b889035c95cfb80c92704614bf76f17546ad4f4b08218a630e16da7df34766a975b3bb85b01df9e99a4ec0a1d0ec3de6bed7b7a40b2f10") 637 | 638 | def test_crypto_hash_sha512_steps(self): 639 | s = pysodium.crypto_hash_sha512_init() 640 | pysodium.crypto_hash_sha512_update(s, b"Correct Horse ") 641 | pysodium.crypto_hash_sha512_update(s, b"Battery Staple") 642 | self.assertEqual(self.byteHashToString(pysodium.crypto_hash_sha512_final(s)), 643 | "0675070bda47bef936f0b65ae721d90f82ca137841df4d7cae27776501ae4b446ab926d64dc1d282c8758ac0eb02cc4aa11b2452d4f8ffeb795023b797fe2b80") 644 | 645 | def byteHashToString(self, input): 646 | return binascii.hexlify(input).decode('utf8') 647 | 648 | def test_crypto_auth(self): 649 | sk = pysodium.randombytes(pysodium.crypto_auth_KEYBYTES) 650 | tag = pysodium.crypto_auth("howdy", sk) 651 | pysodium.crypto_auth_verify(tag, "howdy", sk) 652 | 653 | def test_crypto_kdf_keygen(self): 654 | key = pysodium.crypto_kdf_keygen() 655 | self.assertEqual(pysodium.crypto_kdf_KEYBYTES, len(key)) 656 | 657 | def test_crypto_kdf_derive_from_key(self): 658 | # https://github.com/jedisct1/libsodium/blob/master/test/default/kdf.exp 659 | expected_subkey = bytes.fromhex("a0c724404728c8bb95e5433eb6a9716171144d61efb23e74b873fcbeda51d8071b5d70aae12066dfc94ce943f145aa176c055040c3dd73b0a15e36254d450614") 660 | subkey_id = 0 661 | ctx = b'KDF test' 662 | key = bytes.fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") 663 | self.assertEqual(expected_subkey, pysodium. crypto_kdf_derive_from_key(pysodium.crypto_kdf_BYTES_MAX, subkey_id, ctx, key)) 664 | 665 | expected_subkey = bytes.fromhex("02507f144fa9bf19010bf7c70b235b4c2663cc00e074f929602a5e2c10a780757d2a3993d06debc378a90efdac196dd841817b977d67b786804f6d3cd585bab5") 666 | subkey_id = 1 667 | ctx = b'KDF test' 668 | key = bytes.fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") 669 | self.assertEqual(expected_subkey, pysodium.crypto_kdf_derive_from_key(pysodium.crypto_kdf_BYTES_MAX, subkey_id, ctx, key)) 670 | 671 | def test_crypto_kdf_hkdf_sha256(self): 672 | # test vectors: https://datatracker.ietf.org/doc/html/rfc5869 673 | if not pysodium.sodium_version_check(1, 0, 19): return 674 | expected_prk = bytes.fromhex("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") 675 | expected_out = bytes.fromhex("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") 676 | ikm = bytes.fromhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b") 677 | salt = bytes.fromhex("000102030405060708090a0b0c") 678 | ctx = bytes.fromhex("f0f1f2f3f4f5f6f7f8f9") 679 | outlen = 42 680 | self.assertEqual(expected_prk, pysodium.crypto_kdf_hkdf_sha256_extract(salt, ikm)) 681 | self.assertEqual(expected_out, pysodium.crypto_kdf_hkdf_sha256_expand(outlen, expected_prk, ctx)) 682 | 683 | expected_prk = bytes.fromhex("06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244") 684 | expected_out = bytes.fromhex("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87") 685 | ikm = bytes.fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f") 686 | salt = bytes.fromhex("606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf") 687 | ctx = bytes.fromhex("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") 688 | outlen = 82 689 | self.assertEqual(expected_prk, pysodium.crypto_kdf_hkdf_sha256_extract(salt, ikm)) 690 | self.assertEqual(expected_out, pysodium.crypto_kdf_hkdf_sha256_expand(outlen, expected_prk, ctx)) 691 | 692 | expected_prk = bytes.fromhex("19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04") 693 | expected_out = bytes.fromhex("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8") 694 | ikm = bytes.fromhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b") 695 | salt = bytes.fromhex("") 696 | ctx = bytes.fromhex("") 697 | outlen = 42 698 | state = pysodium.crypto_kdf_hkdf_sha256_extract_init(salt) 699 | state = pysodium.crypto_kdf_hkdf_sha256_extract_update(state, ikm) 700 | self.assertEqual(expected_prk, pysodium.crypto_kdf_hkdf_sha256_extract_final(state)) 701 | self.assertEqual(expected_out, pysodium.crypto_kdf_hkdf_sha256_expand(outlen, expected_prk, ctx)) 702 | 703 | def test_crypto_kdf_hkdf_sha512(self): 704 | if not pysodium.sodium_version_check(1, 0, 19): return 705 | expected_prk = bytes.fromhex("665799823737ded04a88e47e54a5890bb2c3d247c7a4254a8e61350723590a26c36238127d8661b88cf80ef802d57e2f7cebcf1e00e083848be19929c61b4237") 706 | expected_out = bytes.fromhex("832390086cda71fb47625bb5ceb168e4c8e26a1a16ed34d9fc7fe92c1481579338da362cb8d9f925d7cb") 707 | ikm = bytes.fromhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b") 708 | salt = bytes.fromhex("000102030405060708090a0b0c") 709 | ctx = bytes.fromhex("f0f1f2f3f4f5f6f7f8f9") 710 | outlen = 42 711 | self.assertEqual(expected_prk, pysodium.crypto_kdf_hkdf_sha512_extract(salt, ikm)) 712 | self.assertEqual(expected_out, pysodium.crypto_kdf_hkdf_sha512_expand(outlen, expected_prk, ctx)) 713 | 714 | def test_crypto_kx(self): 715 | if not pysodium.sodium_version_check(1, 0, 12): return 716 | client_pk, client_sk = pysodium.crypto_kx_keypair() 717 | server_pk, server_sk = pysodium.crypto_kx_keypair() 718 | 719 | crx, ctx = pysodium.crypto_kx_client_session_keys(client_pk, client_sk, server_pk) 720 | srx, stx = pysodium.crypto_kx_server_session_keys(server_pk, server_sk, client_pk) 721 | 722 | self.assertEqual(crx, stx) 723 | self.assertEqual(ctx, srx) 724 | 725 | def test_sodium_inc(self): 726 | r = b'A' * 32 727 | pysodium.sodium_increment(r) 728 | self.assertEqual(r, b'BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA') 729 | 730 | def test_crypto_core_ristretto255_scalar_random(self): 731 | if not pysodium.sodium_version_check(1, 0, 18): return 732 | a = pysodium.crypto_core_ristretto255_scalar_random() 733 | b = pysodium.crypto_core_ristretto255_scalar_random() 734 | # stupid check that random returns different values... 735 | self.assertNotEqual(a,b) 736 | 737 | def test_crypto_core_ristretto255_random(self): 738 | if not pysodium.sodium_version_check(1, 0, 18): return 739 | a = pysodium.crypto_core_ristretto255_random() 740 | b = pysodium.crypto_core_ristretto255_random() 741 | # same stupid check that random returns different values... 742 | self.assertNotEqual(a,b) 743 | 744 | def test_crypto_core_ristretto255_is_valid_point(self): 745 | if not pysodium.sodium_version_check(1, 0, 18): return 746 | invalid = binascii.unhexlify(b"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f") 747 | self.assertEqual(False, pysodium.crypto_core_ristretto255_is_valid_point(invalid)) 748 | invalid = binascii.unhexlify(b"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f") 749 | self.assertEqual(False, pysodium.crypto_core_ristretto255_is_valid_point(invalid)) 750 | 751 | def test_crypto_core_ristretto255_from_hash(self): 752 | if not pysodium.sodium_version_check(1, 0, 18): return 753 | h = pysodium.crypto_generichash(b'howdy', outlen=pysodium.crypto_core_ristretto255_HASHBYTES) 754 | p = pysodium.crypto_core_ristretto255_from_hash(h) 755 | pysodium.crypto_core_ristretto255_is_valid_point(p) 756 | 757 | def test_crypto_scalarmult_ristretto255_base(self): 758 | if not pysodium.sodium_version_check(1, 0, 18): return 759 | p = pysodium.crypto_scalarmult_ristretto255_base(pysodium.crypto_core_ristretto255_scalar_random()) 760 | pysodium.crypto_core_ristretto255_is_valid_point(p) 761 | 762 | def test_crypto_scalarmult_ristretto255(self): 763 | if not pysodium.sodium_version_check(1, 0, 18): return 764 | n = pysodium.crypto_scalarmult_ristretto255_base(pysodium.crypto_core_ristretto255_scalar_random()) 765 | p = pysodium.crypto_scalarmult_ristretto255_base(pysodium.crypto_core_ristretto255_scalar_random()) 766 | r = pysodium.crypto_scalarmult_ristretto255(n, p) 767 | pysodium.crypto_core_ristretto255_is_valid_point(r) 768 | 769 | def test_crypto_core_ristretto255_scalar_invert(self): 770 | if not pysodium.sodium_version_check(1, 0, 18): return 771 | s = pysodium.crypto_core_ristretto255_scalar_random() 772 | r = pysodium.crypto_core_ristretto255_scalar_invert(s) 773 | p = pysodium.crypto_scalarmult_ristretto255_base(pysodium.crypto_core_ristretto255_scalar_random()) 774 | q = pysodium.crypto_scalarmult_ristretto255(s, p) 775 | p_ = pysodium.crypto_scalarmult_ristretto255(r, q) 776 | self.assertEqual(p,p_) 777 | 778 | def test_crypto_core_ristretto255_add_sub(self): 779 | if not pysodium.sodium_version_check(1, 0, 18): return 780 | p = pysodium.crypto_core_ristretto255_random() 781 | q = pysodium.crypto_core_ristretto255_random() 782 | 783 | p_q = pysodium.crypto_core_ristretto255_add(p, q) 784 | r = pysodium.crypto_core_ristretto255_sub(p_q,q) 785 | self.assertEqual(p,r) 786 | 787 | def test_crypto_core_ristretto255_scalar_add_sub(self): 788 | if not pysodium.sodium_version_check(1, 0, 18): return 789 | 790 | x = pysodium.crypto_core_ristretto255_scalar_random() 791 | y = pysodium.crypto_core_ristretto255_scalar_random() 792 | x_y = pysodium.crypto_core_ristretto255_scalar_add(x,y) 793 | r = pysodium.crypto_core_ristretto255_scalar_sub(x_y,y) 794 | 795 | p1 = pysodium.crypto_scalarmult_ristretto255_base(x) 796 | p2 = pysodium.crypto_scalarmult_ristretto255_base(r) 797 | self.assertEqual(p1,p2) 798 | 799 | def test_crypto_core_ristretto255_scalar_negate(self): 800 | if not pysodium.sodium_version_check(1, 0, 18): return 801 | s = pysodium.crypto_core_ristretto255_scalar_random() 802 | r = pysodium.crypto_core_ristretto255_scalar_negate(s) 803 | # s + neg(s) = 0 mod L 804 | s_r = pysodium.crypto_core_ristretto255_scalar_add(s,r) 805 | self.assertEqual(s_r,b"\x00"*32) 806 | 807 | def test_crypto_core_ristretto255_scalar_complement(self): 808 | if not pysodium.sodium_version_check(1, 0, 18): return 809 | x = pysodium.crypto_core_ristretto255_scalar_random() 810 | x_ = pysodium.crypto_core_ristretto255_scalar_complement(x) 811 | # x + complement(x) = 1 mod L 812 | one = pysodium.crypto_core_ristretto255_scalar_add(x,x_) 813 | self.assertEqual(one,b'\x01'+b"\x00"*31) 814 | 815 | def test_crypto_core_ristretto255_scalar_mul(self): 816 | if not pysodium.sodium_version_check(1, 0, 18): return 817 | two = b'\x02' + b'\x00' * 31 818 | four_mul = pysodium.crypto_core_ristretto255_scalar_mul(two,two) 819 | four_add = pysodium.crypto_core_ristretto255_scalar_add(two,two) 820 | self.assertEqual(four_mul,four_add) 821 | 822 | x = pysodium.crypto_core_ristretto255_scalar_random() 823 | one = b'\x01' + b'\x00' * 31 824 | r = pysodium.crypto_core_ristretto255_scalar_mul(x,one) 825 | self.assertEqual(x,r) 826 | 827 | if __name__ == '__main__': 828 | unittest.main() 829 | --------------------------------------------------------------------------------