--- /dev/null
+//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
+//! SPDX-License-Identifier: GPL-3.0-or-later
+
+/**
+ * Convert a bigint, number, or hex string to bytes.
+ *
+ * @param {(bigint|number|string)} input
+ * @param {number} [length]
+ * @returns {Uint8Array<ArrayBuffer>}
+ */
+export function Bytes (input: unknown, minLength?: number): Uint8Array<ArrayBuffer> {
+ if (typeof input === 'number') {
+ input = BigInt(input | 0)
+ }
+ if (typeof input === 'bigint') {
+ input = input.toString(16)
+ }
+ if (typeof input === 'string' && input.length & 1) {
+ input = `0${input}`
+ }
+ if (typeof input !== 'string' || !/^([a-f0-9]{2})+$/i.test(input)) {
+ throw new TypeError('invalid Bytes input', { cause: input })
+ }
+ if (typeof minLength !== 'number' || minLength < 1) {
+ throw new TypeError('invalid minLength', { cause: minLength })
+ }
+ const bytes = input.match(/.{2}/g)?.map(int => parseInt(int, 16)) ?? []
+ const filler = new Array(minLength > bytes.length ? minLength - bytes.length : 0)
+ return new Uint8Array([...filler, ...bytes])
+}
+
+/**
+ * Convert a byte buffer to a hex string.
+ *
+ * @param {ArrayBuffer} input
+ * @param {number} [length]
+ * @returns {string}
+ */
+export function BytesToHex (input: unknown, length?: number): string {
+ if (!(input instanceof ArrayBuffer) || input.byteLength < 1) {
+ throw new TypeError('invalid buffer', { cause: input })
+ }
+ if (typeof length !== 'number' || length < 1) {
+ throw new TypeError('invalid length', { cause: length })
+ }
+ const bytes = new Uint8Array(input)
+ return [...bytes].map(b => b.toString(16).padStart(2, '0')).join('').padStart(length, '0')
+}
+