Algorithm of choice was RSA and the most important part is to use "RSA/ECB/PKCS1PADDING" algorithm when calling Cipher instance in Java, other stuff is pretty straightforward.
RSA works like this. |
As you can see, Alice encrypts data with Bob's public key, and only Bob can decrypt it, because only he has his private key.
Here's the Java code (Warning, some Android elements ahead)
public class Encryption { private static Key privKey; private static PublicKey pubKey; private static PublicKey servPub; private static String tag = "Encryption"; private static String[] alg = {"RSA","RSA/ECB/PKCS1PADDING"}; private static String hash = "SHA1";
private static String serverPubKeyB64 = ""; //Bob's public key here public static String encrypt(String data) { return b64(encrpyt(data.getBytes())); } public static byte[] encrpyt(byte[] data) { genKey(); try { Cipher c1 = Cipher.getInstance(alg[1]); c1.init(Cipher.ENCRYPT_MODE, getServPub()); return c1.doFinal(data); } catch(Exception e) { Log.e(tag, "encrpyt", e); } return new byte[0]; } public static void genKey() { if (privKey == null || pubKey == null) { Log.i(tag, "generating key"); try { KeyPairGenerator kpg = KeyPairGenerator.getInstance(alg[0]); kpg.initialize(1024); KeyPair kp = kpg.generateKeyPair(); privKey = kp.getPrivate(); pubKey = kp.getPublic(); } catch (Exception e) { Log.e(tag, "genKey", e); } } } public static PublicKey getServPub() { if(servPub == null) { try { byte[] encodedPublicKey = b64decode(serverPubKeyB64); KeyFactory keyFactory = KeyFactory.getInstance(alg[0]); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); return publicKey; } catch(Exception e) { Log.e(tag, "getServPub", e); } } return servPub; } public static PublicKey getPubKey() { genKey(); return pubKey; } public static String getPubKeyB64() { PublicKey key = getPubKey(); if(key != null) { return b64(getPubKey().getEncoded()); } else { Log.e(tag, "getPubKeyB64 - key is null"); return ""; } } public static String b64(byte[] b) { return Base64.encodeToString(b, Base64.DEFAULT); } public static byte[] b64decode(String str) { return Base64.decode(str, Base64.DEFAULT); } public static String sha1(String data) { return sha1(data.getBytes()); } public static String sha1(byte[] data) { return formatString(sha1bytes(data)); } public static byte[] sha1bytes(byte[] data) { try { MessageDigest md = MessageDigest.getInstance(hash); return md.digest(data); } catch(Exception e) { Log.e(tag, "sha1", e); return new byte[0]; } } @SuppressLint("DefaultLocale") public static String formatString(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { sb.append(String.format("%02X", b)); } return sb.toString().toLowerCase(); } }And the PHP code:
class Encryption { public $pubkey = '...'; public $privkey; public function __construct() { $this->privkey = openssl_pkey_get_private(file_get_contents('....pem')); } public function encrypt($data) { if (openssl_public_encrypt($data, $encrypted, $this->pubkey)) $data = base64_encode($encrypted); else throw new Exception('Unable to encrypt data.'); return $data; } public function decrypt($data) { if (openssl_private_decrypt(base64_decode($data), $decrypted, $this->privkey)) $data = $decrypted; else $data = ''; return $data; } }
5 comments:
Personally I prefer phpseclib's RSA implementation. It's OOP API is easier to understand IMHO and it supports a ton more key formats. And if just works. OpenSSL is on a lot of shared hosts but not all and on those that it is sometimes there's no openssl.cnf file. phpseclib just works. http://phpseclib.sourceforge.net/
Uh, where were you a week ago! :) Thanks for this. Will come in handy. Using symmetric encryption between Java and PHP I had to jump through hoops, just using mcrypt library in PHP wasn't enough because it didn't support PKCS5 padding (and un-padding), which I had to then implement myself, or rather, find the code for it.
Great post, thanks dude! :)
how I can to create privKey and pubKey?
You can generate a keypair with openSSL. https://en.wikibooks.org/wiki/Cryptography/Generate_a_keypair_using_OpenSSL
Post a Comment