Skip to content

Instantly share code, notes, and snippets.

@stenio123
Last active February 23, 2023 22:16
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stenio123/0ae467df32364efad0ca01d3b9c3e1c5 to your computer and use it in GitHub Desktop.
Save stenio123/0ae467df32364efad0ca01d3b9c3e1c5 to your computer and use it in GitHub Desktop.
Signing a base64 string with Vault Transit Secret Engine

This code shows the steps to enable the transit secret engine, configure a key, and use the sign leveraging Vault.

vault secrets enable transit

# Default key type doesn't support signing
vault write -f transit/keys/my-key type=rsa-4096

# Encode a string as base64
echo -n 'This was created by Stenio, you can trust me!' | openssl base64
# VGhpcyB3YXMgY3JlYXRlZCBieSBTdGVuaW8sIHlvdSBjYW4gdHJ1c3QgbWUh

# Sign the string
vault write transit/sign/my-key input=VGhpcyB3YXMgY3JlYXRlZCBieSBTdGVuaW8sIHlvdSBjYW4gdHJ1c3QgbWUh
# Key          Value
# ---          -----
# signature    vault:v1:I4qAHruYs.....

Now to verify the key:

Client with access to Vault:

# Verify on the receiving end
vault write transit/verify/my-key input=VGhpcyB3YXMgY3JlYXRlZCBieSBTdGVuaW8sIHlvdSBjYW4gdHJ1c3QgbWUh signature=vault:v1:I4qAHruYs.....

Offline client

First, export the PUBLIC key (which can only be using for verification, so not sensitive)

vault read -field=keys transit/keys/my-key

# Output:
# map[1:map[name:rsa-4096 public_key:-----BEGIN PUBLIC KEY-----
# MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw8tAveSMeeRvpqpsahMi
# nEA+CXgHTA4SX5tSFhS5
# ....
# asqmrdS6jA3FStUs8r5ItOECAwEAAQ==
# -----END PUBLIC KEY-----

# Create a file public.key with the content between (and including) "-----BEGIN PUBLIC KEY-----" and "-----END PUBLIC KEY-----"

TODO - openssl command that works
openssl dgst -sha256 -verify public.key -signature in.txt.sha256 in.txt  
@benoitdechateauvieux
Copy link

Hi Stênio,

When you sign, it's important to use the same hash_algorithm and signature_algorithm as OpenSSL.

vault write -format=json transit/sign/my-key input=VGhpcyB3YXMgY3JlYXRlZCBieSBTdGVuaW8sIHlvdSBjYW4gdHJ1c3QgbWUh hash_algorithm=sha2-256 signature_algorithm=pkcs1v15

Then create a file msg.sig.base64 with the signature generated by Vault.
Vault always use base64 so the signature will be returned in base64.

OpenSSL only works with binary data, so you'll have to decode the signature first

openssl base64 -d -A -in msg.sig.base64 -out msg.sig

And then verify the signature of your original message

openssl dgst -sha256 -verify public.key -signature msg.sig msg.txt

@scraimer
Copy link

The very last command to verify the signature didn't work for me, until I told OpenSSL to use PSS padding:

openssl dgst -sha256 -verify public.key -signature msg.sig -sigopt rsa_padding_mode:pss msg.txt

I hope this helps someone else, too :-)

@SergiiDmytruk
Copy link

Alternative way of making it work with OpenSSL is to make Vault sign with signature_algorithm=pkcs1v15, then OpenSSL command doesn't need to be changed.

@stevenzamborsky
Copy link

Here's an end-to-end example of signing with Transit and then verifying with an offline client using openssl.

# Define our plaintext
TEXT="abc123"

# Encode our plaintext with base64
B64_ENCODED_TEXT=$(echo $TEXT | base64)

# Reset the transit secrets engine
vault secrets disable transit
vault secrets enable transit

# Create a key called 'test' using 'rsa-2048'
vault write -f transit/keys/test \
	type='rsa-2048'

# Export the public key from the transit secret engine key named 'test'
PUBLIC_KEY=$(vault read -format=json transit/keys/test | \
	jq -r '.data.keys."1".public_key')

# Sign our base64 encoded text using our transit key named 'test' and
#  capture the signature
SIGNATURE=$(vault write -format=json transit/sign/test/sha2-256 \
	input="$B64_ENCODED_TEXT" \
	signature_algorithm="pss" | \
	jq -r '.data.signature')

# Demonstrate that we can use transit to verify our signature
printf "\nVerifying signature using Vault Transit...\n"
vault write transit/verify/test/sha2-256 \
	signature_algorithm="pss" \
	input=$B64_ENCODED_TEXT \
	signature=$SIGNATURE

# Write out public key to a file
echo $PUBLIC_KEY > publickey.pem

# Remove the metadata from the Vault supplied signature and decode the
#  signature using base64, writing the raw signature to a file
echo $SIGNATURE | cut -d':' -f3 | base64 -d > sig

# Write the non-encoded plaintext to a file
echo "$TEXT" > mytext

# Use openssl to verify the signature using the base64 decoded raw signature
#  along with the public key and the non-encoded plaintext
printf "\nVerifying signature using openssl...\n"
openssl dgst \
	-sha256 \
	-verify publickey.pem \
	-signature sig \
	-sigopt rsa_padding_mode:pss \
	mytext

@utkarshrai003
Copy link

Why am i not able to decode the signature generated by Vault.
My signature looks like this-

vault:v1:Yo5+IGy0waxGvqXouQ8TKAmSVqMbz8FT8IqB1f8DNhMSSVjqNdy0rTc2LMt/qivI98lW5k42VRgzo4F9Rs6/RMu+PZWoJkjtprxqafxbb8j763vDIOP/UkL3emzL8deNJt37A/8s0Yx5AcsfTAIdNBoleM6KFolq0HBNN2xKg3nDsUy+ZoDobnogNGPMBKKApq5w/hORwWQhrZCg0jtpJSSyLlsqEN9det00i4GeI8Oa6dPRasH9QH/uFM+Ciq3vzrbBxSsLjU02kBbz1qu6dewx+jDhl6CEp5EN3zzoq95XHVrwajvlf+kzhHDWNDzbj+s65lW8+gBfXxDSJMC5VQ==

I am trimming vault:v1: and then try to decode the signature to binary, but i am getting weird characters, and I am not able to verify my signature. Happy to provide more details around this.

@stevenzamborsky
Copy link

Hi @utkarshrai003 , you need to be sure that your cryptographic algorithm (sha2-256 in my case) and your signature algorithm (pss in my case) are correct when you're using openssl.

If you can provide an end-to-end example reproducing the issue you're experiencing, we can try to diagnose the issue, otherwise there are too many variables that could cause the issue you describe.

@utkarshrai003
Copy link

Hi @stevenzamborsky , Appreciate your prompt reply.

I am providing more details about this to see if we can point out what's wrong with my understanding here.

Key Details -

bash-4.4# vault read basePath/keys/3a3f5988-3550-44ad-8eaa-73d5bda6f0fb

Key                       Value
---                       -----
allow_plaintext_backup    false
auto_rotate_period        0s
deletion_allowed          true
derived                   false
exportable                false
imported_key              false
keys                      map[1:map[creation_time:2023-02-22T13:46:28.05626551Z name:rsa-2048 public_key:-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4LBJiEeJCo97vozYCb/3
FzAiZr5flOyEC9yYZJ2m9MoYqcyVJSpleHB9Dc+58LE0LFv3eWnsFo7V7NquNJci
+Smd9Ps5GEhgHi55E9XdrujYYmtesSSGA6yi3gbVcjEyNEr0m4vpGJbWdAMST9Cd
9geTAPfvz72jZl6OjD4q0zL9zhjkK24jlFhgMQ+dt3zGLRyhq8E7wtDz07DQ7oxY
2pl9fCMQtLM0zPEN69SYNiN2pVs35bTom4NMWn4VZCeZTz3lIvLp9GSFWOKKxA3E
4CYhIY6aCMwPYqUU1A8fXO+/ZJh7/FRb8gXG/hYH/QEdnX0CpEfTVRPQ2prfkjRi
VQIDAQAB
-----END PUBLIC KEY-----
]]
latest_version            1
min_available_version     0
min_decryption_version    1
min_encryption_version    0
name                      3a3f5988-3550-44ad-8eaa-73d5bda6f0fb
supports_decryption       true
supports_derivation       false
supports_encryption       true
supports_signing          true
type                      rsa-2048

Signature generation -

Input here is base64 encoded string.

vault write basePath/sign/3a3f5988-3550-44ad-8eaa-73d5bda6f0fb input=dXRrYXJzaA== hash_algorithm=sha2-256 signature_algorithm=pss

Signature generated by Vault -

vault:v1:Z3xOWcqdSxJeVeEwLxPlmjoPHk+VEWCpCae1YafFRecZaffVcIDoTU2a+ZatwYqxMxYE6x+KZuud0M2qB0Uhz+GwsmLGke47PZ4qHQQzKeylggUNf++Ige7WFKiF4rBQd+Ijvv008iqvYahxiaQjlRonbJWPyVeANgYrUpSMJkRNjPRnuFAlyK37x9gRXq/iFnRPg4gsTD3R257ijICI8JuSUly7Ic1Vs6s3Kvi9EUV9uby81LdN1x6B57JDO0eXPE5qO/43lTJW/ONDjgRjfLHidUeNIlnyIEa6g6rKYFAE2xD+rMPmYIj771e3COAYrfhys4gfzy7SIAl9o8WNFQ==

Signature is supposed to be Base64 encoded -

I am trimming vault:v1: and then using an online tool to decode this base64 encoded signature to be passed to openssl.
This is what I am getting on decoding this. The tool being used is - https://www.base64decode.org/

g|NYʝK�^U0/�:��O�`	aE�ipMM3���fͪ�E!ᰲbƑ;=*��3)쥂�
��Pw#4*aq#�'lW6�+R&DMgP%ȭ�^�tO,L=۞⌀R\!U7*�E}ԷM�C;G<Nj;72VC�c|uG"Y F`P��`W��r�. 	}ō�

I apologize in advance if I am doing something terribly wrong.

@ram-parameswaran
Copy link

@utkarshrai003 I tried the contents exactly like the example above from @stevenzamborsky on a Mac (Vault running in DEV on Mac and all commands also running on Mac) and it all worked very well. This makes me think its an OS specific issue you are running into. Could you please confirm which OS are you running your tests in?

@ram-parameswaran
Copy link

Oh and the gibberish you see at the end in your post above is not really gibberish but "text" after base64 decoding

@utkarshrai003
Copy link

utkarshrai003 commented Feb 23, 2023

I am using Mac with OS Ventura 13.1.
And I have tested with openssl version - LibreSSL 3.3.6 and openssl 1.1.1

@ram-parameswaran
Copy link

Please try doing the base64 decoding using the command mentioned in Steve's post above, echo $SIGNATURE | cut -d':' -f3 | base64 -d > sig, please note that in this command the trim of the Vault specific prefix is also handled

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment