[Ethereum] Public / Private Key use case

private-keypublic-keysolidityweb3js

I want to generate a large number of single user private/ public key pairs and store the public keys in a smart contract. Private keys will be distributed non electronically to users. If a user inputs a successfully private key (via a Dapp) and that key unlocks the public key, they will be rewarded with some ETH from the smart contract.

Steps have been broken down as follows:

  1. Generate private and public key pairs 1000+.
  2. Public Keys are stored in a smart contract
  3. Private Keys are distributed non-digitally to users (lets say printed on paper)
  4. A user coming from some address interacts with our DApp with the aid of MIST and enters the private key they have received.
  5. DApp sends the TX to the smart contract. Since interaction with DApp is via MIST the msg.sender will be the users address.

As far as I can see there are two possible solutions, to verifying the private/public key combo and sending a reward to msg.sender:

a. A public key is generated from the private key on-chain (let's say using https://github.com/jbaylina/ecsol). If they are a match. Remove public key from the contract and payout msg.sender.

OR

b. Before sending the TX to the smart contract, generate a public key from the private key off-chain (inside our DAPP). Check against the public key in the smart contract. If they are a match.. Payout.

The problem I'm having is choosing between a. and b. Each one has a downside:

a. Performing decrypt on chain is costly. But at least we know msg.sender (where to release the funds to) which is difficult to determine in b.
OK so I reveal the private/public key combo, but since each private and public key combo are unique, exposing one private key should not affect the integrity of the remaining ones. Public / Private key combos are unique and will be single use.

b. Once I verify the public/private key are a match offchain how can I then let the contract know that the decryption was a success and that it should release funds to msg.sender? In my mind ideally this would occur via a callback.. For example: decrypt off chain, if successful, callback and release funds to calling address. But solidity doesn't offer this functionality. Perhaps I could sign the and validate the transaction for example using (https://medium.com/@angellopozo/ethereum-signing-and-validating-13a2d7cb0ee3). So I record the match came from msg.sender and then get my Dapp to send another request which will trigger a msg.sender.transfer ?

I should note that we do not know the user address beforehand (and in fact it can be any ETH address).

I hope my question clear. Perhaps I'm missing something? Thoughts?

Best Answer

  1. Store in the contract the address generated from the private key for each user.

  2. Send users the generated private key.

  3. Dapp signs a static message with the generated private key.

  4. Contracts uses ecrecover with signed message from dapp, validates the address is stored in the contract.

In 4 you can associate the user address with the address generated by you.