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:
random.json
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.
signature.base64
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.
server.crt
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 XWTB2PiGutI86GYDNIEiYvbTkAC1PQO3U2A/Depb2m2W4zUF81UFjTthCNmvPYFdnrBlGMgS7mo1rNUKfkVU9M0Yv0fPkjVaYoDo3ADOw1DGtENtU+Em+Clhowz+FQEhfUTLOBTfruYpnb1CSjbovo8AzjHF0pb+0F8awVMZPuHEhjE8oHJcQInVXmkLq/IR5WNcM0E0ygRQto37NE9CIFDst+5WAN7UmlqYTNil+iqmzjj92vTDlHr+Gh3bhgxb+aR9rabpaGQni2MlyXH0kGCrbAdryvCzUTZ/SxXY6MWfmNFODzvibcO2j//GFm/Z8uyVuyeAt5GNO0QQipWvv8eauALAW87JDLw8vgYcbFapHIAsWOyrhD9tMMmaejKzc+leMwvs0BSy6I8jwLBy6MlcPUHO3i4JFs+0qstKtqaVzmUGm+fnfJPZLySHBBazrX0tMpn36FyiE3wn8XYncOJM1ylUNdT9j2A+xp3ZuoMkr4+Fv6Flh444B+eeqEdZTlgSmXDh7VFoCrcks4QO2KJ0ajzltNv42fO5KdizOPg1fV1totJivzsxA4i0+RnhpPO9tdT4iYjBcuNSdh9nYDtcn7cizODaCr6Y+oOzfIktBok19YjebgMd+AbDhkVmHmPEsaOuL62eqdmCobwPJUjVtM8cgccQqfkfek30uK4=
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 513502f20d5bc7031343e3d62040fe6f895336d5ea574365bc523c6e13a30b25a9985d205920b683fbe81ad8d6b1efbca63b5ce907a84788415efac6056d7444
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.