Important Notice!¶
WARNING: DO NOT USE BEACON GENERATED VALUES AS SECRET CRYPTOGRAPHIC KEYS.
Remember, these random numbers are not only available over the public internet, but are kept on “record” and can be accessed at anytime with just a timestamp. Make sure you understand the implications of using the NIST randomness beacon in your projects.
Contents¶
Installation¶
Prerequisites¶
A required library pycryptodome
is used with nistbeacon
.
Ubuntu, and other Linux-based users should have python3-dev
installed.
apt-get install python3-dev
Beacon Usage¶
It is easy to use the beacon. Most queries are performed through
NistBeacon
which produces NistBeaconValue
objects.
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>
prev_record = NistBeacon.get_previous(1447873020)
# Next Record
# https://beacon.nist.gov/rest/record/next/<timestamp>
next_record = NistBeacon.get_next(1447873020)
# First Record
# https://beacon.nist.gov/rest/record/1378395540
first_record = NistBeacon.get_first_record(download=True)
# Last Record
# https://beacon.nist.gov/rest/record/last
last_record = NistBeacon.get_last_record()
# Verify the record and the record chain
record_chain_result = NistBeacon.chain_check(1447873020)
Beacon Methods¶
chain_check
¶
@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.
"""
get_first_record
¶
@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.
"""
get_last_record
¶
@classmethod
def get_last_record(cls) -> NistBeaconValue:
"""
Get the last (newest) record available.
:return: The last beacon value. 'None' otherwise.
"""
get_next
¶
@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.
"""
get_previous
¶
@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
"""
get_record
¶
@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.
Instance Details¶
"""
: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
"""
Properties¶
frequency
¶
@property
def frequency(self) -> int:
"""
:return: The time interval, in seconds, between expected records
"""
json
¶
@property
def json(self) -> str:
"""
:return: The JSON representation of the beacon, as a string
"""
output_value
¶
@property
def output_value(self) -> str:
"""
:return: The SHA-512 hash of the signatureValue as a 64 byte hex string
"""
previous_output_value
¶
@property
def previous_output_value(self) -> str:
"""
:return:
The SHA-512 hash value for the previous record - 64 byte hex
string
"""
pseudo_random
¶
@property
def pseudo_random(self) -> Random:
"""
:return:
A python `random.Random` object that has been seeded with
the value's `output_value`. This is a pseudo-random
number generator
"""
seed_value
¶
@property
def seed_value(self) -> str:
"""
:return:
A seed value represented as a 64 byte (512-bit) hex string
value
"""
signature_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
"""
status_code
¶
@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
"""
timestamp
¶
@property
def timestamp(self) -> int:
"""
:return:
The time the seed value was generated as the number of
seconds since January 1, 1970
"""
valid_signature
¶
@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
"""
version
¶
@property
def version(self) -> str:
"""
:return: Reported NIST randomness beacon version
"""
xml
¶
@property
def xml(self) -> str:
"""
:return: The XML representation of the beacon, as a string
"""
Methods¶
from_json
¶
@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
"""
from_xml
¶
@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
Project Information¶
Project Health¶
Branch | Build Status | Coverage Status |
---|---|---|
Master | ||
Develop |
Contributing¶
Please refer to the CONTRIBUTING document on GitHub
CHANGELOG¶
v0.9.4¶
- Project Changes
- Switched to
pycryptodome
frompycrypto
. - Started locking versions for
requirements.txt
. - Created a
sphinx
based documentation site. - Internal Changes
- Synced
LICENSE
file to use boilerplate notice. - Removed
nist_records
dependency onNistBeaconValue
- Removed
local_record_db
. Most records are stored injson
now.
v0.9.3¶
- Updated
LICENSE
to work with GitHub LICENSE features. - Updated
README
links for Codecov, - Fixed
CONTRIBUTING
link inREADME
. - Updated library to use additional signing key
- For more details, see:
v0.9.2¶
- Internal Changes
- LICENSE
- Updated for 2016.
NistBeacon
get_first_record
now defaults to downloading the first record.
NistBeaconCrypto
- Now computes the
struct
and other values for theSHA512Hash
.
- Now computes the
NistBeaconValue
- Pushed
struct
and signature hash building intoNistBeaconCrypto
.
- Pushed
- Project Changes
- Coverage Tool
- Switched from Coveralls to Codecov.
v0.9.1¶
- Internal Changes
NistBeacon
NIST_BASE_URL
renamed to_NIST_API_URL
, to clarify that the value should NOT be altered under normal circumstances.
NistBeaconCrypto
- New helper class for signature checking of
NistBeaconValue
objects. This is NOT a class designed for general use!
- New helper class for signature checking of
NistBeaconValue
- Added a helper class
NistBeaconCrypto
to handle SHA512 generation and signature checking. This means thatNistBeaconCrypto
needs to be the only reference for key import and signature checking. All otherNistBeaconValue
do not have to generate the full RSA objects. - Started using the now existing
xmlns
property directly from NIST.
- Added a helper class
v0.9.0¶
- Features
NistBeaconValue
- Added a
pseudo_random
property. Returns arandom.Random
object that has been seeded with theoutput_value
for a givenNistBeaconValue
.
- Added a
v0.8.3¶
- Internal Changes
NistBeaconValue
- Creating a beacon value will store the JSON, XML representations
once.
These values do not have to be computed on each
json
orxml
property access now as before.
- Creating a beacon value will store the JSON, XML representations
once.
These values do not have to be computed on each
- Project Changes (for Developers)
pylint
has been added to the project and build process.
v0.8.2¶
- Bug Fixes:
NistBeaconValue
- Reported issue where a
xmlns
value onrecord
ended up breaking XML loading. Reported on GitHub. Since this is just a bug fix release. Thisxmlns
value will not show up if one was to use thexml
value from theNistBeaconValue
object.
- Reported issue where a
v0.8.1¶
- Minor documentation changes
v0.8.0¶
- Features
NistBeaconValue
- Added
json
andxml
as properties (replacesto_json()
andto_xml()
)
- Added
v0.7.0¶
- Name changes
- Changed from
py_nist_beacon
tonistbeacon
- Changed from
NistRandomnessBeacon
toNistBeacon
- Changed from
NistRandomnessBeaconValue
toNistBeaconValue
v0.6.0¶
- Features
NistRandomnessBeacon
- Added a
get_first_record
method. An optional boolean flag nameddownload
allows the caller to either use the local first record object, or to download the first record directly from the NIST beacon.
- Added a
v0.5.2¶
- Added a section on installation.
- Updated
CONTRIBUTING
- Re-do
PHONY
targets inMakefile
- Update
travis
build steps to include3.5-dev
andnightly
v0.5.1¶
- Badges made to point to their release branches
v0.5.0¶
- General
- Lots of documentation added through
docstrings
! 📝 NistRandomnessBeacon
- The beacon now understands how to check the chain. Using the
chain_check
method on the beacon with a giventimestamp
value the NIST Randomness Beacon chain can be verified for integrity purposes. 🔗
@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.
"""
NistRandomnessBeaconValue
- ⚠️ All properties of the beacon have been placed behind
@property
decorators to minimize possible manipulation - ⚠️
verify_signature
has been removed from beacon values. Replaced with ``valid_signature`` - Introduced
valid_signature
as abool
property. Replaces ``verify_signature``
v0.4.0¶
- Added a
verify_signature
toNistRandomnessBeaconValue
objects. This method returns aTrue
orFalse
after verifying the provided record. The record is verified using two steps: - First, using a combination of input data of the record, a simple
message
is packed to create a message. That message is then used in
combination with
the record’s reported
signature_value
and the known NIST Beacon X.509 certificate. This certificate is available for download, but is baked into the application as follows:- Original CER file as a string:
nist_beacon_constants.py - NIST_CER_FILE
- Original Public Key as a string:
nist_beacon_constants.py - NIST_RSA_KEY
- Hard copy of
beacon.cer
is provided at the root of the project
- Original CER file as a string:
- Second, the
signature_value
is ran through asha512
hash to confirm theoutput_value
is correct on the record. - If either of the steps are found to be invalid,
verify_signature
will return aFalse
result.
v0.3.0¶
- Added
to_xml
,to_json
, andfrom_json
methods on beacon values
v0.2.0¶
- Initial PyPI release package