Signing and securing your source code on the blockchain

Guy Harrison
ProvenDB
Published in
7 min readMay 30, 2019

GitHub has deservedly become the one-stop shop for source code repositories. At the time of writing, GitHub has over 57 million repositories and is the undisputed premier platform for collaboration and social coding. We all ❤ GitHub!

In many cases, storing source code in GitHub provides not just convenient cloud-based version control, but also proof of ownership and intellectual property. If you are the first to upload code to GitHub then you have a very good claim that the source code is yours.

However, GitHub is not an ideal repository for Intellectual Property. Firstly, it’s owned by Microsoft, and while Microsoft may have become a benign, Open Source-friendly Corporation, it is nonetheless a commercial software company. In the event of an intellectual property dispute between a programmer and Microsoft, there is an obvious conflict of interest if GitHub records are used to resolve the dispute.

Perhaps more importantly, the current gold standard for proving the timestamp, ownership, and integrity of digital items is the Blockchain. Only by using a public Blockchain can we indisputably prove the timestamp of a data record. In every other case, we must rely on the integrity and goodwill of the operators of the datastore.

If we really want to prove ownership of source code, we need a mechanism which is (a) independent of any software vendor and (b) Blockchain enabled.

In this blog, I’m going to show you how to prove your source code repositories by signing them with a private key and anchoring the signed repository to the Blockchain. We are going to use ProvenDB to do this. ProvenDB is our blockchain enabled database service based on MongoDB.

ProvenDB connects MongoDB to the Bitcoin Blockchain

Setting up the private keys

You may already have a private key that you want to use to sign your work. Alternatively, you can create your own private key with a few commands. In this example, I am going to create a set of RSA keys.

I’m using the OpenSSL library to do this. It’s usually pre-installed on Mac OS and Linux machines and can be installed on Windows by installing either Cygwin or the Windows Subsystem for Linux.

First I’ll create a private key:

$ openssl genrsa -out guysPrivateKey.pem 4096Generating RSA private key, 4096 bit long modulus
…………………………………………..++………………………………………………………………………………………………………………………………………………………..++
e is 65537 (0x10001)

I can then extract the public key from that private key with this command:

$ openssl rsa -in guysPrivateKey.pem -pubout >guysPublicKey.pem

Now I have two key files: my private key guysPrivateKey.pem and my public key guysPublicKey.pem.

Creating and signing your repository archive

I’m going to create a tar file containing all the files within the git repository mongoblock-proof (this is the source code for my “MongoDB on the blockchain post” which you can find here). If you are on Windows you might create a zip file instead — it really doesn’t matter what archive tool you use as long as it includes all of the source code files.

$ cd ~/gitgit $ tar czvf mongoblock-proof.tgz mongoblock-proof
a mongoblock-proof
a mongoblock-proof/mongoHash.sh
a mongoblock-proof/.eslintrc.yml
a mongoblock-proof/config.js
a mongoblock-proof/README.md
a mongoblock-proof/yarn.lock
a mongoblock-proof/.gitignore
a mongoblock-proof/package.json
a mongoblock-proof/.git
a mongoblock-proof/mongoHash.js
<snip>
a mongoblock-proof/.git/logs/refs

Signing the archive

I can sign the archive with my private key using a command like this:

$ openssl dgst -sha256 -sign guysPrivateKey.pem -out mongoblock-proof.sign mongoblock-proof.tgz

This creates a signature file mongoblock-proof.sign that could only have been created from the combination of my private key and the exact contents of the archive. Anyone with my public key can confirm that the archive was signed by me, but only someone with my private key could have created the signature.

Putting the files in ProvenDB

ProvenDB is a MongoDB Atlas powered database service which has built-in blockchain capabilities. Let’s sign up for a free service — it takes about 5 minutes.

After signing in with your favorite OAuth provider — Google, Facebook or GitHub we can create a service:

We then need to provide a service name, a username and a password to create our service:

Once we hit Create Service it will take a few minutes to spin up our dedicated ProvenDB service. Once it’s complete you will get a MongoDB URI that you can use to connect to the service:

For convenience sake, I’m going to assign this URI to an environment variable:

git $ export PROVENDB_URI=mongodb://guy:myStrongPassword@myprovencode.provendb.io/myprovencode?ssl=true

Now let’s test the connection:

git $ mongo $PROVENDB_URIMongoDB shell version v4.0.0
connecting to: mongodb://myprovencode.provendb.io/myprovencode?ssl=true
MongoDB server version: 4.0.9
>

OK, it’s all good.

Now, let’s upload my archive into the ProvenDB using the mongofiles command:

git $ mongofiles --uri $PROVENDB_URI --db myprovencode put mongoblock-proof.sign2019–05–23T11:32:04.347+1000 added file: mongoblock-proof.signgit $ mongofiles --uri $PROVENDB_URI --db myprovencode put mongoblock-proof.tgz2019–05–23T11:32:08.448+1000 added file: mongoblock-proof.tgzgit $ mongofiles --uri $PROVENDB_URI --db myprovencode put guysPublicKey.pem2019–05–23T11:32:21.830+1000 added file: guysPublicKey.pem

Note that I uploaded the archive, the signature file I created and my public key. You don’t have to upload your public key, but I find it helps to have all of this information in the one place.

Proving to the blockchain

All the information is in ProvenDB, but it’s not on the Blockchain yet. To put it on the Blockchain we need to submit a proof. First, let’s connect to ProvenDB and check that the data is inside the database:

git $ mongo $PROVENDB_URIMongoDB shell version v4.0.0
connecting to: mongodb://myprovencode.provendb.io/myprovencode?ssl=true
MongoDB server version: 4.0.9
> db.fs.files.find({},{filename:1})
{ “_id” : ObjectId(“5ce5fcd7038db4e311528ae9”), “filename” : “mongoblock-proof.tgz” }
{ “_id” : ObjectId(“5ce5fd03038db4e336431ee7”), “filename” : “mongoblock-proof.sign” }
{ “_id” : ObjectId(“5ce5fd19038db4e342d95562”), “filename” : “guysPublicKey.pem” }

The mongofiles command loaded our data into collections db.files and db.chunks.

Now we need to get the database version number. We do this using the getVersion command.

> db.runCommand({getVersion:1})
{
“ok” : 1,
“response” : “The version is set to: ‘current’”,
“version” : NumberLong(7),
“status” : “current”
}

Then we use the submitProof command to request that this version of the database be proven to the blockchain:

> db.runCommand({submitProof:7}){
“ok” : 1,
“version” : NumberLong(7),
“dateTime” : ISODate(“2019–05–23T01:55:23Z”),
“hash” : “82878d4721931f494db8ed24a10ae412679435d7740f041c575a33b283fc5e4d”,
“proofId” : “d3ca4750–7cfd-11e9-a57b-016e53825aab”,
“status” : “Pending”
}

A little later a hash of your database version will be embedded on the Bitcoin Blockchain. This proof can be used to validate the integrity of the archive and its timestamp. You can retrieve the proof with the getProof command:

> db.runCommand({getProof:7,format:'binary'})
{
"ok" : 1,
"proofs" : [
{
"proofId" : "d3ca4750-7cfd-11e9-a57b-016e53825aab",
"version" : NumberLong(7),
"submitted" : ISODate("2019-05-23T01:55:23Z"),
"type" : "Full",
"hash" : "82878d4721931f494db8ed24a10ae412679435d7740f041c575a33b283fc5e4d",
"status" : "Valid",
"details" : {
"protocol" : {
"name" : "chainpoint",
"uri" : "http://35.235.91.33",
"hashIdNode" : "d3ca4750-7cfd-11e9-a57b-016e53825aab",
"chainpointLocation" : "https://b.chainpoint.org/calendar/3249782/data"
},
"btcTxn" : "0f59ad3b47121c44043508c34b6e4a152686e74a9042ad9178a87481e5cba1d9",
"btcTxnReceived" : "2019-05-23T02:00:02.023Z",
"btcTxnConfirmed" : "2019-05-23T02:03:59Z",
"btcBlock" : "577331"
},
"proof" : BinData(0,"eJytVrtuZMcRtX/B36BQXHY9+lETEXCiwKEjJUR1V7dJYE0S5OjhUHbiVIE/wNbaKwtODBgK9R80/DE+d5a7i+WMABnwJYPh5XR11alzTtUfv70Ytzf7+eX+h6v9/u5hd37+hVzHi9v735yPK7++ubu9vtmffy6v9r+7m9/98t2rV1f+cPV40bjVFlqZTGipafQ2g9Up+VTi ....")
}
]
}

Note that this Chainpoint format proof includes not just your repository archive, but also the signature and the public key which you also uploaded. These have been proven to the blockchain as well!

Exporting from ProvenDB

Although the proof is on the blockchain, the data is still held in ProvenDB. If you want to extract the data to a portable format, you can export your newly created database service from the ProvenDB.com dashboard.

This export is in mongodump format, so you can load it into your own mongo database and use mongofiles to extract the archive and signatures. We have an open source tool provendb-verify that can be used to validate the proofs in a stand-alone MongoDB database.

Scripting the process

I wrote a simple bash script to automate the signing, uploading, and blockchain proof submission:

You can use this script to sign, update and prove any file on provendb.com. All you need is a private key file and a ProvenDB.com account. Here’s an example of the script in action:

$ bash provenfiles.sh -f MySourceArchive.tgz -u $PROVENDB_URI -k guysPrivateKey.pem 
2019–05–30T11:17:27.000+1000 : Signing MySourceArchive.tgz with guysPrivateKey.pem
2019–05–30T11:17:27.000+1000 : Uploading files to ProvenDB
2019–05–30T11:17:29.906+1000 connected to: localhost
2019–05–30T11:17:29.907+1000 added file: MySourceArchive.tgz
2019–05–30T11:17:33.233+1000 connected to: localhost
2019–05–30T11:17:33.233+1000 added file: MySourceArchive.tgz.sign
2019–05–30T11:17:34.000+1000 : Submitting blockchain proof
Blockchain proof bab2fed0–8278–11e9-a57b-011471000b1a submitted

Conclusion

In this blog post, we’ve used ProvenDB to pin a signed copy of a database archive to the Blockchain. You can store as many repositories as you like — and any other artifacts — into the ProvenDB database and prove them all to the Blockchain with a single operation. Best of all, it’s completely free to do so!

ProvenDB is a general purpose database with Blockchain integration which is powered by MongoDB Atlas and is MongoDB compatible. However, using mongofiles we can use the database as a general purpose repository for files and — by using standard SSL utilities — assign ownership to those files. We can then prove the timestamp, integrity, and ownership of these files to the Blockchain.

If you don’t like mucking around with MongoDB commands, try out ProvenDocs.com — it lets you prove documents of up to 16MB to the Blockchain using drag and drop.

ProvenDocs is a free application that lets you prove documents to the Blockchain without coding.

ProvenDB integrates MongoDB with the Bitcoin Blockchain. Immutable versions of database state are anchored to the Blockchain, delivering an unparalleled level of data integrity. ProvenDB allows MongoDB developers to build high-performance applications that include cryptographic proof of data integrity and provenance without having to understand blockchain programming complexities. Sign up for a free 1GB account at ProvenDB.com.

--

--

Guy Harrison
ProvenDB

CTO at ProvenDB.com. Author of many books on database technology. Hopeless old geek. http://guyharrison.net