HashiCorp Vault for Tamper Protection and — Whoops I Accidentally Created a Blockchain

John Boero
Jun 20, 2019 · 6 min read
HashiCorp Vault manages secrets. This focus is on Transit, or Encryption as a Service.

A recent project in which I used Vault Transit to sign and verify certification badge images presented an interesting use case for copyright enforcement.

The European Union has passed controversial rules to protect copyright holders and prevent unauthorized sharing or modification of copyrighted materials on the internet. The law aims to prevent plagiarism and copyright abuse via copy pasta, but what mechanisms can actually be used by someone claiming a violation? How can you identify any impostors or prove content or an image is yours and was yours at a certain point in time?

Administer the test.

My need came from our partner certification badges. If a partner or affiliate of ours gets an image badge for their website, what prevents someone else from copying and photoshopping or deep faking their own? How could one prove that the example GIF above was copied from giphy.com? The example I’ll use here is certified backstage passes for our upcoming HashiConf EU.

There are a few ways to do this. In my case, I had a simple template in SVG format with placeholders for details like name, date, and certification level. That data is simple enough to create a detached signature via a protected Transit key. I can then add a subtle watermark to the SVG containing a tamper-resistant signature. This is straightforward as I have an established range of data to sign- a concatenation of text fields populated in my template.

What if I need a generic signature option for raster data or JPEG images? Pixels are tougher to generalize. You may think you could just generate a signature from an entire image file and then watermark it with its own signature but that obviously changes the signature in a chicken/egg scenario. The proper way to do this is to make a sequence of image files where each one gets a watermark from the previous image signature started by a random seed. Image content can be verified by using Vault to check the signature of the previous image against whichever image you’re testing. Whoa wait a second — this is almost a blockchain. I myself have thought blockchain is overhyped lately but this is very useful.

Basic blockchain with Vault. Consensus algorithm, currency, and shiny Lamborghini sold separately.

It turns out Vault Transit makes a pretty good blockchain tool and nobody ever gets to see its private keys. Not even I as a user get to. Nobody can sign a block without Vault access. In this case, I don’t need a consensus algorithm because I’m the only one verifying images haven’t been forged and I don’t need a cryptocurrency as I don’t need miners around for consensus. It may be useful to have a public blockchain with consensus for wider public copyright registration but that’s out of scope here. Here’s how easy it is to set up Vault Transit for individual signing via the UI:

Basic key creation for direct HMAC

It’s then quick and dirty to generate a new SVG from template with signature. It can then be converted to any other image format. Note that my key type supports HMAC but doesn’t support signatures. The difference is that signatures use asymmetric encryption and can be verified with public keys while HMAC is symmetric encryption only. As these are my images, HMAC is fine and we only take 8 characters of it.

#!/bin/bash
# Usage: secure-badge.sh [NAME] [YEAR]
INPUT=$(echo “$@” | base64)
SIG=$(vault write image-verifiers/hmac/svg-signer \
input=”$INPUT” -format=json)
SIG=$(echo $SIG | jq .data.hmac)
SIG=”#${SIG:10:8}”

sed -i “s/NAME/$1/” template.svg
sed -i “s/YEAR/$2/” template.svg
sed -i “s/SIGNATURE/$SIG/” template.svg

My very own backstage pass for HashiConf EU! Super subtle fingerprint HMAC in the bottom right corner.

It’s simple to create a key for HMAC hashing. This is standard Vault. The HMAC operation can then be applied by CLI or REST API using a valid token to generate consistent secure hashes of our data. In order to verify signatures, I can re-generate a signature for what I’m expecting and compare it to what the image shows. For simplicity, this signature can be watermarked via Imagemagick or the image tool of your choice. Just so long as the signature is legible. If you’re really up for it, you can watermark a QR code version of the signature or even employ NFC or RFID tags.

What about the chain option? If I start a chain of image files, I need to start with a seed. In my case, I’ll start with a plain old “hello world” message which simulates my first image. In order to verify the original image in the chain, I’ll need to have this exact phrase handy. In this case, we use RSA-2048 which is asymmetric and allows signing. That means the general public can verify images via our public keys if they have the previous image in the chain.

Creating a chain key plus initial seed for the first image.

Now I’ll create a signer script for the chain images. Note this is very proof-of-concept and doesn’t do much error checking. It assumes a local symlink “last-hash” that points to our last hashed image. It has Vault sign the image with our key which we extract into a QR code and then watermark onto our image. After that, it makes our new signed image the new last-hash symlink. I can then take out my phone and snap the QR code from the bottom left corner of any image which is my Vault signature which can be verified via the public keys. If this were a real project it would make sense to combine this signing and verification all into a single mobile app and central verification.

#!/bin/bash
# Note requirement: ./last-hash is a symlink to the previous file or seed text.
# Usage: sign-image.sh [IMAGE FILE]

LAST=$(readlink -f last-hash)
cat last-hash | base64 -w 0 > last-base64

# Get signature from the last image/block
SIG=$(vault write image-verifiers/sign/chain-signer/sha2–256 input=@last-base64 -format=json)
SIG=$(echo “$SIG” | jq -r .data.signature)

# Generate small qrcode PNG from last image
qrencode -s 1 -o qr.png “$SIG”

# Now watermark last image signature onto our image
composite -watermark 50% -gravity southwest -geometry +4+4 qr.png “$1” “$1-sig.jpg”

# Now make our image the last image
ln -sf “$1-sig.jpg” last-hash
echo “Signed ‘$1’ from ‘$LAST’. ‘$1-sig.jpg’ is new last-hash.”

I can show a demo of this using an atrocious GIF and some witchcraft with some random images which ironically I don’t own the copyright to. I’ll sequence some images and sign them in order. Each one will get a local copy with a QR code fingerprint in the bottom left corner which can easily be scanned with QR scanning apps and then verified by Vault (done below). If any byte of these signed images has been altered including metadata with copyright, date or location, Vault can tell me.

Ugly GIF but it demonstrates secure signing of images with Vault. Note I’m using fish shell, not bash.

Conclusion

What started out as a secure badge project has mushroomed into a really interesting use case for Vault in the field of tamper detection and blockchain. It isn’t a complete blockchain solution but it’s a very good start to one and may be applicable in your business.

HashiCorp Solutions Engineering Blog

A Community Blog by the Solutions Engineers of HashiCorp and Invited Guests

John Boero

Written by

HashiCorp Solutions Engineering Blog

A Community Blog by the Solutions Engineers of HashiCorp and Invited Guests

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade