RSA Publickey implemenation in android

1.8k views Asked by At

I have implemented RSA cryptography using in php, javascript, and android app using library:

  1. phpseclib for php side

  2. pidcrypt for javascript

  3. 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-----
  1. 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;
 }
  1. 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 ---

  1. 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.

1

There are 1 answers

0
Asif Bakht On BEST ANSWER

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

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(plainText.getBytes("UTF-8"));//
byte[] coded = Base64.encodeBase64(encryptedBytes);  //used library encode decode
String encryptedData = new String(encodedBytes);

second last line was to encode the cipher binary data into BASE64

I will learn more about BASE64 differences between JAVA and PHP

Thanks