Skip to main content

Python 3 Library to access the NIST Randomness Beacon

Project description

BuildStatus CoverageStatus

Python NIST Randomness Beacon

WARNING: DO NOT USE BEACON GENERATED VALUES AS SECRET CRYPTOGRAPHIC KEYS.

Installation

Prerequisites

A required library pycrypto is used with nistbeacon.

Ubuntu, and other Linux-based users should have python3-dev installed.

apt-get install python3-dev

Installing nistbeacon

To install the beacon library, simply use pip:

pip install nistbeacon

Beacon Usage

It is easy to use the beacon. Most queries are performed through NistBeacon which produces NistBeaconValue objects.

Beacon Sample Code

from nistbeacon import NistBeacon

# In the examples below I will be using 1447873020 as my <timestamp> when required

# Current Record (or next closest) - https://beacon.nist.gov/rest/record/<timestamp>
record = NistBeacon.get_record(1447873020)

# Previous Record - https://beacon.nist.gov/rest/record/previous/<timestamp>
record = NistBeacon.get_previous(1447873020)

# Next Record - https://beacon.nist.gov/rest/record/next/<timestamp>
record = NistBeacon.get_next(1447873020)

# Last Record - https://beacon.nist.gov/rest/record/last
record = NistBeacon.get_last_record()

# Verify the record and the record chain
record_chain_result = NistBeacon.chain_check(1447873020)

Beacon Methods

@classmethod
def chain_check(cls, timestamp: int) -> bool:
    """
    Given a record timestamp, verify the chain integrity.

    :param timestamp: UNIX time / POSIX time / Epoch time
    :return: 'True' if the timestamp fits the chain. 'False' otherwise.
    """
@classmethod
def get_first_record(
        cls,
        download: bool=False
) -> NistBeaconValue:
    """
    Get the first (oldest) record available. Since the first record
    IS a known value in the system we can load it from constants.

    :param download: 'True' will always reach out to NIST to get the
                     first record. 'False' returns a local copy.
    :return: The first beacon value. 'None' otherwise.
    """
@classmethod
def get_last_record(cls) -> NistBeaconValue:
    """
    Get the last (newest) record available.

    :return: The last beacon value. 'None' otherwise.
    """
@classmethod
def get_next(cls, timestamp: int) -> NistBeaconValue:
    """
    Given a record timestamp, get the next record available.

    :param timestamp: UNIX time / POSIX time / Epoch time
    :return: The next beacon value if available. 'None' otherwise.
    """
@classmethod
def get_previous(cls, timestamp: int) -> NistBeaconValue:
    """
    Given a record timestamp, get the previous record available.

    :param timestamp: UNIX time / POSIX time / Epoch time
    :return: The previous beacon value if available. 'None; otherwise
    """
@classmethod
def get_record(cls, timestamp: int) -> NistBeaconValue:
    """
    Get a specific record (or next closest)

    :param timestamp: UNIX time / POSIX time / Epoch time
    :return: The requested beacon value if available. 'None' otherwise.
    """

Beacon Value

The NistBeaconValue objects act as basic python objects. As one would expect, there are a number of properties and methods available on it.

Beacon Value Instance

"""
:param version:
    Reported NIST randomness beacon version

:param frequency:
    The time interval, in seconds, between expected records

:param timestamp:
    The time the seed value was generated as the number of
    seconds since January 1, 1970

:param seed_value:
    A seed value represented as a 64 byte (512-bit) hex string
    value

:param previous_output_value:
    The SHA-512 hash value for the previous record - 64 byte hex
    string

:param signature_value:
    A digital signature (RSA) computed over (in order): version,
    frequency, timeStamp, seedValue, previousHashValue, statusCode

    Note: Except for version, the hash is on the byte
    representations and not the string representations of the data
    values

:param output_value:
    The SHA-512 hash of the signatureValue as a 64 byte hex string

:param status_code:
    The status code value:
        0 - Chain intact, values all good
        1 - Start of a new chain of values, previous hash value
            will be all zeroes
        2 - Time between values is greater than the frequency, but
            the chain is still intact
"""

Beacon Value Properties

@property
def frequency(self) -> int:
    """
    :return: The time interval, in seconds, between expected records
    """
@property
def json(self) -> str:
    """
    :return: The JSON representation of the beacon, as a string
    """
@property
def output_value(self) -> str:
    """
    :return: The SHA-512 hash of the signatureValue as a 64 byte hex string
    """
@property
def previous_output_value(self) -> str:
    """
    :return:
        The SHA-512 hash value for the previous record - 64 byte hex
        string
    """
@property
def seed_value(self) -> str:
    """
    :return:
        A seed value represented as a 64 byte (512-bit) hex string
        value
    """
@property
def signature_value(self) -> str:
    """
    :return:
        A digital signature (RSA) computed over (in order): version,
        frequency, timeStamp, seedValue, previousHashValue, statusCode

        Note: Except for version, the hash is on the byte
        representations and not the string representations of the data
        values
    """
@property
def status_code(self) -> str:
    """
    :return:
        The status code value:
            0 - Chain intact, values all good
            1 - Start of a new chain of values, previous hash value
                will be all zeroes
            2 - Time between values is greater than the frequency, but
                the chain is still intact
    """
@property
def timestamp(self) -> int:
    """
    :return:
        The time the seed value was generated as the number of
        seconds since January 1, 1970
    """
@property
def valid_signature(self) -> bool:
    """
    Shows the result of signature verification

    First, required records (version, frequency, timestamp,
    seed_value, previous_output_value) are packed together to form
    a message. This message is then checked against the record's reported
    signature field WITH the known NIST public key.

    Second, the signature value is independently ran through a SHA512
    hash. The result of this operation SHOULD equal the record's reported
    output_value field.

    As long as the result of the 'First' step and'ed with the 'Second'
    step, the record is considered valid.

    :return: 'True' if this record is valid. 'False' otherwise
    """
@property
def version(self) -> str:
    """
    :return: Reported NIST randomness beacon version
    """
@property
def xml(self) -> str:
    """
    :return: The XML representation of the beacon, as a string
    """

Beacon Value Methods

@classmethod
def from_json(cls, input_json: str):
    """
    Convert a string of JSON which represents a NIST randomness beacon
    value into a 'NistBeaconValue' object.

    :param input_json: JSON to build a 'Nist RandomnessBeaconValue' from
    :return: A 'NistBeaconValue' object, 'None' otherwise
    """
@classmethod
def from_xml(cls, input_xml: str):
    """
    Convert a string of XML which represents a NIST Randomness Beacon value
    into a 'NistBeaconValue' object.

    :param input_xml: XML to build a 'NistBeaconValue' from
    :return: A 'NistBeaconValue' object, 'None' otherwise
    """

Contributing

Please refer to the CONTRIBUTING document on GitHub

References

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

nistbeacon-0.8.2.tar.gz (13.2 kB view hashes)

Uploaded Source

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