A group of bankers will store sensitive financial information on a server owned by a third party. I represent the 3rd party server.

The financial information will be stored as plain text on the server except that the customer's Account Numbers will be encrypted. The banks do not want us to know their customers' account numbers.

My question is, how safe is it to use the Account Number as a nonce if it is also the message being encrypted when using AES-GCM? So, how safe is it to encrypt as follows: AES-GCM[Key, Nonce = AccountNumber, Message = Account Number].

I know this is an example of deterministic encryption and it would be best to use GCM-SIV mode but I cannot find any libraries that implement this encryption that I can use with the .NET Framework.

On a side note, has anyone ever used Miscreant .NET? As far as I know it has not received FIPS compliance.

Here is an example of the design:

Banker's Data: 
Note, that the AccountNumber is a primary key and will not be repeated.  Therefore, nonce = message = AccountNumber will never be repeated.

PK*AccountNumber   Balance     Nonce
1                  $10,000     1
2                  $15,000     2
3                  $20,000     3

3rd Party Server
AccountNumber   Balance
A2B3C4          $10,000
T4K8S9          $15,000
L6D9S8          $20,000

If the Banker wants to query the 3rd party server for the balance of AccountNumber = 1, he will query the server for AES-GCM(Key,Nonce=1,Message=1)='A2B3C4'. Since only the banker knows the Key and AccountNumber only he can know which record to query for. This is in essence a zero-knowledge encryption scheme where only the Banker has any knowledge of the key, nonce or message.

  • $\begingroup$ Welcome to cryptoSE! What is the reason for encrypting the Customers Id? Does it make a difference since the IDs are just numbers and no other cusotomer information is encrypted? $\endgroup$ – Marc Ilunga Mar 6 '19 at 8:57
  • $\begingroup$ Hi Mark, I'm trying to create zero knowledge system where the 3rd party [represented by me] has no knowledge of the customer's identity. With the design I describe, I can analyze customer spending for example and alert the bankers to possible loan defaults without having to know the identity of the customers. $\endgroup$ – user66406 Mar 7 '19 at 1:34
  • $\begingroup$ I see... But are you also encrypting the balances? If not then it's doesn't make a lot of difference. What I mean is that asking for balance of client "1" is not much different than asking for client "A2B3C4" if the third party doesn't know the link to real identities. The only scenario where this could be interesting would be if the clients of the bank are order by last name per say and the third party has somehow access to the list of bank's clients. In that case wouldn't unique random ids be enough if the bank keeps secret the link the real identities? $\endgroup$ – Marc Ilunga Mar 7 '19 at 12:45
  • $\begingroup$ While it is true that the bank alone holds the customer table used to identify customers, the customer ID is more like a bank account number. The banks I work with would prefer we didn't have access to these bank account numbers. I think the premise we are working on is we want to know and store as little about the customer on our end as possible. ie I can't encrypt balance because that's what we're analyzing but I can encrypt the customer id \ bank account number. $\endgroup$ – user66406 Mar 11 '19 at 20:20
  • 1
    $\begingroup$ How does the recipient of a ciphertext act on it? Presumably either (a) the recipient already knows the message, in which case—why does the recipient need to know the ciphertext?; or (b) the recipient does not know the message, in which case—how does the recipient decide under which nonce to verify and/or decrypt it? $\endgroup$ – Squeamish Ossifrage Mar 13 '19 at 3:58

I think this is a bad idea for a few reasons:

  • In GCM mode, if you encrypt two messages with the same nonce, then the messages' plaintexts may be retrievable from the ciphertexts. So if you have two different messages about the same customer that both use the customer id as the nonce, then your encryption may be broken.

  • When a user retrieves a ciphertext, how will they know the customer ID to use as the nonce? Usually the nonce is included with the ciphertext so that the user can use it with the key to decrypt the ciphertext, but if you do this, then the customer ID will be in plaintext.

Is there some reason that you don't want to use a random nonce as is normally done? If there isn't a specific reason to go off the standard path, then you should avoid doing so.

| improve this answer | |
  • $\begingroup$ Hi, please see the edit to my post. Does this make things more clear? $\endgroup$ – user66406 Mar 6 '19 at 3:02

You don’t need encryption to accomplish your goal. A more secure solution is for the bank to use a keyed hash function (also known as a pseudo-random function) that isn’t invertible. They bank would keep the key secret from you.

The standard PRF in 2019 would be HMAC-SHA256. So the bank would send you HMAC_SHA256(key,account_number) instead of the actual account number. The bank would be able to do lookups (typically called “point queries”, meaning exact-match queries) via account number by computing the HMAC first.

For what it’s worth, I know from personal experience this exact solution is already used at large scale in the banking industry. The HMACs are truncated to 128 bits and stored as UUIDs in practice. Banks often use a different key with each of their interchange partners to prevent correlation.

| improve this answer | |
  • $\begingroup$ I wanted to use encryption so that the Banker's could decrypt the Account Numbers on the client side. For example, if the banker executed an API call that returned a list of accounts using encryption he could determine which Account Numbers were returned without having to maintain a lookup table on the client side. $\endgroup$ – user66406 Mar 13 '19 at 6:09
  • $\begingroup$ I would appreciate your response to one other question. Where do banks store their private key typically? Let's say they have 1,000 bankers on 1,000 different desktop computers within a windows domain. If every one of them needs to query our database and needs access to the private key, do they store the private key using Windows Cryptographic Service Provider or a Certificate Store? If so, practically speaking if a malicious person has root control of a domain computer couldn't they get the private key? Is there a solution to this? $\endgroup$ – user66406 Mar 13 '19 at 6:10
  • $\begingroup$ The common case is for the key to be stored with whatever application the bank is using for lookups. These are typically server applications, and secure key storage is platform-specific. Sometimes even mainframe. But the key is kept and used only by a server on the banks side. Note the bank can also just store the mapping of account-> HMAC on their server and not expose the key to anything other than the system which generates the HMACs. $\endgroup$ – rmalayter Mar 13 '19 at 13:11
  • $\begingroup$ Thank you. Your posts were very helpful! $\endgroup$ – user66406 Mar 14 '19 at 5:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.