aboutsummaryrefslogtreecommitdiff
path: root/examples/05-python/sha3.py
blob: 1e66c59da87d7992b2c24c5036b0cc2802586a3e (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/usr/bin/env python3

#
# sha3.py: Access libsha3.so functions via Python ctypes module and
# compare libsha3.so output against hashlib output.
#

import csv, ctypes, hashlib, sys

# common function argument types
XOF_ARGS = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_char_p, ctypes.c_size_t]
HASH_ARGS = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_char_p]

# load sha3 module
sha3 = ctypes.CDLL('../../libsha3.so')

# set function argument and return types
# (note: this is not required, but it helps to prevent argument and type
# oopsies)
sha3.shake128.argtypes = XOF_ARGS
sha3.shake128.rettype = None
sha3.shake256.argtypes = XOF_ARGS
sha3.shake256.rettype = None
sha3.sha3_224.argtypes = HASH_ARGS
sha3.sha3_224.rettype = None
sha3.sha3_256.argtypes = HASH_ARGS
sha3.sha3_256.rettype = None
sha3.sha3_384.argtypes = HASH_ARGS
sha3.sha3_384.rettype = None
sha3.sha3_512.argtypes = HASH_ARGS
sha3.sha3_512.rettype = None

class Result:
  """Individual digest result"""
  algo : str
  source : str
  digest : bytes

  def __init__(self: object, algo: str, source: str, digest: bytes) -> None:
    """Create hash test result."""
    self.algo = algo
    self.source = source
    self.digest = digest

  def to_row(self: object) -> [str]:
    """Convert result to CSV row."""
    return [self.algo, self.source, self.digest.hex()]

class Results:
  """Collection of digest results."""
  rs : [Result]

  def __init__(self: object) -> None:
    self.rs = []

  def append(self: object, algo: str, source: str, digest: bytes) -> None:
    """append result to self"""
    self.rs.append(Result(algo, source, digest))

  def write(self, io) -> None:
    """write results as CSV to given IO."""
    cw = csv.writer(io) # create csv writer
    cw.writerow(['algo', 'source', 'digest']) # write headers

    # write rows
    for r in self.rs:
      cw.writerow(r.to_row())

def test_shake128(rs: Results, data: bytes) -> None:
  """append SHAKE128 digest of data from hashlib and libsha3 to results"""
  algo = 'shake128' # algorithm name
  size = 32 # output size, in bytes

  # append hashlib digest
  rs.append(algo, 'hashlib', hashlib.shake_128(data).digest(size))

  # append libsha3 digest
  buf = ctypes.create_string_buffer(size)
  sha3.shake128(data, len(data), buf, size)
  rs.append(algo, 'libsha3', buf.raw)

def test_shake256(rs: Results, data: bytes) -> None:
  """append SHAKE256 digest of data from hashlib and libsha3 to results"""
  algo = 'shake256' # algorithm name
  size = 32 # output size, in bytes

  # append hashlib digest
  rs.append(algo, 'hashlib', hashlib.shake_256(data).digest(size))

  # append libsha3 digest
  buf = ctypes.create_string_buffer(size)
  sha3.shake256(data, len(data), buf, size)
  rs.append(algo, 'libsha3', buf.raw)

def test_sha3_224(rs: Results, data: bytes) -> None:
  """append SHA3-224 digest of data from hashlib and libsha3 to results"""
  algo = 'sha3-224' # algorithm name

  # append hashlib digest
  rs.append(algo, 'hashlib', hashlib.sha3_224(data).digest())

  # append libsha3 digest
  buf = ctypes.create_string_buffer(28)
  sha3.sha3_224(data, len(data), buf)
  rs.append(algo, 'libsha3', buf.raw)

def test_sha3_256(rs: Results, data: bytes) -> None:
  """append SHA3-256 digest of data from hashlib and libsha3 to results"""
  algo = 'sha3-256' # algorithm name

  # append hashlib digest
  rs.append(algo, 'hashlib', hashlib.sha3_256(data).digest())

  # append libsha3 digest
  buf = ctypes.create_string_buffer(32)
  sha3.sha3_256(data, len(data), buf)
  rs.append(algo, 'libsha3', buf.raw)

def test_sha3_384(rs: Results, data: bytes) -> None:
  """append SHA3-384 digest of data from hashlib and libsha3 to results"""
  algo = 'sha3-384' # algorithm name

  # append hashlib digest
  rs.append(algo, 'hashlib', hashlib.sha3_384(data).digest())

  # append libsha3 digest
  buf = ctypes.create_string_buffer(48)
  sha3.sha3_384(data, len(data), buf)
  rs.append(algo, 'libsha3', buf.raw)

def test_sha3_512(rs: Results, data: bytes) -> None:
  """append SHA3-512 digest of data from hashlib and libsha3 to results"""
  algo = 'sha3-512' # algorithm name

  # append hashlib digest
  rs.append(algo, 'hashlib', hashlib.sha3_512(data).digest())

  # append libsha3 digest
  buf = ctypes.create_string_buffer(64)
  sha3.sha3_512(data, len(data), buf)
  rs.append(algo, 'libsha3', buf.raw)

# declare test data and results
DATA = b'foo bar'
rs = Results()

# run tests, add to results
test_shake128(rs, DATA)
test_shake256(rs, DATA)
test_sha3_224(rs, DATA)
test_sha3_256(rs, DATA)
test_sha3_384(rs, DATA)
test_sha3_512(rs, DATA)

# print results to stdout as csv
rs.write(sys.stdout)