-
Notifications
You must be signed in to change notification settings - Fork 2
/
siphash24.pyx.in
109 lines (91 loc) · 3.73 KB
/
siphash24.pyx.in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# SPDX-FileCopyrightText: Daniele Nicolodi <[email protected]>
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
# cython: language_level=3, boundscheck=False
from libc.stdint cimport uint64_t, int64_t, uint8_t
from libc.stdio cimport snprintf
from libc.string cimport memcpy, memset
from cpython cimport Py_buffer, PyObject_GetBuffer, PyBUF_SIMPLE, PyBuffer_Release, PyUnicode_Check, PyObject_CheckBuffer
from cpython.conversion cimport PyOS_snprintf
cdef extern from "c-siphash.h":
ctypedef struct CSipHash:
pass
cdef void c_siphash_init(CSipHash *state, const uint8_t seed[16])
cdef void c_siphash_append_13(CSipHash *state, const uint8_t *bytes, size_t n_bytes)
cdef void c_siphash_append_24(CSipHash *state, const uint8_t *bytes, size_t n_bytes)
cdef uint64_t c_siphash_finalize_13(CSipHash *state)
cdef uint64_t c_siphash_finalize_24(CSipHash *state)
cdef bytes uint64le(uint64_t v):
cdef uint8_t[8] r = [
<uint8_t>(v >> 0),
<uint8_t>(v >> 8),
<uint8_t>(v >> 16),
<uint8_t>(v >> 24),
<uint8_t>(v >> 32),
<uint8_t>(v >> 40),
<uint8_t>(v >> 48),
<uint8_t>(v >> 56),
]
return <bytes>r[:8]
cdef str hexlify(uint64_t v):
cdef char string[17]
PyOS_snprintf(
string, sizeof(string),
'%02x%02x%02x%02x%02x%02x%02x%02x',
<uint8_t>(v >> 0),
<uint8_t>(v >> 8),
<uint8_t>(v >> 16),
<uint8_t>(v >> 24),
<uint8_t>(v >> 32),
<uint8_t>(v >> 40),
<uint8_t>(v >> 48),
<uint8_t>(v >> 56))
return string[:16].decode('ascii')
{{for variant in "13", "24"}}
cdef class siphash{{variant}}:
cdef CSipHash state
cdef readonly int digest_size
cdef readonly int block_size
cdef readonly str name
def __cinit__(self):
self.digest_size = 8
self.block_size = 8
self.name = 'siphash{{variant}}'
def __init__(self, data=b'', /, *, key=b''):
"""Return a new Sip Hash {{variant}} hash object."""
cdef const uint8_t[::1] keybytes = memoryview(key).cast('B')
if keybytes.shape[0] > 16:
raise ValueError("maximum key length is 16 bytes")
cdef uint8_t padded[16]
memset(padded, 0, sizeof(padded))
memcpy(padded, &keybytes[0], keybytes.shape[0])
c_siphash_init(&self.state, padded)
cdef const uint8_t[::1] databytes = memoryview(data).cast('B')
c_siphash_append_{{variant}}(&self.state, &databytes[0], databytes.shape[0])
def update(self, data=b''):
"""Update this hash object's state with the provided data."""
cdef const uint8_t[::1] databytes = memoryview(data).cast('B')
c_siphash_append_{{variant}}(&self.state, &databytes[0], databytes.shape[0])
def digest(self):
"""Return the digest value as a bytes object."""
cdef CSipHash state
memcpy(&state, &self.state, sizeof(state))
cdef uint64_t hash = c_siphash_finalize_{{variant}}(&state)
return uint64le(hash)
def hexdigest(self):
"""Return the digest value as a string of hexadecimal digits."""
cdef CSipHash state
memcpy(&state, &self.state, sizeof(state))
cdef uint64_t hash = c_siphash_finalize_{{variant}}(&state)
return hexlify(hash)
def intdigest(self):
"""Return the digest calue as a signed 64bit integer."""
cdef CSipHash state
memcpy(&state, &self.state, sizeof(state))
cdef uint64_t hash = c_siphash_finalize_{{variant}}(&state)
return <int64_t>hash
def copy(self):
"""Return a copy of the hash object."""
cdef siphash{{variant}} r = siphash{{variant}}.__new__()
memcpy(&r.state, &self.state, sizeof(r.state))
return r
{{endfor}}