1

I have an app dealing with money transactions so it's very important to have security. I use passwords and some other tricks when the user sends requests to my php file, but I want to know if it is possible to somehow let the php file verify that the POST method sends Only from my app and Volley?

I don't want to accept requests from web pages or anything else; only my request With Android Volley Proceeded.

P.S : Send a Values from POST method and check on PHP to identify is Not a Safe Method, and easily can hacked.

Kjartan
  • 18,591
  • 15
  • 71
  • 96
ali 22
  • 21
  • 3

2 Answers2

1

When you are sending your request from android, encrypt your payload using some encryption, probably RSA, and then decrypt that request on your server side, if decrypted successfully, you can be sure that the request is genuine and is not altered.

Generate a private key file in PHP

$config = array(
   "digest_alg" => "sha512",
   "private_key_bits" => 4096,
   "private_key_type" => OPENSSL_KEYTYPE_RSA,
);
$keys = openssl_pkey_new($config);
$priv = openssl_pkey_get_private($keys);
openssl_pkey_export_to_file($priv, 'private.pem');

Generate a public .der-file from the private key file with OpenSSL

openssl rsa -in private.pem -pubout -outform DER -out public.der

Import and use the public key in Java (Android side):

File pubKeyFile = new File("public.der");
DataInputStream dis = new DataInputStream(new FileInputStream(pubKeyFile));
byte[] keyBytes = new byte[(int) pubKeyFile.length()];

dis.readFully(keyBytes);
dis.close();

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKey publicKey = (RSAPublicKey)keyFactory.generatePublic(keySpec);

Encode your payload in Android (get bytes according to your requirement)

Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
String payload = "tejashwi kalp taru";
byte[] encryptedBytes = Base64.getEncoder().encode(cipher.doFinal(payload.getBytes()));
String encryptedData = new String(encryptedBytes));
//send encryptedData to server for decryption

Decrypt your payload in PHP:

$fp = fopen("private.pem", "r");
$privateKey = fread($fp, 8192);
fclose($fp);

$res = openssl_get_privatekey($privateKey);
$cipher = base64_decode($cipher);
openssl_private_decrypt( $cipher, $decrypted, $res, OPENSSL_PKCS1_OAEP_PADDING );

// $decrypted is the result

Git repo for demo: https://github.com/tejashwikalptaru/encrypted-communication

Tejashwi Kalp Taru
  • 2,994
  • 2
  • 20
  • 35
0

Generally, no. Can't be done. Whatever your app does, someone can do the exact same thing without using your app.

You can make it hard to replicate what your app does, though. Using encryption, as already suggested, accomplishes this: attacker would have to extract the key from your app and replicate your encryption logic.

In similar vein, you can set custom headers, you can check other headers match what your app would send, you can check details of the payload to see if they match what the app would send, and so on. Any of these make it harder to construct a request that would pass as legitimate, but none would prevent it.

Some attack vectors can be prevented, though: for example, if you specifically want to prevent requests from unmodified web browsers, you can check headers that can't be set from Javascript: https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name

Niko Kiirala
  • 194
  • 3