File: __init__.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (132 lines) | stat: -rw-r--r-- 4,406 bytes parent folder | download | duplicates (2)
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from ._sha3_cffi import ffi as _ffi, lib as _lib
import codecs

SHA3_MAX_DIGESTSIZE = 64 # 64 Bytes (512 Bits) for 224 to 512
SHA3_LANESIZE = (20 * 8) # ExtractLane needs max uint64_t[20] extra.

class Immutable(type):
    def __init__(cls, name, bases, dct):
        type.__setattr__(cls,"attr",set(dct.keys()))
        type.__init__(cls, name, bases, dct)

    def __setattr__(cls, name, value):
        # Mock Py_TPFLAGS_IMMUTABLETYPE
        qualname = '.'.join([cls.__module__, cls.__name__])
        raise TypeError(f"cannot set '{name}' attribute of immutable type '{qualname}'")


class _sha3(metaclass=Immutable):
    _keccak_init = None  # Overridden in subclasses

    def __new__(cls, string=None, usedforsecurity=True):
        self = super().__new__(cls)
        self._hash_state = _ffi.new("Keccak_HashInstance*")

        assert self._keccak_init is not None
        self._keccak_init()

        if string:
            self.update(string)
        return self

    def update(self, string):
        if isinstance(string, memoryview):
            buf = string.tobytes()
        else:
            buf = _ffi.from_buffer(string)
        res = _lib.Keccak_HashUpdate(self._hash_state, buf, len(buf) * 8)

    def digest(self):
        digest = _ffi.new("char[]",
                          SHA3_MAX_DIGESTSIZE + SHA3_LANESIZE)
        state_copy = _ffi.new("Keccak_HashInstance*")
        _ffi.memmove(state_copy, self._hash_state,
                     _ffi.sizeof("Keccak_HashInstance"))
        if _lib.Keccak_HashFinal(state_copy, digest) != _lib.SUCCESS:
            raise RuntimeError("internal error in SHA3 Final()")
        return _ffi.unpack(digest, self._hash_state.fixedOutputLength // 8)

    def hexdigest(self):
        return codecs.encode(self.digest(), 'hex').decode()

    def copy(self):
        copy = super().__new__(type(self))
        copy._hash_state = _ffi.new("Keccak_HashInstance*")
        _ffi.memmove(copy._hash_state, self._hash_state,
                     _ffi.sizeof("Keccak_HashInstance"))
        return copy

    @property
    def digest_size(self):
        return self._hash_state.fixedOutputLength // 8

    @property
    def block_size(self):
        return self._hash_state.sponge.rate // 8

    @property
    def _capacity_bits(self):
        return 1600 - self._hash_state.sponge.rate

    @property
    def _rate_bits(self):
        return self._hash_state.sponge.rate

    @property
    def _suffix(self):
        return bytes([self._hash_state.delimitedSuffix])


class _shake(_sha3):
    def digest(self, length):
        if length >= (1 << 29):
            raise ValueError("length is too large")
        if length < 0:
            raise ValueError("value must be positive")
        # ExtractLane needs at least SHA3_MAX_DIGESTSIZE + SHA3_LANESIZE and
        # SHA_LANESIZE extra space.
        digest = _ffi.new("char[]", length + SHA3_LANESIZE)
        # Get the raw (binary) digest value
        state_copy = _ffi.new("Keccak_HashInstance*")
        _ffi.memmove(state_copy, self._hash_state,
                     _ffi.sizeof("Keccak_HashInstance"))
        if _lib.Keccak_HashFinal(state_copy, digest) != _lib.SUCCESS:
            raise RuntimeError("internal error in SHA3 Final()")
        if _lib.Keccak_HashSqueeze(state_copy, digest, length * 8) != _lib.SUCCESS:
            raise RuntimeError("internal error in SHA3 Squeeze()")
        return _ffi.unpack(digest, length)

    def hexdigest(self, length):
        return codecs.encode(self.digest(length), 'hex').decode()


class sha3_224(_sha3):
    name = "sha3_224"
    def _keccak_init(self):
        return _lib.Keccak_HashInitialize_SHA3_224(self._hash_state)

class sha3_256(_sha3):
    name = "sha3_256"
    def _keccak_init(self):
        return _lib.Keccak_HashInitialize_SHA3_256(self._hash_state)

class sha3_384(_sha3):
    name = "sha3_384"
    def _keccak_init(self):
        return _lib.Keccak_HashInitialize_SHA3_384(self._hash_state)

class sha3_512(_sha3):
    name = "sha3_512"
    def _keccak_init(self):
        return _lib.Keccak_HashInitialize_SHA3_512(self._hash_state)

class shake_128(_shake):
    name = "shake_128"
    def _keccak_init(self):
        return _lib.Keccak_HashInitialize_SHAKE128(self._hash_state)

class shake_256(_shake):
    name = "shake_256"
    def _keccak_init(self):
        return _lib.Keccak_HashInitialize_SHAKE256(self._hash_state)