3

I'm trying to design a wallet, where any number of public keys can be handed out. Say Alice hands out the public keys to receive messages. She doesn't want others to be able to link all of the public keys to the same person. They should each look random, so that giving out N public keys causes a bystander to believe that there are N different people.

I know that this can be done by having a master private key $p_0$, and generate future private keys with something like $p_{i+1} = \text{Hash}(p_i, p_0)$. However, in order to decrypt the message, Alice would have to try every single private key. I'm doing this in a browser and JS Tests with ECC appear to show that it's a bit slow for a UI once you have a dozen or so keys, but doable if Alice can wait a second (Though not ideal). If you're trying to decrypt dozens of messages at a time, this quickly becomes impossible with too many private keys. And at least in my case, I will have to try to decrypt many messages.

What I really want, is to simply have one private key, and any number of desired public keys. Most cryptosystems have specific key-pairs. And while you can simply concatenate a group's Public Keys to get N Private Keys : 1 Public Key (Decryption requiring every individual), there doesn't appear to be well-known algorithm for 1 Private Key : N Public Keys.

The examples mentioned here did not help, because they are all too slow if decryption requires an ECC multiplication.

==

QA Format: I expected to find a solution on this SE, since it didn't seem like a complicated question, but couldn't. Anyway, I'm posing it here to help others / for those who are interested since I thought it was fairly neat.

2 Answers2

5

Here's an idea:

  • Alice's private key is an AES key $k$, which Alice picks randomly. Yes, we're using an AES key as a private key; bear with me a moment...

  • To generate a new public key, Alice picks a random value $r$, and generates the pair $(\text{AES}_k(r), rG)$, which she publishes, and which I will refer to as $(b, H)$. Alice can optionally forget the value $r$ she picked. Alice can generate and publish as many public keys as she needs...

  • To encrypt a message $m$ with this public key $(b, H)$, Bob selects a random value $s$, computes the point $sG$ and the AES key $KDF(sH)$, and outputs the triplet $(b, sG, \text{AES}_{KDF(sH)}(m))$

  • To decrypt $(b, sG, \text{AES}_{KDF(sH)}(m))$, Alice first decrypts $\text{AES}_k^{-1}(b) = r$, (and if that decryption fails, the message wasn't meant for her). Then she computes $r(sG) = s(rG) = sH$, computes $KDF(sH)$, and then decrypts $\text{AES}_{KDF(sH)}(m))$, giving her the message $m$.

Two different public keys from Alice are unlinkable, as the only connection is that they contain the encryption of two different values with the same AES key, and that's indistinguishable from random.

And, all operations take time independent of the number of public keys Alice generates...

(Note: you'll use some authenticating encryption mode of AES, such as AES-GCM...)

poncho
  • 154,064
  • 12
  • 239
  • 382
0

Define HashToPoint(Number) -> Point as a function that maps integers to an even distribution of ECC Points (Which is easily done by hashing to get an x coordinate, and incrementing x until you hit a point where $x^3+ax+b$ is a quadratic residue, and gives a Point with the desired order.)

Have Bob generate a master private key $a$.

To generate a new public key, generate a random integer $r$ (64-bit in my case), and calculate $A = a\text{HashToPoint}(r)$. Broadcast $(A, r)$.

To send to Alice's public key $(A, r)$, follow standard DH. Generate a random private key $t$, and calculate $T = t\text{HashToPoint}(r)$. Save $S = tA$ as the shared secret, and broadcast $(T, \text{Hash}(S))$.

Now, Alice can calculate $S = aT$ only once, and have the shared secret. She checks the hash against the broadcasted hash to know that it was sent to her (Or, she can simply notice that the attempted decryption gives random bytes). This formula works no matter what $(A_i, r_i)$ the sender used.

An eavesdropper cannot know who received the message, so the message contents and the receiver identity are secure.

Now the $O(n)$ receiving algorithm is $O(1)$, and sending remains $O(1)$.