I have a multi-tenant, SaaS application that integrates with an online payment processor. I facilitate processing transactions on behalf of my tenants by storing their secret API keys in my database, and then using those keys to make calls to the payment processor. Each tenant can have one or several user accounts; in order to keep the secret keys secret, each user account has a public/private key pair. The public key is stored unencrypted with the user account, and the private key is stored using AES with a key derived from the user's password. The secret API key is stored with each account, after being encrypted with the user's public key. With this system, if an administrator for the tenant needs to update the secret API key this can easily be done because the new API key can be encrypted and stored with each of that tenant's user's public keys.

This works well for payments that are run by a user who is logged into the system, because the API key can be decrypted on login and used to process payments. The problem is that I would like to provide an end user payment page that my tenants can direct their customers to in order to make payments. The problem is that the API key will not be available to those users, so I won't have a way to run the payments.

Any good suggestions on how to work this out? The best solution I've come up with so far (suggested, in fact, by my non-programmer wife) is to generate a random, "one-time" key and use this to encrypt the API key with AES, then embed that key in the link to the payment page but not store the link (or the key) in the database. When the end user accessed the link the API key could be decrypted and used for that payment, and then that encrypted copy could be deleted from the database. The encrypted copy would also be deleted if the invoice expired, or if the balance was paid through a different method, in order to minimize the possible exposure of having the API key in the database with the decryption keys floating around the internet.

Flaws in this scenario? Other solutions?

In reply to Securing an API secret key by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.