KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore"); keyPairGenerator.initialize( new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_SIGN) .setDigests(KeyProperties.DIGEST_SHA256) .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1")) .setUserAuthenticationRequired(true) .build()); keyPairGenerator.generateKeyPair();
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); PublicKey publicKey = keyStore.getCertificate(MainActivity.KEY_NAME).getPublicKey(); KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); PrivateKey key = (PrivateKey) keyStore.getKey(KEY_NAME, null);
boolean enroll(String userId, String password, PublicKey publicKey);
Signature signature = cryptoObject.getSignature(); // Include a client nonce in the transaction so that the nonce is also signed // by the private key and the backend can verify that the same nonce can't be used // to prevent replay attacks. Transaction transaction = new Transaction("user", 1, new SecureRandom().nextLong()); try { signature.update(transaction.toByteArray()); byte[] sigBytes = signature.sign(); // Send the transaction and signedTransaction to the dummy backend if (mStoreBackend.verify(transaction, sigBytes)) { mActivity.onPurchased(sigBytes); dismiss(); } else { mActivity.onPurchaseFailed(); dismiss(); } } catch (SignatureException e) { throw new RuntimeException(e); }
@Override public boolean verify(Transaction transaction, byte[] transactionSignature) { try { if (mReceivedTransactions.contains(transaction)) { // It verifies the equality of the transaction including the client nonce // So attackers can't do replay attacks. return false; } mReceivedTransactions.add(transaction); PublicKey publicKey = mPublicKeys.get(transaction.getUserId()); Signature verificationFunction = Signature.getInstance("SHA256withECDSA"); verificationFunction.initVerify(publicKey); verificationFunction.update(transaction.toByteArray()); if (verificationFunction.verify(transactionSignature)) { // Transaction is verified with the public key associated with the user // Do some post purchase processing in the server return true; } } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { // In a real world, better to send some error message to the user } return false; }