|
- """
- SHA-3 and SHAKE test vectors
-
- Copyright (c) Mike Hamburg, Cryptography Research, 2016.
-
- I will need to contact legal to get a license for this; in the mean time it is
- for example purposes only.
- """
-
- from __future__ import print_function
- import binascii
- import sys
- import getopt
- import Strobe.Keccak
- import fileinput
-
-
- def monte(hash,seed,samples=100,iterations=1000,bits=None,
- minoutbits=None,maxoutbits=None,**kwargs):
- if bits is None and hash().out_bytes is not None:
- bits = hash().out_bytes * 8
-
- md = binascii.unhexlify(seed)
- inputlen = len(md)
-
- print()
- if maxoutbits is None:
- outputlen = minoutbytes = maxoutbytes = bits//8
- print("[L = %d]" % bits)
- mdname = "MD"
- print()
- print("Seed = %s" % seed)
- else:
- minoutbytes = (minoutbits+7)//8
- maxoutbytes = maxoutbits//8
- outputlen = maxoutbytes
- print("[Minimum Output Length (bits) = %d]" % minoutbits)
- print()
- print("[Maximum Output Length (bits) = %d]" % maxoutbits)
- mdname = "Output"
- print()
- print("Msg = %s" % seed)
-
- print()
-
- for j in range(samples):
- for i in range(iterations):
- md = hash.hash((md+bytearray(inputlen))[0:inputlen],length=outputlen)
- randmd = bytearray(2)+md
- randish = randmd[-2]*256 + randmd[-1]
- rng = maxoutbytes-minoutbytes+1
- prev_outputlen = outputlen
- outputlen = minoutbytes + (randish % rng)
-
- print("COUNT = %d" % j)
- if minoutbytes != maxoutbytes: print("Outputlen = %d" % (prev_outputlen*8))
- print(mdname,"=", "".join(("%02x" % x for x in md)))
- print()
- sys.stdout.flush()
-
- def kat(hash,file,len=None,**kwargs):
- length = None
- outlen = None
-
- ignore = ["[Tested", "[Input Length", "COUNT = ",
- "[Minimum Output Length", "[Maximum Output Length"]
-
- for line in open(file,'r').readlines():
- line = line.rstrip()
-
- if line == "":
- print()
- elif any((line.startswith(ign) for ign in ignore)):
- print(line)
- elif line.startswith("Len = "):
- length = int(line.split("Len = ")[1])
- print(line)
- elif line.startswith("Msg = "):
- msg = line.split("Msg = ")[1]
- msg = binascii.unhexlify(msg)
- if length is not None: msg = msg[0:length//8]
- print(line)
- elif line.startswith("[L = "):
- outlen = int(line.split("[L = ")[1][0:-1])//8
- print(line)
- elif line.startswith("[Outputlen = "):
- outlen = int(line.split("[Outputlen = ")[1][0:-1])//8
- print(line)
- elif line.startswith("Outputlen = "):
- outlen = int(line.split("Outputlen = ")[1])//8
- print(line)
- elif line.startswith("Output = "):
- output = hash.hash(msg, length=outlen)
- print("Output =", "".join(("%02x" % x for x in output)))
- elif line.startswith("MD = "):
- output = hash.hash(msg, length=outlen)
- print("MD =", "".join(("%02x" % x for x in output)))
-
- if __name__ == '__main__':
-
- def usage(err=1):
- print("usage: TODO", file=sys.stderr)
- exit(err)
-
- opts,args = getopt.getopt(sys.argv[1:], "",
- ["test=","hash=","seed=","min-len=","max-len=","file="])
- if len(args) != 0 or len(opts) != len(set(opts)): usage()
- opts = dict(opts)
-
- hashes = {
- "SHA3_224":Strobe.Keccak.SHA3_224,
- "SHA3_256":Strobe.Keccak.SHA3_256,
- "SHA3_384":Strobe.Keccak.SHA3_384,
- "SHA3_512":Strobe.Keccak.SHA3_512,
- "SHAKE128":Strobe.Keccak.SHAKE128,
- "SHAKE256":Strobe.Keccak.SHAKE256
- }
- if "--hash" in opts and opts["--hash"] in hashes:
- hash = hashes[opts["--hash"]]
- else: usage()
-
- tests = {
- "Monte":monte,
- "Kat":kat
- # TODO: varlen
- }
- if "--test" in opts and opts["--test"] in tests:
- test = tests[opts["--test"]]
- else: usage()
-
- seed = None
- if "--seed" in opts: seed=opts["--seed"]
-
- file = None
- if "--file" in opts: file=opts["--file"]
-
- # parse lengths
- minlen = maxlen = None
- if "--min-len" in opts and opts["--min-len"] != "":
- minlen = int(opts["--min-len"])
- if "--max-len" in opts and opts["--max-len"] != "":
- maxlen = int(opts["--max-len"])
- if (minlen is None) != (maxlen is None): usage()
- if minlen is not None and (minlen+7)//8 > maxlen//8: usage()
-
- test(hash,seed=seed,file=file,minoutbits=minlen,maxoutbits=maxlen)
-
-
-
|