From ac0d99f2a509d06f94a6b5ade21c8732e1f222cb Mon Sep 17 00:00:00 2001 From: Will Fatherley Date: Sat, 3 Aug 2024 22:46:43 -0400 Subject: [PATCH 1/3] ensure hkdf can return entirety of expand --- src/hkdfref/_hkdfref.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hkdfref/_hkdfref.py b/src/hkdfref/_hkdfref.py index 0ca188a..4fab850 100644 --- a/src/hkdfref/_hkdfref.py +++ b/src/hkdfref/_hkdfref.py @@ -7,7 +7,7 @@ from typing import Any, Callable -logger = getLogger(__name__) +logger = getLogger(__name__[1:]) default_hash = hashlib.sha512 @@ -39,7 +39,9 @@ def hkdf(*ikm: bytes, **kwargs: Any) -> bytes: prk = extract(salt, *ikm, hash=extract_hash) else: prk = b"".join(ikm) - return expand(prk, info, l, expand_hash) + return expand( + prk, info, l, expand_hash, return_all=kwargs.get("return_all", False) + ) def expand( From 11764a42497c38b29d091628db8728f155214d5b Mon Sep 17 00:00:00 2001 From: Will Fatherley Date: Tue, 6 Aug 2024 11:42:36 -0400 Subject: [PATCH 2/3] trigger test workflow for any push or pr --- .github/workflows/tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a9d5a2a..89aad7c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,9 +2,7 @@ name: Tests on: push: - branches: [ "main" ] pull_request: - branches: [ "main" ] jobs: build: From 6116fa7fa17920ab34c65e960ba07f221bd12d5f Mon Sep 17 00:00:00 2001 From: Will Fatherley Date: Wed, 7 Aug 2024 11:10:20 -0400 Subject: [PATCH 3/3] add simple cli --- pyproject.toml | 4 +- src/hkdfref/__init__.py | 96 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4870022..9082b1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,8 +30,8 @@ requires-python = ">=3.9" repository = "https://github.com/wfatherley/hkdfref.git" -# [project.scripts] -# hkdf = hkdfref:cli +[project.scripts] +hkdf = "hkdfref:cli" [tool.setuptools.packages.find] diff --git a/src/hkdfref/__init__.py b/src/hkdfref/__init__.py index 75a4d1a..ec9c2c6 100644 --- a/src/hkdfref/__init__.py +++ b/src/hkdfref/__init__.py @@ -1,9 +1,97 @@ """hkdfref""" import argparse +import codecs +import hashlib -from ._hkdfref import expand, extract, hkdf, logger +from sys import stdout +from ._hkdfref import ( + default_hash, default_salt, expand, extract, hkdf, logger +) -def cli(): - """command line interface""" - pass \ No newline at end of file + +def cli() -> None: + """return None""" + logger.debug("cli: enter") + + # configure argument parser + argument_parser = argparse.ArgumentParser( + prog="hkdf", + description="Generate secure keying material according to RFC 5869.", + epilog="Specification: https://datatracker.ietf.org/doc/html/rfc5869", + ) + argument_parser.add_argument( + "ikm", + type=lambda string: string.encode("latin-1"), + action="append", + help="Input key material. Fed into HKDF as UTF-8 bytes." + ) + argument_parser.add_argument( + "-s", + "--salt", + type=lambda string: string.encode("latin-1"), + default=default_salt, + help=( + "Salt for extract step. Defaults to 0x00 * 20. Fed into HKDF as" + " UTF-8 bytes." + ) + ) + argument_parser.add_argument( + "--hash", + help="One of the known SHAs. Used by both extract and expand" + ) + argument_parser.add_argument( + "--exthash", + help="One of the known SHAs. Used only by extract." + ) + argument_parser.add_argument( + "--exphash", + help="One of the known SHAs. Used only by expand." + ) + argument_parser.add_argument( + "-i", + "--info", + default=b"", + type=lambda string: string.encode("latin-1"), + help="Info for expand step. Fed into HKDF as UTF-8 bytes." + ) + output_length_group = argument_parser.add_mutually_exclusive_group(required=True) + output_length_group.add_argument( + "-l", + "--length", + type=int, + help="First octets to return. Return whole without." + ) + output_length_group.add_argument( + "--returnall", action="store_true", help="Return entire result" + ) + argument_parser.add_argument( + "--skipextract", action="store_true", help="Skip extract step" + ) + + # parse arguments + namespace = argument_parser.parse_args() + logger.debug("cli: args=%s", namespace) + + # rebind hash functions + namespace.hash = namespace.hash or default_hash + namespace.exthash = getattr(hashlib, str(namespace.exthash), default_hash) + namespace.exphash = getattr(hashlib, str(namespace.exphash), default_hash) + + # return okm + stdout.write( + codecs.encode( + hkdf( + *namespace.ikm, + salt=namespace.salt, + l=namespace.length, + info=namespace.info, + extract_hash=namespace.exthash, + expand_hash=namespace.exphash, + hash=namespace.hash, + skip_extract=namespace.skipextract, + return_all=namespace.returnall + ), + "hex_codec" + ).decode() + )