I have implemented RSA cryptography using in php, javascript, and android app using library:
phpseclib for php side
pidcrypt for javascript
bouncrycastle version(bcprov-jdk14-151) for anrdroid serviceprovider
I have my cryptography mechanism like:
user->request->publickey
->server->generate(publickey,privatekey) and save private key into Database
->server->sendpublickey->user
->user->encryptdata->send->server->decrypt
however this mechanism works fine between javascript and php encryption and decryption but in android platform when server send public key. It cannot decrypt the public key.
now I have tested different scenario for this
PHP KeyGenerating
$rsa = new Crypt_RSA();
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
define('CRYPT_RSA_EXPONENT', 65537);
extract($rsa->createKey(1024));
PHP DecryptingCode
$rsa = new Crypt_RSA();
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
$rsa->loadKey($pri);
$binaryCiphertext=base64_decode($encrypted);
$strBase64DecryptedData=$rsa->decrypt($binaryCiphertext);
$plaintText = base64_decode($strBase64DecryptedData);
as my public key is.
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALrBdN8F83hT2+pBsAwiNx+v3FWp51IdEElE8UvVhfZYmePbitpzLcJi
jZ4/tvRFXJGhqa3PKPUQkH2F4VrHruA2kNceiL/Btywc9oM+tDMeX1jcRKwXwK1k
KdccKwn0qywG6YxQuqWQIotOfV+IIuhcHdaHBl6CZ05/cBo6AlMlAgMBAAE=
-----END RSA PUBLIC KEY-----
request key from server and server generates publickey and private key and send public key MODULUS and EXPONENT to android app and apply this code:
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(mod,exp); KeyFactory keyFactory = KeyFactory.getInstance("RSA","BS"); PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec); Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BS"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = cipher.doFinal(plaintText.getBytes()); byte[] encodedBytes = org.bouncycastle.util.encoders.Base64.encode(encryptedBytes); String encryptedData = new String(encodedBytes);
this code unable to decrypt message and I get this error from PHP SIDE
Decryption error in /security/RSA.php on line **2493**
RSA.php 2493 code
if (ord($em[0]) != 0 || ord($em[1]) > 2) {
user_error('Decryption error');
return false;
}
Second scenario is getting the publick key string and parse it
byte[] keyBytes = Base64.decode(keyString, Base64.DEFAULT); String rsaPublicKeyString = new String(keyBytes); String sliceKeyHeader = rsaPublicKeyString.replaceAll("(-+BEGIN RSA PUBLIC KEY-+\\r?\\n|-+END RSA PUBLICKEY-+\\r?\\n?)", ""); byte[] encodedDER = Base64.encode(sliceKeyHeader.getBytes(),Base64.DEFAULT); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedDER); KeyFactory kf = KeyFactory.getInstance("RSA","BC"); PublicKey pkPublic = (PublicKey) kf.generatePublic(publicKeySpec);
with this I get error
java.security.spec.InvalidKeySpecException:
java.lang.ClassCastException: com.android.org.bouncycastle.asn1.DERApplicationSpecific
cannot be cast to com.android.org.bouncycastle.asn1.ASN1Sequence
I know that the encoded public key is DER encoded but still i dont know what to do here --- I think someone can guide me with DER encode decode ---
The third scenario is
final Reader reader = new StringReader(rsaPublicKeyString); PemReader pemReader = new PemReader(reader); PemObject pemObject= pemReader.readPemObject(); pemReader.close(); AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(pemObject.getContent());
I forgot the error it was like
unable to cast pemObject to asymmetric ( not sure but something like that )
I even tried some of the codes from the below links but I am getting different errors.
RSA Android Encrypt / RSA PHP Decrypt PhpSeclib <-> BouncyCastle RSA
Please look into code and help me.
OK After several hours to work on with EXPONENT and MODULUS I have successfully encrypt and decrypt data between android app and php server here is the solution that might become handy to someone
my mistake was that when cipher data is ready to encode i was using JAVA internal BASE64 class which generates x2 size encoded data and php have different decoding and encoding mechanism (i am not to much sure about that just a guess)
so to void that i used APACHE commons-codec-1.8 library here is the correct code
second last line was to encode the cipher binary data into BASE64
I will learn more about BASE64 differences between JAVA and PHP
Thanks