Advisory: We only operate services from the RANDOM.ORG domain. Other sites that claim to be operated by us are impostors. If in doubt, contact us.

Manual Signature Verification

Verify the authenticity of true random data signed by RANDOM.ORG

RANDOM.ORG's API can digitally sign random data for you, such that it can be proved to originate from our service. The signature format is specified in PKCS #1 v2.0. You can use our Signature Verification Form or our Signed API to verify signatures, but it is also possible to do it yourself without the use of RANDOM.ORG. This page explains how to perform signature verification in this fashion. We assume you are using a Unix-based setup (such as GNU/Linux) and that you have OpenSSL installed.

You need the following files:

A random object returned by RANDOM.ORG's Signed API. In this example, we will assume it is a JSON object but it could also be in another format. There should be no trailing newline in this file.
A signature of the random object, created by RANDOM.ORG. We will assume the signature is base64-encoded, as it would normally be when returned by the RANDOM.ORG API. There should be no trailing newline in this file.
A copy of RANDOM.ORG's X.509 certificate, which contains our public key. This is needed to process the signature.

You can download examples of the files here: random.json, signature.base64, server.crt

The signature contains a signed SHA-512 hash of the random object returned by RANDOM.ORG. To verify the signature, we need to (a) calculate the hash ourselves (using only the random object) and then (b) see that it matches the one signed by RANDOM.ORG. If the two hashes match, we know that the random object really originates from RANDOM.ORG.

First, let's have a look at what the contents of random.json might look like:

$ cat random.json
{"method":"generateSignedIntegers","hashedApiKey":"oT3AdLMVZKajz0pgW/8Z+t5sGZkqQSOnAi1aB8Li0tXgWf8LolrgdQ1wn9sKx1ehxhUZmhwUIpAtM8QeRbn51Q==","n":6,"min":1,"max":6,"replacement":true,"base":10,"data":[6,1,4,4,3,6],"completionTime":"2014-06-03 17:15:13Z","serialNumber":79924}

(Note: ‘$’ is our Unix shell prompt.)

Caveat: Please note that the order of the properties that appear in the random.json object must be the same as specified in our API documentation. As you may know, JSON considers the property order insignificant. This means that two objects are considered identical if they have identical properties, even if the properties appear in different orders. However, when we calculate the SHA-512 hashes for two such objects, we will arrive at different values. If you use the RANDOM.ORG API to verify signatures, our API will automatically order the properties correctly before it hashes the objects, but since we're doing everything manually here, we don't have that luxury. Hence, if you're using a toolkit that does not preserve the order of the properties in your random.json object as the RANDOM.ORG API returned them to you, you may have to reorder them manually before calculating the SHA-512 hash.

Now, let's have a look at the contents of signature.base64:

$ cat signature.base64

We are now ready to begin the signature verification. First, we will need to calculate the SHA-512 hash of the random object. This is our own version of the hash. We can do this quite easily with OpenSSL. The following command will calculate the hash and output it in hex format, which is easy to compare to the signed hash later on.

$ cat random.json | openssl dgst -sha512 | awk '{ print $2; }' > random-hash.hex
$ cat random-hash.hex

Next, we start recovering the signed hash from the signature. OpenSSL can do this, but it expects the signature to be in a binary format, and the signature returned by RANDOM.ORG was base64-encoded. Hence, we first convert the base64 representation of the signature to its binary equivalent:

$ base64 --decode < signature.base64 > signature.binary

Next, we can recover the SHA-512 hash from the signature. OpenSSL does this by outputting the recovered hash in DER format. The following command does the job:

$ openssl rsautl -verify -pkcs -certin -inkey server.crt -in signature.binary > signed-hash.der

Finally, we can use OpenSSL to examine the data encoded in the DER file:

$ openssl asn1parse -inform DER < signed-hash.der
    0:d=0  hl=2 l=  81 cons: SEQUENCE
    2:d=1  hl=2 l=  13 cons: SEQUENCE
    4:d=2  hl=2 l=   9 prim: OBJECT            :sha512
   15:d=2  hl=2 l=   0 prim: NULL
   17:d=1  hl=2 l=  64 prim: OCTET STRING      [HEX DUMP]:513502F20D5BC7031343E3D62040FE6F895336D5EA574365BC523C6E13A30B25A9985D205920B683FBE81AD8D6B1EFBCA63B5CE907A84788415EFAC6056D7444

The last line in the output is the hash in hex that was signed by RANDOM.ORG. For the signature to verify correctly, this hash must be the same as the random-hash.hex file we calculated locally.