1#!/usr/bin/env python2
2"""
3Wrapper for libsodium library
4
5Copyright (c) 2013-2014, Marsiske Stefan.
6All rights reserved.
7
8Redistribution and use in source and binary forms, with or without modification,
9are 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
18THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28"""
29
30import ctypes
31import ctypes.util
32
33sodium = ctypes.cdll.LoadLibrary(ctypes.util.find_library('sodium') or ctypes.util.find_library('libsodium'))
34if not sodium._name:
35    raise ValueError('Unable to find libsodium')
36
37sodium.sodium_version_string.restype = ctypes.c_char_p
38
39try:
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])
43except (IndexError, ValueError):
44    raise ValueError('Unable to parse version string from libsodium')
45
46def 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
57def 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
66def 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
95sodium.crypto_pwhash_scryptsalsa208sha256_strprefix.restype = ctypes.c_char_p
96
97crypto_auth_KEYBYTES = sodium.crypto_auth_keybytes()
98crypto_auth_BYTES = sodium.crypto_auth_bytes()
99crypto_box_NONCEBYTES = sodium.crypto_box_noncebytes()
100crypto_box_BEFORENMBYTES = sodium.crypto_box_beforenmbytes()
101crypto_box_PUBLICKEYBYTES = sodium.crypto_box_publickeybytes()
102crypto_box_SECRETKEYBYTES = sodium.crypto_box_secretkeybytes()
103crypto_box_ZEROBYTES = sodium.crypto_box_zerobytes()
104crypto_box_BOXZEROBYTES = sodium.crypto_box_boxzerobytes()
105crypto_box_MACBYTES = sodium.crypto_box_macbytes()
106crypto_box_SEALBYTES = sodium.crypto_box_sealbytes()
107crypto_box_SEEDBYTES = sodium.crypto_box_seedbytes()
108crypto_secretbox_KEYBYTES = sodium.crypto_secretbox_keybytes()
109crypto_secretbox_NONCEBYTES = sodium.crypto_secretbox_noncebytes()
110crypto_secretbox_ZEROBYTES = sodium.crypto_secretbox_zerobytes()
111crypto_secretbox_BOXZEROBYTES = sodium.crypto_secretbox_boxzerobytes()
112crypto_secretbox_MACBYTES = sodium.crypto_secretbox_macbytes()
113crypto_sign_PUBLICKEYBYTES = sodium.crypto_sign_publickeybytes()
114crypto_sign_SECRETKEYBYTES = sodium.crypto_sign_secretkeybytes()
115crypto_sign_SEEDBYTES = sodium.crypto_sign_seedbytes()
116crypto_sign_BYTES = sodium.crypto_sign_bytes()
117crypto_sign_ed25519_SECRETKEYBYTES = sodium.crypto_sign_ed25519_secretkeybytes()
118crypto_sign_ed25519_PUBLICKEYBYTES = sodium.crypto_sign_ed25519_publickeybytes()
119crypto_stream_KEYBYTES = sodium.crypto_stream_keybytes()
120crypto_stream_NONCEBYTES = sodium.crypto_stream_noncebytes()
121crypto_stream_chacha20_NONCEBYTES = sodium.crypto_stream_chacha20_noncebytes()
122crypto_stream_chacha20_KEYBYTES = sodium.crypto_stream_chacha20_keybytes()
123crypto_stream_xchacha20_NONCEBYTES = sodium.crypto_stream_xchacha20_noncebytes()
124crypto_stream_xchacha20_KEYBYTES = sodium.crypto_stream_xchacha20_keybytes()
125crypto_generichash_KEYBYTES_MAX = sodium.crypto_generichash_keybytes_max()
126crypto_generichash_BYTES = sodium.crypto_generichash_bytes()
127crypto_generichash_BYTES_MIN = sodium.crypto_generichash_bytes_min()
128crypto_generichash_BYTES_MAX = sodium.crypto_generichash_bytes_max()
129crypto_generichash_STATEBYTES = sodium.crypto_generichash_statebytes()
130crypto_scalarmult_curve25519_BYTES = sodium.crypto_scalarmult_curve25519_bytes()
131crypto_scalarmult_BYTES = sodium.crypto_scalarmult_bytes()
132crypto_scalarmult_SCALARBYTES = sodium.crypto_scalarmult_curve25519_scalarbytes()
133crypto_generichash_blake2b_KEYBYTES_MAX = sodium.crypto_generichash_blake2b_keybytes_max()
134crypto_generichash_blake2b_BYTES = sodium.crypto_generichash_blake2b_bytes()
135crypto_generichash_blake2b_BYTES_MIN = sodium.crypto_generichash_blake2b_bytes_min()
136crypto_generichash_blake2b_BYTES_MAX = sodium.crypto_generichash_blake2b_bytes_max()
137crypto_generichash_blake2b_SALTBYTES = sodium.crypto_generichash_blake2b_saltbytes()
138crypto_generichash_blake2b_PERSONALBYTES = sodium.crypto_generichash_blake2b_personalbytes()
139crypto_pwhash_scryptsalsa208sha256_SALTBYTES = sodium.crypto_pwhash_scryptsalsa208sha256_saltbytes()
140crypto_pwhash_scryptsalsa208sha256_STRBYTES = sodium.crypto_pwhash_scryptsalsa208sha256_strbytes()
141crypto_pwhash_scryptsalsa208sha256_STRPREFIX = sodium.crypto_pwhash_scryptsalsa208sha256_strprefix()
142crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE = sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_interactive()
143crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE = sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_interactive()
144crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE = sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive()
145crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE = sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive()
146crypto_hash_sha256_BYTES = sodium.crypto_hash_sha256_bytes()
147crypto_hash_sha512_BYTES = sodium.crypto_hash_sha512_bytes()
148crypto_hash_sha512_STATEBYTES = sodium.crypto_hash_sha512_statebytes()
149crypto_aead_chacha20poly1305_KEYBYTES = sodium.crypto_aead_chacha20poly1305_keybytes()
150crypto_aead_chacha20poly1305_NPUBBYTES = sodium.crypto_aead_chacha20poly1305_npubbytes()
151crypto_aead_chacha20poly1305_NONCEBYTES = crypto_aead_chacha20poly1305_NPUBBYTES
152crypto_aead_chacha20poly1305_ABYTES = sodium.crypto_aead_chacha20poly1305_abytes()
153
154if sodium_version_check(1, 0, 9):
155    crypto_aead_chacha20poly1305_ietf_KEYBYTES = sodium.crypto_aead_chacha20poly1305_ietf_keybytes()
156    crypto_aead_chacha20poly1305_ietf_NPUBBYTES = sodium.crypto_aead_chacha20poly1305_ietf_npubbytes()
157    crypto_aead_chacha20poly1305_ietf_ABYTES = sodium.crypto_aead_chacha20poly1305_ietf_abytes()
158    crypto_pwhash_SALTBYTES = sodium.crypto_pwhash_saltbytes()
159    crypto_pwhash_STRBYTES = sodium.crypto_pwhash_strbytes()
160    crypto_pwhash_OPSLIMIT_INTERACTIVE = sodium.crypto_pwhash_opslimit_interactive()
161    crypto_pwhash_MEMLIMIT_INTERACTIVE = sodium.crypto_pwhash_memlimit_interactive()
162    crypto_pwhash_OPSLIMIT_MODERATE = sodium.crypto_pwhash_opslimit_moderate()
163    crypto_pwhash_MEMLIMIT_MODERATE = sodium.crypto_pwhash_memlimit_moderate()
164    crypto_pwhash_OPSLIMIT_SENSITIVE = sodium.crypto_pwhash_opslimit_sensitive()
165    crypto_pwhash_MEMLIMIT_SENSITIVE = sodium.crypto_pwhash_memlimit_sensitive()
166    crypto_pwhash_ALG_DEFAULT = sodium.crypto_pwhash_alg_default()
167    crypto_pwhash_ALG_ARGON2I13 = sodium.crypto_pwhash_alg_argon2i13()
168    crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE = sodium.crypto_pwhash_argon2i_opslimit_interactive()
169    crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE = sodium.crypto_pwhash_argon2i_memlimit_interactive()
170    crypto_pwhash_argon2i_OPSLIMIT_MODERATE = sodium.crypto_pwhash_argon2i_opslimit_moderate()
171    crypto_pwhash_argon2i_MEMLIMIT_MODERATE = sodium.crypto_pwhash_argon2i_memlimit_moderate()
172    crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE = sodium.crypto_pwhash_argon2i_opslimit_sensitive()
173    crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE = sodium.crypto_pwhash_argon2i_memlimit_sensitive()
174else:
175    crypto_pwhash_ALG_DEFAULT = None
176    crypto_aead_chacha20poly1305_ietf_KEYBYTES = 32
177    crypto_aead_chacha20poly1305_ietf_NPUBBYTES = 12
178    crypto_aead_chacha20poly1305_ietf_ABYTES = 16
179    crypto_pwhash_BYTES_MAX = 4294967295
180    crypto_pwhash_BYTES_MIN = 16
181    crypto_pwhash_MEMLIMIT_MAX = 4398046510080
182    crypto_pwhash_MEMLIMIT_MIN = 1
183    crypto_pwhash_OPSLIMIT_MAX = 4294967295
184    crypto_pwhash_OPSLIMIT_MIN = 3
185    crypto_pwhash_PASSWD_MAX = 4294967295
186    crypto_pwhash_PASSWD_MIN = 0
187
188crypto_aead_chacha20poly1305_ietf_NONCEBYTES = crypto_aead_chacha20poly1305_ietf_NPUBBYTES
189
190if sodium_version_check(1, 0, 12):
191    crypto_kx_PUBLICKEYBYTES = sodium.crypto_kx_publickeybytes()
192    crypto_kx_SECRETKEYBYTES = sodium.crypto_kx_secretkeybytes()
193    crypto_kx_SESSIONKEYBYTES = sodium.crypto_kx_sessionkeybytes()
194    crypto_aead_xchacha20poly1305_ietf_KEYBYTES = sodium.crypto_aead_xchacha20poly1305_ietf_keybytes()
195    crypto_aead_xchacha20poly1305_ietf_NPUBBYTES = sodium.crypto_aead_xchacha20poly1305_ietf_npubbytes()
196    crypto_aead_xchacha20poly1305_ietf_NONCEBYTES = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
197    crypto_aead_xchacha20poly1305_ietf_ABYTES = sodium.crypto_aead_xchacha20poly1305_ietf_abytes()
198    sodium.crypto_pwhash_bytes_max.restype=ctypes.c_uint
199    sodium.crypto_pwhash_opslimit_max.restype=ctypes.c_uint
200    sodium.crypto_pwhash_memlimit_max.restype=ctypes.c_uint
201    sodium.crypto_pwhash_passwd_max.restype=ctypes.c_uint
202    sodium.crypto_pwhash_scryptsalsa208sha256_bytes_max.restype=ctypes.c_uint
203    sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_max.restype=ctypes.c_uint
204    sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_max.restype=ctypes.c_ulonglong
205    sodium.crypto_pwhash_scryptsalsa208sha256_passwd_max.restype=ctypes.c_uint
206    crypto_pwhash_BYTES_MAX = sodium.crypto_pwhash_bytes_max()
207    crypto_pwhash_BYTES_MIN = sodium.crypto_pwhash_bytes_min()
208    crypto_pwhash_MEMLIMIT_MAX = sodium.crypto_pwhash_memlimit_max()
209    crypto_pwhash_MEMLIMIT_MIN = sodium.crypto_pwhash_memlimit_min()
210    crypto_pwhash_OPSLIMIT_MAX = sodium.crypto_pwhash_opslimit_max()
211    crypto_pwhash_OPSLIMIT_MIN = sodium.crypto_pwhash_opslimit_min()
212    crypto_pwhash_PASSWD_MAX = sodium.crypto_pwhash_passwd_max()
213    crypto_pwhash_PASSWD_MIN = sodium.crypto_pwhash_passwd_min()
214    crypto_pwhash_scryptsalsa208sha256_BYTES_MAX = sodium.crypto_pwhash_scryptsalsa208sha256_bytes_max()
215    crypto_pwhash_scryptsalsa208sha256_BYTES_MIN = sodium.crypto_pwhash_scryptsalsa208sha256_bytes_min()
216    crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX = sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_max()
217    crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN = sodium.crypto_pwhash_scryptsalsa208sha256_memlimit_min()
218    crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX = sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_max()
219    crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN = sodium.crypto_pwhash_scryptsalsa208sha256_opslimit_min()
220    crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX = sodium.crypto_pwhash_scryptsalsa208sha256_passwd_max()
221    crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN = sodium.crypto_pwhash_scryptsalsa208sha256_passwd_min()
222else:
223    crypto_pwhash_scryptsalsa208sha256_BYTES_MIN = 16
224    crypto_pwhash_scryptsalsa208sha256_BYTES_MAX = 4294967264
225    crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX = 68719476736
226    crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN = 16777216
227    crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN = 32768
228    crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX =4294967295
229    crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX = 4294967295
230    crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN = 0
231
232if sodium_version_check(1, 0, 13):
233    crypto_pwhash_ALG_ARGON2ID13 = sodium.crypto_pwhash_alg_argon2id13()
234    crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE = sodium.crypto_pwhash_argon2id_opslimit_interactive()
235    crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE = sodium.crypto_pwhash_argon2id_memlimit_interactive()
236    crypto_pwhash_argon2id_OPSLIMIT_MODERATE = sodium.crypto_pwhash_argon2id_opslimit_moderate()
237    crypto_pwhash_argon2id_MEMLIMIT_MODERATE = sodium.crypto_pwhash_argon2id_memlimit_moderate()
238    crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE = sodium.crypto_pwhash_argon2id_opslimit_sensitive()
239    crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE = sodium.crypto_pwhash_argon2id_memlimit_sensitive()
240
241if sodium_version_check(1, 0, 15):
242    crypto_secretstream_xchacha20poly1305_STATEBYTES = sodium.crypto_secretstream_xchacha20poly1305_statebytes()
243    crypto_secretstream_xchacha20poly1305_ABYTES = sodium.crypto_secretstream_xchacha20poly1305_abytes()
244    crypto_secretstream_xchacha20poly1305_HEADERBYTES = sodium.crypto_secretstream_xchacha20poly1305_headerbytes()
245    crypto_secretstream_xchacha20poly1305_KEYBYTES = sodium.crypto_secretstream_xchacha20poly1305_keybytes()
246    crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = sodium.crypto_secretstream_xchacha20poly1305_messagebytes_max()
247    crypto_secretstream_xchacha20poly1305_TAG_MESSAGE = sodium.crypto_secretstream_xchacha20poly1305_tag_message()
248    crypto_secretstream_xchacha20poly1305_TAG_PUSH = sodium.crypto_secretstream_xchacha20poly1305_tag_push()
249    crypto_secretstream_xchacha20poly1305_TAG_REKEY = sodium.crypto_secretstream_xchacha20poly1305_tag_rekey()
250    crypto_secretstream_xchacha20poly1305_TAG_FINAL = sodium.crypto_secretstream_xchacha20poly1305_tag_final()
251
252if sodium_version_check(1, 0, 18):
253    crypto_core_ristretto255_BYTES = sodium.crypto_core_ristretto255_bytes()
254    crypto_core_ristretto255_HASHBYTES = sodium.crypto_core_ristretto255_hashbytes()
255    crypto_core_ristretto255_SCALARBYTES = sodium.crypto_core_ristretto255_scalarbytes()
256    crypto_core_ristretto255_NONREDUCEDSCALARBYTES = sodium.crypto_core_ristretto255_nonreducedscalarbytes()
257    crypto_auth_hmacsha256_BYTES = sodium.crypto_auth_hmacsha256_bytes()
258    crypto_hash_sha256_STATEBYTES = sodium.crypto_hash_sha256_statebytes()
259
260sodium_init = sodium.sodium_init
261
262class CryptoSignState(ctypes.Structure):
263    _pack_ = 1
264    _fields_ = [
265        ('state', ctypes.c_uint64 * 8),
266        ('count', ctypes.c_uint64 * 2),
267        ('buf', ctypes.c_uint8 * 128)
268    ]
269
270def __check(code):
271    if code != 0:
272        raise ValueError
273
274
275def pad_buf(buf, length, name = 'buf'):
276    buflen = len(buf)
277    if buflen > length:
278        raise ValueError("Cannot pad %s (len: %d - expected %d or less)" % (name, buflen, length))
279
280    padding = length - buflen
281    if padding > 0:
282        return buf + b"\x00"*padding
283    else:
284        return buf
285
286# int crypto_scalarmult_base(unsigned char *q, const unsigned char *n);
287def crypto_scalarmult_base(n):
288    if n is None:
289        raise ValueError("invalid parameters")
290    if len(n) != crypto_scalarmult_SCALARBYTES: raise ValueError("truncated scalar")
291    q = ctypes.create_string_buffer(crypto_scalarmult_BYTES)
292    __check(sodium.crypto_scalarmult_base(q, n))
293    return q.raw
294
295def crypto_scalarmult_curve25519(n, p):
296    if None in (n,p):
297        raise ValueError("invalid parameters")
298    if len(n) != crypto_scalarmult_SCALARBYTES: raise ValueError("truncated scalar")
299    if len(p) != crypto_scalarmult_BYTES: raise ValueError("truncated point")
300    buf = ctypes.create_string_buffer(crypto_scalarmult_BYTES)
301    __check(sodium.crypto_scalarmult_curve25519(buf, n, p))
302    return buf.raw
303
304
305def crypto_scalarmult_curve25519_base(n):
306    if n is None:
307        raise ValueError("invalid parameters")
308    if len(n) != crypto_scalarmult_SCALARBYTES: raise ValueError("truncated scalar")
309    buf = ctypes.create_string_buffer(crypto_scalarmult_BYTES)
310    __check(sodium.crypto_scalarmult_curve25519_base(buf, n))
311    return buf.raw
312
313# crypto_stream_chacha20_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k)
314def crypto_stream_chacha20_xor(message, nonce, key):
315    if len(nonce) != crypto_stream_chacha20_NONCEBYTES: raise ValueError("truncated nonce")
316    if len(key) != crypto_stream_chacha20_KEYBYTES: raise ValueError("truncated key")
317
318    mlen = ctypes.c_longlong(len(message))
319
320    c = ctypes.create_string_buffer(len(message))
321
322    __check(sodium.crypto_stream_chacha20_xor(c, message, mlen, nonce, key))
323
324    return c.raw
325
326# 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)
327def crypto_stream_chacha20_xor_ic(message, nonce, initial_counter, key):
328    if len(nonce) != crypto_stream_chacha20_NONCEBYTES: raise ValueError("truncated nonce")
329    if len(key) != crypto_stream_chacha20_KEYBYTES: raise ValueError("truncated key")
330
331    mlen = ctypes.c_longlong(len(message))
332    ic = ctypes.c_uint64(initial_counter)
333
334    c = ctypes.create_string_buffer(len(message))
335
336    __check(sodium.crypto_stream_chacha20_xor_ic(c, message, mlen, nonce, ic, key))
337
338    return c.raw
339
340# crypto_stream_xchacha20_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k)
341def crypto_stream_xchacha20_xor(message, nonce, key):
342    if len(nonce) != crypto_stream_xchacha20_NONCEBYTES: raise ValueError("truncated nonce")
343    if len(key) != crypto_stream_xchacha20_KEYBYTES: raise ValueError("truncated key")
344
345    mlen = ctypes.c_longlong(len(message))
346
347    c = ctypes.create_string_buffer(len(message))
348
349    __check(sodium.crypto_stream_xchacha20_xor(c, message, mlen, nonce, key))
350
351    return c.raw
352
353# 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)
354def crypto_stream_xchacha20_xor_ic(message, nonce, initial_counter, key):
355    if len(nonce) != crypto_stream_xchacha20_NONCEBYTES: raise ValueError("truncated nonce")
356    if len(key) != crypto_stream_xchacha20_KEYBYTES: raise ValueError("truncated key")
357
358    mlen = ctypes.c_longlong(len(message))
359    ic = ctypes.c_uint64(initial_counter)
360
361    c = ctypes.create_string_buffer(len(message))
362
363    __check(sodium.crypto_stream_xchacha20_xor_ic(c, message, mlen, nonce, ic, key))
364
365    return c.raw
366
367# 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);
368def crypto_aead_chacha20poly1305_encrypt(message, ad, nonce, key):
369    if len(nonce) != crypto_aead_chacha20poly1305_NONCEBYTES: raise ValueError("truncated nonce")
370    if len(key) != crypto_aead_chacha20poly1305_KEYBYTES: raise ValueError("truncated key")
371
372    mlen = ctypes.c_ulonglong(len(message))
373    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
374
375    c = ctypes.create_string_buffer(mlen.value + 16)
376    clen = ctypes.c_ulonglong(0)
377
378    __check(sodium.crypto_aead_chacha20poly1305_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key))
379    return c.raw
380
381
382# 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)
383def crypto_aead_chacha20poly1305_decrypt(ciphertext, ad, nonce, key):
384    if len(nonce) != crypto_aead_chacha20poly1305_NONCEBYTES: raise ValueError("truncated nonce")
385    if len(key) != crypto_aead_chacha20poly1305_KEYBYTES: raise ValueError("truncated key")
386
387    m = ctypes.create_string_buffer(len(ciphertext) - 16)
388    mlen = ctypes.c_ulonglong(0)
389    clen = ctypes.c_ulonglong(len(ciphertext))
390    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
391    __check(sodium.crypto_aead_chacha20poly1305_decrypt(m, ctypes.byref(mlen), None, ciphertext, clen, ad, adlen, nonce, key))
392    return m.raw
393
394# 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)
395@sodium_version(1, 0, 9)
396def crypto_aead_chacha20poly1305_encrypt_detached(message, ad, nonce, key):
397    """ Return ciphertext, mac tag """
398    if len(nonce) != crypto_aead_chacha20poly1305_NONCEBYTES: raise ValueError("truncated nonce")
399    if len(key) != crypto_aead_chacha20poly1305_KEYBYTES: raise ValueError("truncated key")
400
401    mlen = ctypes.c_ulonglong(len(message))
402    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
403    c = ctypes.create_string_buffer(mlen.value)
404    maclen_p = ctypes.c_ulonglong(crypto_aead_chacha20poly1305_ABYTES)
405    mac = ctypes.create_string_buffer(maclen_p.value)
406
407    __check(sodium.crypto_aead_chacha20poly1305_encrypt_detached(c, mac, ctypes.byref(maclen_p), message, mlen, ad, adlen, None, nonce, key))
408    return c.raw, mac.raw
409
410# 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)
411@sodium_version(1, 0, 9)
412def crypto_aead_chacha20poly1305_decrypt_detached(ciphertext, mac, ad, nonce, key):
413    """ Return message if successful or -1 (ValueError) if not successful"""
414    if len(nonce) != crypto_aead_chacha20poly1305_NONCEBYTES: raise ValueError("truncated nonce")
415    if len(key) != crypto_aead_chacha20poly1305_KEYBYTES: raise ValueError("truncated key")
416    if len(mac) != crypto_aead_chacha20poly1305_ABYTES:
417        raise ValueError("mac length != %i" % crypto_aead_chacha20poly1305_ABYTES)
418
419    clen = ctypes.c_ulonglong(len(ciphertext))
420    m = ctypes.create_string_buffer(clen.value)
421    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
422    __check(sodium.crypto_aead_chacha20poly1305_decrypt_detached(m, None, ciphertext, clen, mac, ad, adlen, nonce, key))
423    return m.raw
424
425# 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)
426@sodium_version(1, 0, 4)
427def crypto_aead_chacha20poly1305_ietf_encrypt(message, ad, nonce, key):
428    if len(nonce) != crypto_aead_chacha20poly1305_ietf_NONCEBYTES: raise ValueError("truncated nonce")
429    if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key")
430
431    mlen = ctypes.c_ulonglong(len(message))
432    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
433    c = ctypes.create_string_buffer(mlen.value + 16)
434    clen = ctypes.c_ulonglong(0)
435
436    __check(sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, ctypes.byref(clen), message, mlen, ad, adlen, None, nonce, key))
437    return c.raw
438
439# 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)
440@sodium_version(1, 0, 4)
441def crypto_aead_chacha20poly1305_ietf_decrypt(ciphertext, ad, nonce, key):
442    if len(nonce) != crypto_aead_chacha20poly1305_ietf_NONCEBYTES: raise ValueError("truncated nonce")
443    if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key")
444
445    m = ctypes.create_string_buffer(len(ciphertext) - 16)
446    mlen = ctypes.c_ulonglong(0)
447    clen = ctypes.c_ulonglong(len(ciphertext))
448    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
449    __check(sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m, ctypes.byref(mlen), None, ciphertext, clen, ad, adlen, nonce, key))
450    return m.raw
451
452# 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)
453@sodium_version(1, 0, 9)
454def crypto_aead_chacha20poly1305_ietf_encrypt_detached(message, ad, nonce, key):
455    """ Return ciphertext, mac tag """
456    if len(nonce) != crypto_aead_chacha20poly1305_ietf_NONCEBYTES: raise ValueError("truncated nonce")
457    if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key")
458
459    mlen = ctypes.c_ulonglong(len(message))
460    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
461    c = ctypes.create_string_buffer(mlen.value)
462    maclen_p = ctypes.c_ulonglong(crypto_aead_chacha20poly1305_ietf_ABYTES)
463    mac = ctypes.create_string_buffer(maclen_p.value)
464
465    __check(sodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, ctypes.byref(maclen_p), message, mlen, ad, adlen, None, nonce, key))
466    return c.raw, mac.raw
467
468# 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)
469@sodium_version(1, 0, 9)
470def crypto_aead_chacha20poly1305_ietf_decrypt_detached(ciphertext, mac, ad, nonce, key):
471    """ Return message if successful or -1 (ValueError) if not successful"""
472    if len(nonce) != crypto_aead_chacha20poly1305_ietf_NONCEBYTES: raise ValueError("truncated nonce")
473    if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key")
474    if len(mac) != crypto_aead_chacha20poly1305_ietf_ABYTES:
475        raise ValueError("mac length != %i" % crypto_aead_chacha20poly1305_ietf_ABYTES)
476
477    clen = ctypes.c_ulonglong(len(ciphertext))
478    m = ctypes.create_string_buffer(clen.value)
479    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
480    __check(sodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, None, ciphertext, clen, mac, ad, adlen, nonce, key))
481    return m.raw
482
483#crypto_aead_xchacha20poly1305_ietf_encrypt(ciphertext, &ciphertext_len,
484#                                           message, message_len,
485#                                           additional_data, additional_data_len,
486#                                           null, nonce, key);
487@sodium_version(1, 0, 12)
488def crypto_aead_xchacha20poly1305_ietf_encrypt(message, ad, nonce, key):
489    if len(nonce) != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: raise ValueError("truncated nonce")
490    if len(key) != crypto_aead_xchacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key")
491    mlen = ctypes.c_ulonglong(len(message))
492    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
493    c = ctypes.create_string_buffer(mlen.value + 16)
494    clen = ctypes.c_ulonglong(0)
495
496    __check(sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(c, ctypes.byref(clen),
497                                                             message, mlen,
498                                                             ad, adlen,
499                                                             None, nonce, key))
500    return c.raw
501
502#crypto_aead_xchacha20poly1305_ietf_decrypt(decrypted, &decrypted_len,
503#                                           null,
504#                                           ciphertext, ciphertext_len,
505#                                           additional_data, additional_data_len,
506#                                           nonce, key);
507@sodium_version(1, 0, 12)
508def crypto_aead_xchacha20poly1305_ietf_decrypt(ciphertext, ad, nonce, key):
509    if len(nonce) != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: raise ValueError("truncated nonce")
510    if len(key) != crypto_aead_xchacha20poly1305_ietf_KEYBYTES: raise ValueError("truncated key")
511
512    m = ctypes.create_string_buffer(len(ciphertext) - 16)
513    mlen = ctypes.c_ulonglong(0)
514    clen = ctypes.c_ulonglong(len(ciphertext))
515    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
516    __check(sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(m, ctypes.byref(mlen),
517                                                              None,
518                                                              ciphertext, clen,
519                                                              ad, adlen,
520                                                              nonce, key))
521    return m.raw
522
523# crypto_auth(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *k)
524def crypto_auth(m, k):
525    if m is None or k is None:
526        raise ValueError("invalid parameters")
527    if len(k) != crypto_auth_KEYBYTES:
528        raise ValueError("invalid key")
529    buf = ctypes.create_string_buffer(crypto_auth_BYTES)
530    __check(sodium.crypto_auth(buf, m, ctypes.c_ulonglong(len(m)), k))
531    return buf.raw
532
533# crypto_auth_verify(const unsigned char *h, const unsigned char *in, unsigned long long inlen, const unsigned char *k)
534def crypto_auth_verify(h, m, k):
535    if h is None or m is None or k is None:
536        raise ValueError("invalid parameters")
537    if len(k) != crypto_auth_KEYBYTES:
538        raise ValueError("invalid key")
539    if len(h) != crypto_auth_BYTES:
540        raise ValueError("invalid tag")
541    __check(sodium.crypto_auth_verify(h, m, ctypes.c_ulonglong(len(m)), k))
542
543# crypto_generichash(unsigned char *out, size_t outlen, const unsigned char *in, unsigned long long inlen, const unsigned char *key, size_t keylen)
544@encode_strings
545def crypto_generichash(m, k=b'', outlen=crypto_generichash_BYTES):
546    buf = ctypes.create_string_buffer(outlen)
547    __check(sodium.crypto_generichash(buf, ctypes.c_size_t(outlen), m, ctypes.c_ulonglong(len(m)), k, ctypes.c_size_t(len(k))))
548    return buf.raw
549
550
551# crypto_generichash_init(crypto_generichash_state *state, const unsigned char *key, const size_t keylen, const size_t outlen);
552@encode_strings
553def crypto_generichash_init(outlen=crypto_generichash_BYTES, k=b''):
554    state = ctypes.create_string_buffer(crypto_generichash_STATEBYTES)
555    __check(sodium.crypto_generichash_init(ctypes.byref(state), k, ctypes.c_size_t(len(k)), ctypes.c_size_t(outlen)))
556    return state
557
558
559# crypto_generichash_update(crypto_generichash_state *state, const unsigned char *in, unsigned long long inlen);
560@encode_strings
561def crypto_generichash_update(state, m):
562    if len(state) != crypto_generichash_STATEBYTES: raise ValueError("invalid state")
563    __check(sodium.crypto_generichash_update(ctypes.byref(state), m, ctypes.c_ulonglong(len(m))))
564    return state
565
566
567# crypto_generichash_final(crypto_generichash_state *state, unsigned char *out, const size_t outlen);
568def crypto_generichash_final(state, outlen=crypto_generichash_BYTES):
569    if len(state) != crypto_generichash_STATEBYTES: raise ValueError("invalid state")
570    buf = ctypes.create_string_buffer(outlen)
571    __check(sodium.crypto_generichash_final(ctypes.byref(state), buf, ctypes.c_size_t(outlen)))
572    return buf.raw
573
574def crypto_generichash_blake2b_salt_personal(message, outlen = crypto_generichash_blake2b_BYTES, key = b'', salt = b'', personal = b''):
575    keylen   = len(key)
576
577    if keylen != 0 and not crypto_generichash_blake2b_BYTES_MIN <= keylen <= crypto_generichash_blake2b_KEYBYTES_MAX:
578        raise ValueError("%d <= len(key) <= %d - %d received" % (crypto_generichash_blake2b_BYTES_MIN, crypto_generichash_blake2b_KEYBYTES_MAX, keylen))
579
580    salt     = pad_buf(salt, crypto_generichash_blake2b_SALTBYTES, 'salt')
581    personal = pad_buf(personal, crypto_generichash_blake2b_PERSONALBYTES, 'personal')
582
583    buf      = ctypes.create_string_buffer(outlen)
584    outlen   = ctypes.c_size_t(outlen)
585    inlen    = ctypes.c_ulonglong(len(message))
586    keylen   = ctypes.c_size_t(keylen)
587
588    __check(sodium.crypto_generichash_blake2b_salt_personal(buf, outlen, message, inlen, key, keylen, salt, personal))
589    return buf.raw
590
591
592def randombytes(size):
593    buf = ctypes.create_string_buffer(size)
594    sodium.randombytes(buf, ctypes.c_ulonglong(size))
595    return buf.raw
596
597
598def crypto_box_keypair():
599    pk = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES)
600    sk = ctypes.create_string_buffer(crypto_box_SECRETKEYBYTES)
601    __check(sodium.crypto_box_keypair(pk, sk))
602    return pk.raw, sk.raw
603
604# int crypto_box_seed_keypair(unsigned char *pk, unsigned char *sk,
605#                                const unsigned char *seed);
606def crypto_box_seed_keypair(seed):
607    if seed is None:
608        raise ValueError("invalid parameters")
609    if len(seed) != crypto_box_SEEDBYTES: raise ValueError("invalid seed size")
610
611    pk = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES)
612    sk = ctypes.create_string_buffer(crypto_box_SECRETKEYBYTES)
613    __check(sodium.crypto_box_seed_keypair(pk, sk, seed))
614    return pk.raw, sk.raw
615
616def crypto_box_beforenm(pk, sk):
617    if pk is None or sk is None:
618        raise ValueError("invalid parameters")
619    if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size")
620    if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size")
621    c = ctypes.create_string_buffer(crypto_secretbox_KEYBYTES)
622    __check(sodium.crypto_box_beforenm(c, pk, sk))
623    return c.raw
624
625def crypto_box(msg, nonce, pk, sk):
626    if None in (msg, nonce, pk, sk):
627        raise ValueError("invalid parameters")
628    if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size")
629    if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size")
630    if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size")
631    c = ctypes.create_string_buffer(crypto_box_MACBYTES + len(msg))
632    __check(sodium.crypto_box_easy(c, msg, ctypes.c_ulonglong(len(msg)), nonce, pk, sk))
633    return c.raw
634
635def crypto_box_afternm(msg, nonce, k):
636    if None in (msg, nonce, k):
637        raise ValueError("invalid parameters")
638    if len(k) != crypto_box_BEFORENMBYTES: raise ValueError("k incorrect size")
639    if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size")
640    c = ctypes.create_string_buffer(crypto_box_MACBYTES + len(msg))
641    __check(sodium.crypto_box_easy_afternm(c, msg, ctypes.c_ulonglong(len(msg)), nonce, k))
642    return c.raw
643
644def crypto_box_open(c, nonce, pk, sk):
645    if None in (c, nonce, pk, sk):
646        raise ValueError("invalid parameters")
647    if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size")
648    if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size")
649    if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size")
650    msg = ctypes.create_string_buffer(len(c) - crypto_box_MACBYTES)
651    __check(sodium.crypto_box_open_easy(msg, c, ctypes.c_ulonglong(len(c)), nonce, pk, sk))
652    return msg.raw
653
654def crypto_box_open_afternm(c, nonce, k):
655    if None in (c, nonce, k):
656        raise ValueError("invalid parameters")
657    if len(k) != crypto_box_BEFORENMBYTES: raise ValueError("k incorrect size")
658    if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size")
659    msg = ctypes.create_string_buffer(len(c) - crypto_box_MACBYTES)
660    __check(sodium.crypto_box_open_easy_afternm(msg, c, ctypes.c_ulonglong(len(c)), nonce, k))
661    return msg.raw
662
663def crypto_secretbox(msg, nonce, k):
664    if None in (msg, nonce, k):
665        raise ValueError("invalid parameters")
666    if len(k) != crypto_secretbox_KEYBYTES: raise ValueError("k incorrect size")
667    if len(nonce) != crypto_secretbox_NONCEBYTES: raise ValueError("nonce incorrect size")
668    padded = b"\x00" * crypto_secretbox_ZEROBYTES + msg
669    c = ctypes.create_string_buffer(len(padded))
670    __check(sodium.crypto_secretbox(c, padded, ctypes.c_ulonglong(len(padded)), nonce, k))
671    return c.raw[crypto_secretbox_BOXZEROBYTES:]
672
673
674def crypto_secretbox_open(c, nonce, k):
675    if None in (c, nonce, k):
676        raise ValueError("invalid parameters")
677    if len(k) != crypto_secretbox_KEYBYTES: raise ValueError("k incorrect size")
678    if len(nonce) != crypto_secretbox_NONCEBYTES: raise ValueError("nonce incorrect size")
679    padded = b"\x00" * crypto_secretbox_BOXZEROBYTES + c
680    msg = ctypes.create_string_buffer(len(padded))
681    __check(sodium.crypto_secretbox_open(msg, padded, ctypes.c_ulonglong(len(padded)), nonce, k))
682    return msg.raw[crypto_secretbox_ZEROBYTES:]
683
684# int crypto_box_seal(unsigned char *c, const unsigned char *m,
685#                    unsigned long long mlen, const unsigned char *pk);
686
687@sodium_version(1, 0, 3)
688def crypto_box_seal(msg, k):
689    if msg is None or k is None:
690        raise ValueError("invalid parameters")
691    if len(k) != crypto_box_PUBLICKEYBYTES: raise ValueError("k incorrect size")
692    c = ctypes.create_string_buffer(len(msg)+crypto_box_SEALBYTES)
693    __check(sodium.crypto_box_seal(c, msg, ctypes.c_ulonglong(len(msg)), k))
694    return c.raw
695
696# int crypto_box_seal_open(unsigned char *m, const unsigned char *c,
697#                         unsigned long long clen,
698#                         const unsigned char *pk, const unsigned char *sk);
699
700@sodium_version(1, 0, 3)
701def crypto_box_seal_open(c, pk, sk):
702    if None in (c, pk, sk):
703        raise ValueError("invalid parameters")
704    if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size")
705    if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size")
706    msg = ctypes.create_string_buffer(len(c)-crypto_box_SEALBYTES)
707    __check(sodium.crypto_box_seal_open(msg, c, ctypes.c_ulonglong(len(c)), pk, sk))
708    return msg.raw
709
710# int crypto_secretbox_detached(unsigned char *c, unsigned char *mac,
711#                              	const unsigned char *m,
712#                              	unsigned long long mlen,
713#                              	const unsigned char *n,
714#                              	const unsigned char *k);
715
716def crypto_secretbox_detached(msg, nonce, k):
717    if None in (msg, nonce, k): raise ValueError("invalid parameters")
718    if len(k) != crypto_secretbox_KEYBYTES: raise ValueError("key incorrect size")
719    if len(nonce) != crypto_secretbox_NONCEBYTES: raise ValueError("nonce incorrect size")
720    c = ctypes.create_string_buffer(len(msg))
721    mac = ctypes.create_string_buffer(crypto_secretbox_MACBYTES)
722    __check(sodium.crypto_secretbox_detached(c, mac, msg, ctypes.c_ulonglong(len(msg)), nonce, k))
723    return c.raw, mac.raw
724
725
726# int crypto_secretbox_open_detached(unsigned char *m,
727#                                   const unsigned char *c,
728#                                   const unsigned char *mac,
729#                                   unsigned long long clen,
730#                                   const unsigned char *n,
731#                                   const unsigned char *k);
732
733def crypto_secretbox_open_detached(c, mac, nonce, k):
734    if None in (c, mac, nonce, k):
735        raise ValueError("invalid parameters")
736    if len(k) != crypto_secretbox_KEYBYTES: raise ValueError("key incorrect size")
737    if len(nonce) != crypto_secretbox_NONCEBYTES: raise ValueError("nonce incorrect size")
738    msg = ctypes.create_string_buffer(len(c))
739    __check(sodium.crypto_secretbox_open_detached(msg, c, mac, ctypes.c_ulonglong(len(c)), nonce, k))
740    return msg.raw
741
742
743# int crypto_box_detached(unsigned char *c, unsigned char *mac,
744#                        const unsigned char *m, unsigned long long mlen,
745#                        const unsigned char *n, const unsigned char *pk,
746#                        const unsigned char *sk);
747
748def crypto_box_detached(msg, nonce, pk, sk):
749    if None in (msg, nonce, pk, sk): raise ValueError("invalid parameters")
750    if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size")
751    if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size")
752    if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size")
753    c = ctypes.create_string_buffer(len(msg))
754    mac = ctypes.create_string_buffer(crypto_box_MACBYTES)
755    __check(sodium.crypto_box_detached(c, mac, msg, ctypes.c_ulonglong(len(msg)), nonce, pk, sk))
756    return c.raw, mac.raw
757
758# int crypto_box_open_detached(unsigned char *m, const unsigned char *c,
759#                             const unsigned char *mac,
760#                             unsigned long long clen,
761#                             const unsigned char *n,
762#                             const unsigned char *pk,
763#                             const unsigned char *sk);
764
765def crypto_box_open_detached(c, mac, nonce, pk, sk):
766    if None in (c, mac, nonce, pk, sk):
767        raise ValueError("invalid parameters")
768    if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("pk incorrect size")
769    if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("sk incorrect size")
770    if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("nonce incorrect size")
771    msg = ctypes.create_string_buffer(len(c))
772    __check(sodium.crypto_box_open_detached(msg, c, mac, ctypes.c_ulonglong(len(c)), nonce, pk, sk))
773    return msg.raw
774
775
776# void crypto_secretstream_xchacha20poly1305_keygen (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
777@sodium_version(1, 0, 15)
778def crypto_secretstream_xchacha20poly1305_keygen():
779    key = ctypes.create_string_buffer(crypto_secretstream_xchacha20poly1305_KEYBYTES)
780    sodium.crypto_secretstream_xchacha20poly1305_keygen(ctypes.byref(key))
781    return key.raw
782
783
784# int crypto_secretstream_xchacha20poly1305_init_push(crypto_secretstream_xchacha20poly1305_state *state,
785#                                                     unsigned char out[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
786#                                                     const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
787@sodium_version(1, 0, 15)
788def crypto_secretstream_xchacha20poly1305_init_push(key):
789    if key == None:
790        raise ValueError("invalid parameters")
791    if not (len(key) == crypto_secretstream_xchacha20poly1305_KEYBYTES): raise ValueError("Truncated key")
792
793    state  = ctypes.create_string_buffer(crypto_secretstream_xchacha20poly1305_STATEBYTES)
794    header = ctypes.create_string_buffer(crypto_secretstream_xchacha20poly1305_HEADERBYTES)
795    __check(sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, key))
796    return state.raw, header.raw
797
798# int crypto_secretstream_xchacha20poly1305_init_pull(crypto_secretstream_xchacha20poly1305_state *state,
799#                                                     const unsigned char in[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
800#                                                     const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
801@sodium_version(1, 0, 15)
802def crypto_secretstream_xchacha20poly1305_init_pull(header, key):
803    if None in (header, key):
804        raise ValueError("invalid parameters")
805    if not (len(header) == crypto_secretstream_xchacha20poly1305_HEADERBYTES): raise ValueError("Truncated header")
806    if not (len(key) == crypto_secretstream_xchacha20poly1305_KEYBYTES): raise ValueError("Truncated key")
807
808    state  = ctypes.create_string_buffer(crypto_secretstream_xchacha20poly1305_STATEBYTES)
809    __check(sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, key))
810    return state.raw
811
812#void crypto_secretstream_xchacha20poly1305_rekey (crypto_secretstream_xchacha20poly1305_state *state)
813@sodium_version(1, 0, 15)
814def crypto_secretstream_xchacha20poly1305_rekey(state):
815    if state == None:
816        raise ValueError("invalid parameters")
817    if not (len(state) == crypto_secretstream_xchacha20poly1305_STATEBYTES): raise ValueError("Truncated state")
818
819    sodium.crypto_secretstream_xchacha20poly1305_rekey(state)
820
821#int crypto_secretstream_xchacha20poly1305_push (crypto_secretstream_xchacha20poly1305_state *state,
822#                                                unsigned char *out,
823#                                                unsigned long long *outlen_p,
824#                                                const unsigned char *m,
825#                                                unsigned long long mlen,
826#                                                const unsigned char *ad,
827#                                                unsigned long long adlen,
828#                                                unsigned char tag)
829
830@sodium_version(1, 0, 15)
831def crypto_secretstream_xchacha20poly1305_push(state, message, ad, tag):
832    if None in (state, message):
833        raise ValueError("invalid parameters")
834    if not (len(state) == crypto_secretstream_xchacha20poly1305_STATEBYTES): raise ValueError("Truncated state")
835
836    mlen = ctypes.c_ulonglong(len(message))
837    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
838    c = ctypes.create_string_buffer(mlen.value + crypto_secretstream_xchacha20poly1305_ABYTES)
839    clen = ctypes.c_ulonglong(0)
840
841    __check(sodium.crypto_secretstream_xchacha20poly1305_push(
842                                                                state,                  #  crypto_secretstream_xchacha20poly1305_state *state,
843                                                                c,                      #  unsigned char *out
844                                                                ctypes.byref(clen),     #  unsigned long long *outlen_p,
845                                                                message,                #  const unsigned char *m,
846                                                                mlen,                   #  unsigned long long mlen,
847                                                                ad,                     #  const unsigned char *ad,
848                                                                adlen,                  #  unsigned long long adlen,
849                                                                tag))                   #  unsigned char tag)
850    return c.raw
851
852
853#crypto_secretstream_xchacha20poly1305_pull (crypto_secretstream_xchacha20poly1305_state *state,
854#                                            unsigned char *m,
855#                                            unsigned long long *mlen_p,
856#                                            unsigned char *tag_p,
857#                                            const unsigned char *in,
858#                                            unsigned long long inlen,
859#                                            const unsigned char *ad,
860#                                            unsigned long long adlen)
861@sodium_version(1, 0, 15)
862def crypto_secretstream_xchacha20poly1305_pull(state, ciphertext, ad):
863    if None in (state, ciphertext):
864        raise ValueError("invalid parameters")
865    if not (len(state) == crypto_secretstream_xchacha20poly1305_STATEBYTES): raise ValueError("Truncated state")
866    if len(ciphertext) < crypto_secretstream_xchacha20poly1305_ABYTES:
867        raise ValueError("truncated cyphertext")
868
869    m = ctypes.create_string_buffer(len(ciphertext) - crypto_secretstream_xchacha20poly1305_ABYTES)
870    mlen = ctypes.c_ulonglong(0)
871    tag  = ctypes.c_ubyte(0)
872    clen = ctypes.c_ulonglong(len(ciphertext))
873    adlen = ctypes.c_ulonglong(len(ad)) if ad is not None else ctypes.c_ulonglong(0)
874
875    __check(sodium.crypto_secretstream_xchacha20poly1305_pull(
876                                                                state,
877                                                                m,                   # char *m,
878                                                                ctypes.byref(mlen),  # long long *mlen_p,
879                                                                ctypes.byref(tag),   # char *tag_p,
880                                                                ciphertext,          # unsigned char *in,
881                                                                clen,                # long long inlen,
882                                                                ad,                  # unsigned char *ad,
883                                                                adlen                # long long adlen)
884                                                                ))
885    return m.raw, tag.value
886
887def crypto_sign_keypair():
888    pk = ctypes.create_string_buffer(crypto_sign_PUBLICKEYBYTES)
889    sk = ctypes.create_string_buffer(crypto_sign_SECRETKEYBYTES)
890    __check(sodium.crypto_sign_keypair(pk, sk))
891    return pk.raw, sk.raw
892
893
894def crypto_sign_seed_keypair(seed):
895    if len(seed) != crypto_sign_SEEDBYTES: raise ValueError("invalid seed size")
896    pk = ctypes.create_string_buffer(crypto_sign_PUBLICKEYBYTES)
897    sk = ctypes.create_string_buffer(crypto_sign_SECRETKEYBYTES)
898    __check(sodium.crypto_sign_seed_keypair(pk, sk, seed))
899    return pk.raw, sk.raw
900
901def crypto_sign(m, sk):
902    if m is None or sk is None:
903        raise ValueError("invalid parameters")
904    if not (len(sk) == crypto_sign_SECRETKEYBYTES): raise ValueError('Truncated secret key')
905
906    smsg = ctypes.create_string_buffer(len(m) + crypto_sign_BYTES)
907    smsglen = ctypes.c_ulonglong()
908    __check(sodium.crypto_sign(smsg, ctypes.byref(smsglen), m, ctypes.c_ulonglong(len(m)), sk))
909    return smsg.raw
910
911
912def crypto_sign_detached(m, sk):
913    if m is None or sk is None:
914        raise ValueError("invalid parameters")
915    if not (len(sk) == crypto_sign_SECRETKEYBYTES): raise ValueError('Truncated secret key')
916    sig = ctypes.create_string_buffer(crypto_sign_BYTES)
917    # second parm is for output of signature len (optional, ignored if NULL)
918    __check(sodium.crypto_sign_detached(sig, ctypes.c_void_p(0), m, ctypes.c_ulonglong(len(m)), sk))
919    return sig.raw
920
921
922def crypto_sign_open(sm, pk):
923    if sm is None or pk is None:
924        raise ValueError("invalid parameters")
925    if not (len(pk) == crypto_sign_PUBLICKEYBYTES): raise ValueError('Truncated public key')
926    msg = ctypes.create_string_buffer(len(sm))
927    msglen = ctypes.c_ulonglong()
928    __check(sodium.crypto_sign_open(msg, ctypes.byref(msglen), sm, ctypes.c_ulonglong(len(sm)), pk))
929    return msg.raw[:msglen.value]
930
931
932def crypto_sign_verify_detached(sig, msg, pk):
933    if None in (sig, msg, pk):
934        raise ValueError
935    if len(sig) != crypto_sign_BYTES:
936        raise ValueError("invalid sign")
937    if not (len(pk) == crypto_sign_PUBLICKEYBYTES): raise ValueError('Truncated public key')
938    __check(sodium.crypto_sign_verify_detached(sig, msg, ctypes.c_ulonglong(len(msg)), pk))
939
940
941# crypto_sign_init(crypto_sign_state *state);
942@sodium_version(1, 0, 12)
943def crypto_sign_init():
944    state = CryptoSignState()
945    __check(sodium.crypto_sign_init(ctypes.byref(state)))
946    return state
947
948
949# crypto_sign_update(crypto_sign_state *state, const unsigned char *m, unsigned long long mlen);
950@sodium_version(1, 0, 12)
951def crypto_sign_update(state, m):
952    if(not isinstance(state, CryptoSignState)):
953        raise TypeError("state is not CryptoSignState")
954    if m is None:
955        raise ValueError("invalid parameters")
956    __check(sodium.crypto_sign_update(ctypes.byref(state), m, ctypes.c_ulonglong(len(m))))
957
958
959# crypto_sign_final_create(crypto_sign_state *state, unsigned char *sig, unsigned long long *siglen_p, const unsigned char *sk);
960@sodium_version(1, 0, 12)
961def crypto_sign_final_create(state, sk):
962    if(not isinstance(state, CryptoSignState)):
963        raise TypeError("state is not CryptoSignState")
964    if sk is None:
965        raise ValueError("invalid parameters")
966    if len(sk) != crypto_sign_SECRETKEYBYTES:
967        raise ValueError("invalid secret key")
968    buf = ctypes.create_string_buffer(crypto_sign_BYTES)
969    __check(sodium.crypto_sign_final_create(ctypes.byref(state), buf, ctypes.c_void_p(0), sk))
970    return buf.raw
971
972
973# crypto_sign_final_verify(crypto_sign_state *state, unsigned char *sig, const unsigned char *sk);
974@sodium_version(1, 0, 12)
975def crypto_sign_final_verify(state, sig, pk):
976    if(not isinstance(state, CryptoSignState)):
977        raise TypeError("state is not CryptoSignState")
978    if None in (sig, pk):
979        raise ValueError("invalid parameters")
980    if len(sig) != crypto_sign_BYTES:
981        raise ValueError("invalid signature")
982    if len(pk) != crypto_sign_PUBLICKEYBYTES:
983        raise ValueError("invalid public key")
984    __check(sodium.crypto_sign_final_verify(ctypes.byref(state), sig, pk))
985
986
987# int crypto_stream_salsa20(unsigned char *c, unsigned long long clen,
988#                           const unsigned char *n, const unsigned char *k);
989def crypto_stream(cnt, nonce=None, key=None):
990    res = ctypes.create_string_buffer(cnt)
991    if not nonce:
992        nonce = randombytes(crypto_stream_NONCEBYTES)
993    if not key:
994        key = randombytes(crypto_stream_KEYBYTES)
995    __check(sodium.crypto_stream(res, ctypes.c_ulonglong(cnt), nonce, key))
996    return res.raw
997
998
999# crypto_stream_salsa20_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen,
1000#                           const unsigned char *n, const unsigned char *k)
1001def crypto_stream_xor(msg, cnt, nonce, key):
1002    res = ctypes.create_string_buffer(cnt)
1003    if len(nonce) != crypto_stream_NONCEBYTES: raise ValueError("invalid nonce")
1004    if len(key) != crypto_stream_KEYBYTES: raise ValueError("invalid key")
1005    __check(sodium.crypto_stream_xor(res, msg, ctypes.c_ulonglong(cnt), nonce, key))
1006    return res.raw
1007
1008
1009def crypto_sign_pk_to_box_pk(pk):
1010    if pk is None:
1011        raise ValueError
1012    if not (len(pk) == crypto_sign_PUBLICKEYBYTES): raise ValueError('Truncated public key')
1013    res = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES)
1014    __check(sodium.crypto_sign_ed25519_pk_to_curve25519(ctypes.byref(res), pk))
1015    return res.raw
1016
1017
1018def crypto_sign_sk_to_box_sk(sk):
1019    if sk is None:
1020        raise ValueError
1021    if not (len(sk) == crypto_sign_SECRETKEYBYTES): raise ValueError('Truncated secret key')
1022    res = ctypes.create_string_buffer(crypto_box_SECRETKEYBYTES)
1023    __check(sodium.crypto_sign_ed25519_sk_to_curve25519(ctypes.byref(res), sk))
1024    return res.raw
1025
1026def crypto_sign_sk_to_seed(sk):
1027    if sk is None:
1028        raise ValueError
1029    if not (len(sk) == crypto_sign_SECRETKEYBYTES): raise ValueError('Truncated secret key')
1030    seed = ctypes.create_string_buffer(crypto_sign_SEEDBYTES)
1031    __check(sodium.crypto_sign_ed25519_sk_to_seed(ctypes.byref(seed), sk))
1032    return seed.raw
1033
1034# int crypto_pwhash(unsigned char * const out,
1035#                   unsigned long long outlen,
1036#                   const char * const passwd,
1037#                   unsigned long long passwdlen,
1038#                   const unsigned char * const salt,
1039#                   unsigned long long opslimit,
1040#                   size_t memlimit, int alg);
1041@sodium_version(1, 0, 9)
1042@encode_strings
1043def crypto_pwhash(outlen, passwd, salt, opslimit, memlimit, alg=crypto_pwhash_ALG_DEFAULT):
1044    if None in (outlen, passwd, salt, opslimit, memlimit):
1045        raise ValueError("invalid parameters")
1046    if len(salt) != crypto_pwhash_SALTBYTES: raise ValueError("invalid salt")
1047    if not (crypto_pwhash_BYTES_MIN <= outlen <= crypto_pwhash_BYTES_MAX): raise ValueError("invalid hash len")
1048    if not (crypto_pwhash_PASSWD_MIN <= len(passwd) <= crypto_pwhash_PASSWD_MAX): raise ValueError("invalid passwd len")
1049    if not (crypto_pwhash_OPSLIMIT_MIN <= opslimit <= crypto_pwhash_OPSLIMIT_MAX): raise ValueError("invalid opslimit")
1050    if not (crypto_pwhash_MEMLIMIT_MIN <= memlimit <= crypto_pwhash_MEMLIMIT_MAX): raise ValueError("invalid memlimit")
1051
1052    out = ctypes.create_string_buffer(outlen)
1053    __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)))
1054    return out.raw
1055
1056# int crypto_pwhash_str(char out[crypto_pwhash_STRBYTES],
1057#                       const char * const passwd,
1058#                       unsigned long long passwdlen,
1059#                       unsigned long long opslimit,
1060#                       size_t memlimit);
1061@sodium_version(1, 0, 9)
1062@encode_strings
1063def crypto_pwhash_str(passwd, opslimit, memlimit):
1064    if None in (passwd, opslimit, memlimit):
1065        raise ValueError("invalid parameters")
1066    if not (crypto_pwhash_PASSWD_MIN <= len(passwd) <= crypto_pwhash_PASSWD_MAX): raise ValueError("invalid passwd len")
1067    if not (crypto_pwhash_OPSLIMIT_MIN <= opslimit <= crypto_pwhash_OPSLIMIT_MAX): raise ValueError("invalid opslimit")
1068    if not (crypto_pwhash_MEMLIMIT_MIN <= memlimit <= crypto_pwhash_MEMLIMIT_MAX): raise ValueError("invalid memlimit")
1069    out = ctypes.create_string_buffer(crypto_pwhash_STRBYTES)
1070    __check(sodium.crypto_pwhash_str(ctypes.byref(out), passwd, ctypes.c_ulonglong(len(passwd)), ctypes.c_ulonglong(opslimit), ctypes.c_size_t(memlimit)))
1071    return out.raw
1072
1073# int crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES],
1074#                              const char * const passwd,
1075#                              unsigned long long passwdlen);
1076@sodium_version(1, 0, 9)
1077@encode_strings
1078def crypto_pwhash_str_verify(pstr, passwd):
1079    if None in (pstr, passwd) or len(pstr) != crypto_pwhash_STRBYTES:
1080        raise ValueError("invalid parameters")
1081    if not (crypto_pwhash_PASSWD_MIN < len(passwd) <= crypto_pwhash_PASSWD_MAX): raise ValueError("invalid passwd len")
1082    return sodium.crypto_pwhash_str_verify(pstr, passwd, ctypes.c_ulonglong(len(passwd))) == 0
1083
1084# int crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
1085#                                        unsigned long long outlen,
1086#                                        const char * const passwd,
1087#                                        unsigned long long passwdlen,
1088#                                        const unsigned char * const salt,
1089#                                        unsigned long long opslimit,
1090#                                        size_t memlimit);
1091def crypto_pwhash_scryptsalsa208sha256(outlen, passwd, salt, opslimit, memlimit):
1092    if None in (outlen, passwd, salt, opslimit, memlimit):
1093        raise ValueError
1094
1095    if len(salt) != crypto_pwhash_scryptsalsa208sha256_SALTBYTES: raise ValueError("invalid salt")
1096    if not (crypto_pwhash_scryptsalsa208sha256_BYTES_MIN <= outlen <= crypto_pwhash_scryptsalsa208sha256_BYTES_MAX): raise ValueError("invalid hash len")
1097    if not (crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN <= len(passwd) <= crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX): raise ValueError("invalid passwd len")
1098    if not (crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN <= opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX): raise ValueError("invalid opslimit")
1099    if not (crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN <= memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX): raise ValueError("invalid memlimit")
1100
1101    out = ctypes.create_string_buffer(outlen)
1102    __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)))
1103    return out.raw
1104
1105# int crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
1106#                                            const char * const passwd,
1107#                                            unsigned long long passwdlen,
1108#                                            unsigned long long opslimit,
1109#                                            size_t memlimit);
1110def crypto_pwhash_scryptsalsa208sha256_str(passwd, opslimit, memlimit):
1111    if None in (passwd, opslimit, memlimit):
1112        raise ValueError
1113    if not (crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN <= len(passwd) <= crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX): raise ValueError("invalid passwd len")
1114    if not (crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN <= opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX): raise ValueError("invalid opslimit")
1115    if not (crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN <= memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX): raise ValueError("invalid memlimit")
1116    out = ctypes.create_string_buffer(crypto_pwhash_scryptsalsa208sha256_STRBYTES)
1117    __check(sodium.crypto_pwhash_scryptsalsa208sha256_str(out, passwd, ctypes.c_ulonglong(len(passwd)), ctypes.c_ulonglong(opslimit), ctypes.c_size_t(memlimit)))
1118    return out.raw
1119
1120#int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
1121#                                                  const char * const passwd,
1122#                                                  unsigned long long passwdlen);
1123def crypto_pwhash_scryptsalsa208sha256_str_verify(stored, passwd):
1124    if stored is None or passwd is None:
1125       raise ValueError
1126    if not (crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN <= len(passwd) <= crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX): raise ValueError("invalid passwd len")
1127    if len(stored) != crypto_pwhash_scryptsalsa208sha256_STRBYTES: raise ValueError('invalid str size')
1128
1129    __check(sodium.crypto_pwhash_scryptsalsa208sha256_str_verify(stored, passwd, ctypes.c_ulonglong(len(passwd))))
1130
1131# int crypto_sign_ed25519_sk_to_pk(unsigned char *pk, const unsigned char *sk)
1132def crypto_sign_sk_to_pk(sk):
1133    if sk is None or len(sk) != crypto_sign_ed25519_SECRETKEYBYTES:
1134        raise ValueError
1135    res = ctypes.create_string_buffer(crypto_sign_ed25519_PUBLICKEYBYTES)
1136    __check(sodium.crypto_sign_ed25519_sk_to_pk(ctypes.byref(res), sk))
1137    return res.raw
1138
1139# int crypto_hash_sha256(unsigned char *out, const unsigned char *in,
1140#                       unsigned long long inlen);
1141def crypto_hash_sha256(message):
1142    if message is None:
1143        raise ValueError("invalid parameters")
1144    out = ctypes.create_string_buffer(crypto_hash_sha256_BYTES)
1145    __check(sodium.crypto_hash_sha256(out, message, ctypes.c_ulonglong(len(message))))
1146    return out.raw
1147
1148# int crypto_hash_sha512(unsigned char *out, const unsigned char *in,
1149#                       unsigned long long inlen);
1150def crypto_hash_sha512(message):
1151    if message is None:
1152        raise ValueError("invalid parameters")
1153    out = ctypes.create_string_buffer(crypto_hash_sha512_BYTES)
1154    __check(sodium.crypto_hash_sha512(out, message, ctypes.c_ulonglong(len(message))))
1155    return out.raw
1156
1157# int crypto_hash_sha512_init(crypto_hash_sha512_state *state)
1158def crypto_hash_sha512_init():
1159    state = ctypes.create_string_buffer(crypto_hash_sha512_STATEBYTES)
1160    __check(sodium.crypto_hash_sha512_init(state))
1161    return state
1162
1163# int crypto_hash_sha512_update(crypto_hash_sha512_state *state, const unsigned char *in, unsigned long long inlen)
1164def crypto_hash_sha512_update(state, data):
1165    __check(sodium.crypto_hash_sha512_update(state,data,ctypes.c_ulonglong(len(data))))
1166    return state
1167
1168# int crypto_hash_sha512_final(crypto_hash_sha512_state *state, unsigned char *out)
1169def crypto_hash_sha512_final(state):
1170    out = ctypes.create_string_buffer(crypto_hash_sha512_BYTES)
1171    __check(sodium.crypto_hash_sha512_final(state, out))
1172    return out.raw
1173
1174# int crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
1175#                      unsigned char sk[crypto_kx_SECRETKEYBYTES]);
1176@sodium_version(1, 0, 12)
1177def crypto_kx_keypair():
1178    pk = ctypes.create_string_buffer(crypto_kx_PUBLICKEYBYTES)
1179    sk = ctypes.create_string_buffer(crypto_kx_SECRETKEYBYTES)
1180    __check(sodium.crypto_kx_keypair(pk, sk))
1181    return pk.raw, sk.raw
1182
1183# int crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
1184#                                  unsigned char tx[crypto_kx_SESSIONKEYBYTES],
1185#                                  const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES],
1186#                                  const unsigned char client_sk[crypto_kx_SECRETKEYBYTES],
1187#                                  const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES]);
1188@sodium_version(1, 0, 12)
1189def crypto_kx_client_session_keys(client_pk, client_sk, server_pk):
1190    if None in (client_pk, client_sk, server_pk):
1191        raise ValueError("invalid parameters")
1192    if not (len(client_pk) == crypto_kx_PUBLICKEYBYTES): raise ValueError("Invalid client public key")
1193    if not (len(client_sk) == crypto_kx_SECRETKEYBYTES): raise ValueError("Invalid client secret key")
1194    if not (len(server_pk) == crypto_kx_PUBLICKEYBYTES): raise ValueError("Invalid server public key")
1195
1196    rx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES)
1197    tx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES)
1198    __check(sodium.crypto_kx_client_session_keys(rx, tx, client_pk, client_sk, server_pk))
1199    return rx.raw, tx.raw
1200
1201# int crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
1202#                                  unsigned char tx[crypto_kx_SESSIONKEYBYTES],
1203#                                  const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES],
1204#                                  const unsigned char server_sk[crypto_kx_SECRETKEYBYTES],
1205#                                  const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES]);
1206@sodium_version(1, 0, 12)
1207def crypto_kx_server_session_keys(server_pk, server_sk, client_pk):
1208    if None in (server_pk, server_sk, client_pk):
1209        raise ValueError("invalid parameters")
1210    if not (len(server_pk) == crypto_kx_PUBLICKEYBYTES): raise ValueError("Invalid server public key")
1211    if not (len(server_sk) == crypto_kx_SECRETKEYBYTES): raise ValueError("Invalid server secret key")
1212    if not (len(client_pk) == crypto_kx_PUBLICKEYBYTES): raise ValueError("Invalid client public key")
1213
1214    rx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES)
1215    tx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES)
1216    __check(sodium.crypto_kx_server_session_keys(rx, tx, server_pk, server_sk, client_pk))
1217    return rx.raw, tx.raw
1218
1219# void sodium_increment(unsigned char *n, const size_t nlen)
1220@sodium_version(1, 0, 4)
1221def sodium_increment(n):
1222    sodium.sodium_increment(n, ctypes.c_size_t(len(n)))
1223
1224
1225# int crypto_core_ristretto255_is_valid_point(const unsigned char *p);
1226@sodium_version(1, 0, 18)
1227def crypto_core_ristretto255_is_valid_point(p):
1228    return sodium.crypto_core_ristretto255_is_valid_point(p) == 1
1229
1230# int crypto_core_ristretto255_from_hash(unsigned char *p, const unsigned char *r);
1231@sodium_version(1, 0, 18)
1232def crypto_core_ristretto255_from_hash(r):
1233    if len(r) != crypto_core_ristretto255_HASHBYTES: raise ValueError("Invalid parameter, must be {} bytes".format(crypto_core_ristretto255_HASHBYTES))
1234    p = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES)
1235    __check(sodium.crypto_core_ristretto255_from_hash(p,r))
1236    return p.raw
1237
1238# int crypto_scalarmult_ristretto255(unsigned char *q, const unsigned char *n, const unsigned char *p);
1239@sodium_version(1, 0, 18)
1240def crypto_scalarmult_ristretto255(n, p):
1241    if None in (n,p):
1242        raise ValueError("invalid parameters")
1243    if len(n) != crypto_core_ristretto255_SCALARBYTES: raise ValueError("truncated scalar")
1244    if len(p) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point")
1245    buf = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES)
1246    __check(sodium.crypto_scalarmult_ristretto255(buf, n, p))
1247    return buf.raw
1248
1249# int crypto_scalarmult_ristretto255_base(unsigned char *q, const unsigned char *n);
1250@sodium_version(1, 0, 18)
1251def crypto_scalarmult_ristretto255_base(n):
1252    if n is None:
1253        raise ValueError("invalid parameters")
1254    if len(n) != crypto_core_ristretto255_SCALARBYTES: raise ValueError("truncated scalar")
1255    buf = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES)
1256    __check(sodium.crypto_scalarmult_ristretto255_base(buf, n))
1257    return buf.raw
1258
1259# void crypto_core_ristretto255_scalar_random(unsigned char *r);
1260@sodium_version(1, 0, 18)
1261def crypto_core_ristretto255_scalar_random():
1262    r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES)
1263    sodium.crypto_core_ristretto255_scalar_random(r)
1264    return r.raw
1265
1266# int crypto_core_ristretto255_scalar_invert(unsigned char *recip, const unsigned char *s);
1267@sodium_version(1, 0, 18)
1268def crypto_core_ristretto255_scalar_invert(s):
1269    if not s or len(s)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES))
1270    r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES)
1271    __check(sodium.crypto_core_ristretto255_scalar_invert(r,s))
1272    return r.raw
1273
1274# void crypto_core_ristretto255_scalar_reduce(unsigned char *r, const unsigned char *s);
1275@sodium_version(1, 0, 18)
1276def crypto_core_ristretto255_scalar_reduce(s):
1277    if not s or len(s)!=crypto_core_ristretto255_NONREDUCEDSCALARBYTES: raise ValueError("Invalid parameter: must be {} bytes".format(crypto_core_ristretto255_NONREDUCEDSCALARBYTES))
1278    r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES)
1279    sodium.crypto_core_ristretto255_scalar_reduce(r,s)
1280    return r.raw
1281
1282# int crypto_core_ristretto255_add(unsigned char *r, const unsigned char *p, const unsigned char *q)
1283@sodium_version(1, 0, 18)
1284def crypto_core_ristretto255_add(p, q):
1285    if len(p) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point p")
1286    if len(q) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point q")
1287    r = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES)
1288    __check(sodium.crypto_core_ristretto255_add(r, p, q))
1289    return r.raw
1290
1291# int crypto_core_ristretto255_sub(unsigned char *r, const unsigned char *p, const unsigned char *q)
1292@sodium_version(1, 0, 18)
1293def crypto_core_ristretto255_sub(p,q):
1294    if len(p) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point p")
1295    if len(q) != crypto_core_ristretto255_BYTES: raise ValueError("truncated point q")
1296    r = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES)
1297    __check(sodium.crypto_core_ristretto255_sub(r, p, q))
1298    return r.raw
1299
1300# void crypto_core_ristretto255_random(unsigned char *p)
1301@sodium_version(1, 0, 18)
1302def crypto_core_ristretto255_random():
1303    p = ctypes.create_string_buffer(crypto_core_ristretto255_BYTES)
1304    sodium.crypto_core_ristretto255_random(p)
1305    return p.raw
1306
1307# void crypto_core_ristretto255_scalar_negate(unsigned char *neg, const unsigned char *s)
1308@sodium_version(1, 0, 18)
1309def crypto_core_ristretto255_scalar_negate(s):
1310    if not s or len(s)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES))
1311    r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES)
1312    sodium.crypto_core_ristretto255_scalar_negate(r,s)
1313    return r.raw
1314
1315# void crypto_core_ristretto255_scalar_complement(unsigned char *comp, const unsigned char *s)
1316@sodium_version(1, 0, 18)
1317def crypto_core_ristretto255_scalar_complement(s):
1318    if not s or len(s)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES))
1319    r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES)
1320    sodium.crypto_core_ristretto255_scalar_complement(r,s)
1321    return r.raw
1322
1323# void crypto_core_ristretto255_scalar_add(unsigned char *z, const unsigned char *x, const unsigned char *y)
1324@sodium_version(1, 0, 18)
1325def crypto_core_ristretto255_scalar_add(x,y):
1326    if not x or len(x)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES))
1327    if not y or len(y)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES))
1328    r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES)
1329    sodium.crypto_core_ristretto255_scalar_add(r,x,y)
1330    return r.raw
1331
1332# void crypto_core_ristretto255_scalar_sub(unsigned char *z, const unsigned char *x, const unsigned char *y)
1333@sodium_version(1, 0, 18)
1334def crypto_core_ristretto255_scalar_sub(x,y):
1335    if not x or len(x)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES))
1336    if not y or len(y)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES))
1337    r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES)
1338    sodium.crypto_core_ristretto255_scalar_sub(r,x,y)
1339    return r.raw
1340
1341# void crypto_core_ristretto255_scalar_mul(unsigned char *z, const unsigned char *x, const unsigned char *y)
1342@sodium_version(1, 0, 18)
1343def crypto_core_ristretto255_scalar_mul(x,y):
1344    if not x or len(x)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES))
1345    if not y or len(y)!=crypto_core_ristretto255_SCALARBYTES: raise ValueError("Invalid param, must be {} bytes".format(crypto_core_ristretto255_SCALARBYTES))
1346    r = ctypes.create_string_buffer(crypto_core_ristretto255_SCALARBYTES)
1347    sodium.crypto_core_ristretto255_scalar_mul(r,x,y)
1348    return r.raw
1349