Home 0P3N Blog Secure Public Key Encryption: Android Key Generation and Server Encryption
Ready to Start Your Career?
Create Free Account
prometheus s profile image
By: prometheus
July 19, 2016

Secure Public Key Encryption: Android Key Generation and Server Encryption

By: prometheus
July 19, 2016
prometheus s profile image
By: prometheus
July 19, 2016
Secure Public Key Encryption: Android Key Generation and Server Encryption - CybraryHello everyone!This article depicts a specific problem I encountered on one of my recent projects. The main problem was: ONE of my project modules had a specific functionality, which involved key generation on an Android device. The public key is transmitted to the web server, which then uses public key sent to encrypt the requisite secret and display the encrypted secret as a QR code on the desktop. Finally, the Android app we developed decodes the QR code and the private key (which was generated before), then decrypts the cipher to get the secret back.The reverse process had many solutions. But, for my problem, there were bits and pieces everywhere. We found it would be better to generate keys on client app, as it would avoid sending private keys back to client if generated on the server and thus triggering channel breaking attacks.I'll mainly explain the three sub-functions, which were carried out by the main module.
  1. Key pair generation on Android app
  2. Public key encryption on server ( uses RSA algorithm) and encoding cipher to QR code using PHP
  3. QR code decode and decryption of cipher to get the secret generated by the server
 1. Key pair generation on Android appWe mainly use "spongy castle" as our default security provider. It's an alternative to default bouncy castle.If you're developing an app using Android studio like me, and in order to get the required repo module, add these lines to your app gradle:
compile 'com.madgag.spongycastle:core:1.54.0.0'compile 'com.madgag.spongycastle:prov:1.54.0.0'compile 'com.madgag.spongycastle:pkix:1.54.0.0'compile 'com.madgag.spongycastle:pg:1.54.0.0'
The next main thing is to add the following to the main class of the intent you're going to generate keys. This is done to make sure we use spongy castle as our security provider.
static {        Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);    }Let's come to the key pair generation, required code for the key pair generation.try {        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "SC"); //specify the algorithm for generation    generator.initialize(1024); //initialize    KeyPair kPair = generator.generateKeyPair(); //generate a keypair        byte[] privateKeyEnc = kPair.getPrivate().getEncoded(); //store private key as byte stream        byte[] publicKeyEnc = kPair.getPublic().getEncoded(); //store public key as byte stream         publicKey = new String(Base64.encode(publicKeyEnc)); //encode to base64 format and store it as string .this is sent to server         privateKey = new String(Base64.encode(privateKeyEnc)); //encode to base64 format and store it as string     }    catch(Exception e) {        Log.d("failure","fail"); //for debugging    }
2. Public key encryption on server (uses RSA) and encoding cipher to QR code using PHPThe public key is received by the back-end server. We used pure implementation of the RSA algorithm provided by phplibsec library for PHP. We also used the phpqrcode library to encode cipher text into qrcode format.The main code required for the operation:$publicKey = $_POST['pub']; //received from the android app.include('Crypt/RSA.php');   //include phplibsec library$rsa = new Crypt_RSA();$rsa->setHash('sha1');  //set the required parameters for encryption such as hash algorithm$rsa->setMGFHash('sha1');$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP); //follows Optimal asymmetric encryption padding$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1); //set the private key format$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); //set the public key format$key = "-----BEGIN PUBLIC KEY-----n" .($publicKey). '-----END PUBLIC KEY-----';//this is done to adjust key to actual format provided by lib.$rsa->loadKey($key);$messageEncrypt = base64_encode($rsa->encrypt("secret_to_be_shared")); //encrypt the secret to be shared and encode it to base64.include "phpqrcode/qrlib.php"; //include the qrcode library$tempDir = EXAMPLE_TMP_SERVERPATH; //store path for temporary server storage$codeContents = $messageEncrypt;$fileName = 'filename.png'; //custom qrcode file name.this is for test purpose.can be modified to generate for parallel access$pngAbsoluteFilePath = $fileName; //pathnames$urlRelativeFilePath = $fileName;if (!file_exists($pngAbsoluteFilePath)) {QRcode::png($codeContents, $pngAbsoluteFilePath); //qrcode generation and this is displayed on the screen.} 3. QR code decode and decryption of cipher to get the secret generated by the serverIn this sub module, we decode the QR code to get the cipher text and finally decrypt using the private key, which was generated by the Android.-> Don't forget to add spongy castle as a default security provider at the intent, which is used to decipher the cipher text.-> I mainly used a method of calling the QR code app installed already on the mobile device to decode the QR code. I passed the request as an intent. (DM me for the code.)->I received the result and finally decrypt using a private key. Make sure to specify default service provider as spongy castle here, too (in this intent).CODE:byte[] privateKeyBytes = Base64.decode(privatekey); //rivert back to byte streamPKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); //get the keyspec backKeyFactory fact = KeyFactory.getInstance("RSA", "SC"); //specify the required algo and security providerPrivateKey priv = fact.generatePrivate(keySpec);Cipher rsaCipher = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "SC"); //specify parametersrsaCipher.init(Cipher.DECRYPT_MODE, priv);byte[] messageDecoded = Base64.decode(contents); //cipher text resulted from decoding qr code is base64 decoded to byte streambyte[] messageDecryptBytes = rsaCipher.doFinal(messageDecoded); decode the cipher byte streamString messagedecrypt = new String(messageDecryptBytes);  store it as a stringLog.d("decrypteddddd", messagedecrypt); //for logging purpose Finally...we get the secret on the Android device shared only between device and the server.So, why did I use QR encoding as a way of communication between app and server?QR codes are small for temporary storage and they offer additional security measures (they implement security by default). Our project was mainly focused on a new high secure authentication technique, which required faster transmission and additional security (this module is just a part of it). And, we already know two-way authentication can also be vulnerable to high specialized attacks such as social engineering (Mobile is secure!! But, not the carriers delivering such messages? Sigh!!.) Why did I write this article, anyway?There were very few bits and pieces required for the process which we carried out. It would be great to have everything in a single place. It would help fellow security developers.Well, that's it...let me know your suggestions in the comment section below.
Schedule Demo

Build your Cybersecurity or IT Career

Accelerate in your role, earn new certifications, and develop cutting-edge skills using the fastest growing catalog in the industry