Search code examples
securitycryptographypkcs#11hsmsofthsm

Using a HSM to store 'master keys' - how?


I'm using softHSM (FWIW with a go library https://github.com/ThalesIgnite/crypto11, documentation here https://pkg.go.dev/github.com/ThalesIgnite/crypto11?tab=doc).

My goal is to store a 'master key' (AES256) for encrypting objects similarly to how AWS S3 does into the HSM device (because it's more secure). From that key, just derive any other key that I need to encrypt my objects (or decrypt them).

I'm failing at understanding how a generated secret key in a HSM can later be retrieved by the same software program. I see that the API mentions of a context..

rephrased: when I generate a secret key in the HSM like this:

func TestFindingAllKeys(t *testing.T) {
    withContext(t, func(ctx *Context) {
        for i := 0; i < 10; i++ {
            id := randomBytes()
            key, err := ctx.GenerateSecretKey(id, 128, CipherAES)
            require.NoError(t, err)

            defer func(k *SecretKey) { _ = k.Delete() }(key)
        }

        keys, err := ctx.FindAllKeys()
        require.NoError(t, err)
        require.NotNil(t, keys)

        require.Len(t, keys, 10)
    })
}

how do I 'associate' one of those secret keys with my program data (e.g. a S3 bucket or customer)? How do I retrieve that same secret key again (even if I can't dump it out of the HSM) to decrypt the data at a later time?

I'm missing this apparently stupid, but crucial connection: how does one retrieve a previously generated secret key again at a later time?


Solution

  • You can use pkcs#11 token labels, or equivalent to tag symmetric keys. You could also use the slot concept, keeping a local database mapping users/customers to keys.

    For asymmetric primitives you can export the public key and map this object to a customer/user.