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:
- Generate private and public key pairs 1000+.
- Public Keys are stored in a smart contract
- Private Keys are distributed non-digitally to users (lets say printed on paper)
- A user coming from some address interacts with our DApp with the aid of MIST and enters the private key they have received.
- 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?