Secure transmission of secrets both internally as well as with partnering start-ups and enterprises
There are many ways to securely share private messages and secrets: PGP/GnuPG, S/MIME and different homegrown or commercial solutions.
In a perfect world all our partners (others would call them customers but we view our relation differently) would agree on a standard when it comes to exchanging sensitive information. Some settled on S/MIME, others on PGP, many run their own web-based tools and few don’t have any procedure in place. This makes it difficult for us to communicate efficiently and fast in a secure way.
A big challenge in terms of communication for our CSM (Customer Success Management) and TAM (Technical Account Management) faculties is the distribution of an initial set of credentials for our product APIs (e.g. Gini Pay). At this point we often have no established communication paths and we want our partners to get started quickly without putting their credentials at risk.
. . .
How we started (and this may shock you)
In the beginning of a new partnership we mostly interact with the product specialists at our future partner and encryption is a difficult topic at this stage. To overcome this deadlock we adopted a pattern that offered at least some benefits compared to plain-text emails: Splitting the secrets and using 2 communication channels.
Depending on the partner this could mean any combination of E-Mail, SMS, talking on the phone or sending a fax. You read that right – the fax.
We were in dire need for a secure solution that would work for all partner stages and scenarios.
Version 1 – burn after reading
It started as a side project and became quickly the tool of choice for secret message exchange here at Gini: Burn after reading.
The idea is old (and recently reused in Gmail’s “message with expiration” feature) and is as follows:
- You generate a unique URL that you can send your partner in plaintext (e.g. email)
- Your partner can open the URL in their browser but only once
- After the link was visited the message is “burned” and cannot be accessed again
Photo by Antony Xia on Unsplash
The prototype was a small TLS protected web app built in Go and powered by a nice in-memory key-value store named go-cache written by Patrick Mylund Nielsen. The k/v store offered automatic expiration of items after a given amount of time and we removed the item from the store when the partner viewed it. If someone intercepted the email and viewed the credentials we would know (the secret would be gone) and could act accordingly.
The experience was already great and it was a big improvement to our previous procedure but it also had some downsides:
- Secrets are held in memory and re-deploying or restarting the server wiped the data
- Data was stored unencrypted in memory
It was time for a reimplementation with a bigger focus on security and this is where Vault enters the stage.
Version 2 – powered by Vault
Around that time we were experimenting a lot with Vault from HashiCorp and if you haven’t tried it yet you should start today. Using Vault for our reimplementation gave us a lot of benefits right away:
- Data is no longer tied to a single server instance
- Secure persistence for messages in the k/v store
- Prevent simple probing for secrets with HMAC
- Automatic expiration of tokens (and associated messages)
- High Availability setup and improved scalability
Warning! We will now cover some details of the Vault integration. If you’re feeling lost, head over to the excellent Vault documentation and guides, and don’t forget to come back!
How secrets are born and how they fade away:
The birth of a secret
- When a new secret is added in the web interface the server a new Vault token. This token has a Time To Live (TTL)that will ensure an unread message is automatically deleted after a number of uses. The TTL can be set as needed.
- The number of uses is always 2 (1 to write something to the store + 1 to get it back later).
- The actual set of credentials is written to the Cubbyhole Vault backend. Every token has it own Cubbyhole and that makes it the perfect backend for our secrets. This enforces a clear separation of the stored secrets — having access to a token doesn’t put other secrets at risk.
- Additional metadata parameters are stored in a special section in a shared k/v backend The reason for this is that these parameters need to be read before the secret is fetched from Cubbyhole (e.g. is an accepted GDPR statement required before the secret is revealed?).
- A unique link is generated from the token followed by the HMAC of the token and distributed to the partner.
Burn it with fire
- The partner clicks on the TLS protected link and the server renders a HTML page with a reveal button.
- When the button is clicked the server extracts the token and HMAC from the URL and verifies the HMAC. It uses the Vault transit backendto store the HMAC key and do the verification. This adds an extra layer of protection to the secret.
- Once the token is validated it is used to read the secret from Cubbyhole. The token is automatically invalidated as the number of uses is now exhausted.
- A HTML page is rendered and the secret is shown to the partner.
Time for some screenshots
This is the input screen in our internal self-service portal. We use the slack webhook integration to get notified when a secret is revealed.

Creating a new secret
This is the welcome screen the partner sees when the link is opened.

The welcome screen for our partners.
Time to reveal the secret.

The secret is revealed
Wrap it up
It’s just a small tool we built to overcome a challenge we were facing in the B2B2C market but it really proved valuable to us.
We integrated Vault and “Burn after reading” into our internal self-service portal and both fit each other perfectly. The feedback from internal users and partners was great so far and we have yet to find a partner that can’t use it.
Vault proved to be very flexible and made it easy to apply good security principles to our implementation. It’s soothing to be able to delegate crypto operations to a tool specifically designed for this purpose.
Write us a message if you’d like to know more about the technical details of the implementation or if you have other questions. We’re happy to answer them all.
. . .
If you’re into these kind of challenges and read this far, you should probably check out our open positions. We are looking for excellent tech people to join us.
At Gini, we want our posts, articles, guides, white papers and press releases to reach everyone. Therefore, we emphasize that both female, male, and other gender identities are explicitly addressed in them. All references to persons refer to all genders, even when the generic masculine is used in content.