Skip to main content

multisig HMAC

Project description

multisig-hmac

Multisig scheme for HMAC authentication. Python implementation of multisig-hmac.

Usage

Key management can happen in either of two modes, either by storing every of the component keys, or by storing a single master seed and using that to derive keys ad hoc.

The following two examples return true when they are executed, for example inside a virtual environment.

Using stored keys:

import multisig_hmac
from multisig_hmac.multisig_hmac import MultisigHMAC
import base64

m = MultisigHMAC()

# generate keys which need to be stored securely and need to be shared securely with each party
k0 = m.keygen(0)
k1 = m.keygen(1)
k2 = m.keygen(2)

# sign by each client
data = b'hello world'

s0 = m.sign(k0, data)
s2 = m.sign(k2, data)

# combine the used signatures
out = m.combine([s0, s2])

sent = (out[0], base64.urlsafe_b64encode(out[1]))

# --- network ---

received = (sent[0], base64.urlsafe_b64decode(sent[1]))

# verify on the server
threshold = 2
keys = [k0, k1, k2]
signature = received

print(m.verify(keys, signature, data, threshold))

Using a derived master key:

import multisig_hmac
from multisig_hmac.multisig_hmac import MultisigHMAC
import base64

m = MultisigHMAC()

# generate a master seed which needs to be stored securely
# this seed must NOT be shared with any other party
seed = m.seedgen()

k0 = m.deriveKey(seed, 0)
k1 = m.deriveKey(seed, 1)
k2 = m.deriveKey(seed, 2)

# sign by each client
data = b'hello world'

s0 = m.sign(k0, data)
s2 = m.sign(k2, data)

# combine the used signatures
out = m.combine([s0, s2])

sent = (out[0], base64.urlsafe_b64encode(out[1]))

# --- network ---

received = (sent[0], base64.urlsafe_b64decode(sent[1]))

# verify on the server, but now keys are dynamically derived
threshold = 2
signature = received

print(m.verifyDerived(seed, signature, data, threshold))

API

Constants

  • MultisigHMAC.BYTES signature length in bytes (default)
  • MultisigHMAC.KEYBYTES key length in bytes (default)
  • MultisigHMAC.PRIMITIVE is sha256 (default)

So far, the implementation supports the following specific algorithms:

  • MultisigHMAC.SHA256_BYTES signature length in bytes
  • MultisigHMAC.SHA256_KEYBYTES key length in bytes
  • MultisigHMAC.SHA256_PRIMITIVE is sha256
  • MultisigHMAC.SHA512_BYTES signature length in bytes
  • MultisigHMAC.SHA512_KEYBYTES key length in bytes
  • MultisigHMAC.SHA512_PRIMITIVE is sha512
  • MultisigHMAC.SHA384_BYTES signature length in bytes
  • MultisigHMAC.SHA384_KEYBYTES key length in bytes
  • MultisigHMAC.SHA384_PRIMITIVE is sha384

n = MultisigHMAC.popcount(bitfield)

Returns the number of keys (i.e. high bits) in bitfield. bitfield must be a 32-bit unsigned integer. Example:

assert MultisigHMAC.popcount(5) == 2

xs = MultisigHMAC.keyIndexes(bitfield)

Returns the indexes of the keys (i.e. high bits) in bitfield as a list. bitfield must be a 32-bit unsigned integer. Example:

assert MultisigHMAC.keyIndexes(5) == [0,2]

m = MultisigHMAC([alg = MultisigHMAC.PRIMITIVE])

Creates a new instance of MultisigHMAC which can be used as a global singleton. Just sets the algorithm to be used for subsequent methods and associated constants. Example:

m = MultisigHMAC()
assert (m.popcount(5) == 2 and m.keyIndexes(5) == [0,2])

key = MultisigHMAC.keygen(index)

Generates a new cryptographically random key. The function returns { index: 32-bit unsigned integer, key: bytes of length KEYBYTES }.

Note: index should be counted from 0.

masterSeed = MultisigHMAC.seedgen()

Generates a new cryptographically random master seed.

key = MultisigHMAC.deriveKey(masterSeed, index)

Derives a new subkey from a master seed. index must be a 32-bit unsigned integer, but in practice you want to keep a much lower number, as the bitfield used with the signature has as many bits as the largest index. The function returns { index: 32-bit unsigned integer, key: bytes of length KEYBYTES }.

Note: index should be counted from 0.

Keys are derived using a KDF based on HMAC:

b[0...BYTES] = HMAC(Key = masterSeed, data = 'derive' || U32LE(index) || 0x00)
b[BYTES...] = HMAC(Key = masterSeed, b[0...BYTES] || 0x01)

signature = MultisigHMAC.sign(key, data)

Independently signs data with key. The function returns { bitfield: 32-bit unsigned integer, signature: bytes of length BYTES }. This object can be passed to the combine() function explained below.

signature = MultisigHMAC.combine([signatures...])

Combines a list of signatures which have all been signed independently. Only include each signature once, otherwise they will cancel out. Signatures can be combined in any order. The function returns { bitfield: 32-bit unsigned integer, signature: bytearray of length BYTES }.

valid = MultisigHMAC.verify(keys, signature, data, threshold)

Verifies a signature of data against a list of keys, over a given threshold. keys must be an array of keys. The function returns True or False.

valid = MultisigHMAC.verifyDerived(masterSeed, signature, data, threshold)

Verifies a signature of data against dynamically derived keys from masterSeed, over a given threshold. masterSeed must be bytes of length KEYBYTES. The function returns True or False.

Installation

$ pip install multisig-hmac

Running tests

$ pip install -U pytest
$ py.test

License

ISC

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

multisig-hmac-0.2.4.tar.gz (6.1 kB view details)

Uploaded Source

Built Distribution

multisig_hmac-0.2.4-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file multisig-hmac-0.2.4.tar.gz.

File metadata

  • Download URL: multisig-hmac-0.2.4.tar.gz
  • Upload date:
  • Size: 6.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.36.1 CPython/3.7.4

File hashes

Hashes for multisig-hmac-0.2.4.tar.gz
Algorithm Hash digest
SHA256 3f2770f845070917dd331d201376f4919229dd1809e4cc98da522bf9eb44d370
MD5 314662f4754bf0f5eeefaed92bb290fb
BLAKE2b-256 e347e3364e7b41dd140eeb42977b77dbd60fe33e537b3e0e5f2f796fb28f10c3

See more details on using hashes here.

File details

Details for the file multisig_hmac-0.2.4-py3-none-any.whl.

File metadata

  • Download URL: multisig_hmac-0.2.4-py3-none-any.whl
  • Upload date:
  • Size: 8.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.36.1 CPython/3.7.4

File hashes

Hashes for multisig_hmac-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 bc1d810022d6d30367a7626dfa42b160e9b1b804ff88242d7323cb4f826dce82
MD5 2fba438d9ff34136d5411c527bb75418
BLAKE2b-256 c7909dfad1435a629874e4d4f5acd6ab7331b55bfbc41455b218ec1e9226e138

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page