You're on the right track, but that implementation is way more complicated than it needs to be. Any PIN should be handled by the device itself, and should be easy to change to any arbitrary PIN. Or you might even use a fingerprint reader.
You should be able to basically eliminate any additional risk from a modified device or payment terminal (except perhaps the risk of someone physically stealing the device and using it) by doing the crypto as follows:
- The business generates the transaction receipt and signs it with its public key.
- The user pushes the button on the card to initiate the payment handshake. This causes the device to broadcast a Bluetooth Low Energy beacon.
- The payment terminal (computer, POS terminal, cell phone) detects the beacon and sends the transaction receipt to the card.
- The device shows the business info, dollar amount, etc. on its screen.
- The user presses a button to authorize the transaction.
- The device signs the transaction using its private key and sends its response back to the payment terminal.
- The payment terminal sends the doubly signed receipt back to a payment processor.
- The payment processor verifies the signatures using public keys stored in the business's account and the user's account and verifies whether funds are available.
- The payment processor sends back a signed response containing the transaction receipt and a status field that indicates whether the transaction was authorized or not.
- The payment terminal provides the signed response to the device so that the user can verify that the payment was accepted or rejected. (This prevents double charging fraud.)
- If the signatures are valid and funds are available, the payment processor automatically transfers the funds to the business.
In an ideal world, the transaction would then be applied to the default credit card in your online account profile, but you should have the ability (up to a few days after the transaction) to redirect the transaction to a different card by logging in to your online payments account and saying "Bill it to X". Alternatively, you could have multiple PK pairs, one for each account, and you could choose the account on the device itself.
The way you handle offline sales with this model is also pretty straightforward. You use either a mobile app on your phone or a website on your computer (requires browser support), as follows:
- Enter the name of the business.
- The payment app provides a list of matching businesses. Choose the right one.
- Enter the amount of the payment.
- The payment app generates a transaction.
- You push a button on the device, and the payment app does the BTLE handshake.
- You push another button to authorize the transaction, and the payment app sends it to the payment processor.
- The payment app issues a funds hold against your account and gives you a unique transaction ID for that hold. You give that transaction ID to the store.
- The store, upon accepting the order, uses that transaction ID to convert the hold into an actual charge.
The existence of that transaction ID in the merchant's account is proof that the payment occurred. At most, the only thing the merchant would have to do to prevent fraud would be to ensure that nobody uses the same transaction ID to pay for more than one purchase. This is, of course, a trivial local database lookup.
You would also need an app (mobile or desktop) that can download the public key from the device (if the device gets stolen, you'll need to associate the new device's public key with your payment account) and occasionally update its firmware to fix any bugs in the crypto code.