Im trying to decrypt a text sent from the server to an android application.
On PHP, I have the following:
$rsa = new Crypt_RSA();
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
$key = "-----BEGIN PUBLIC KEY-----\n" . ($PublicKey)
. '-----END PUBLIC KEY-----';
$rsa->loadKey($key);
$base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);
$imageEncrypt = base64_encode($rsa->encrypt($base64));
The encoding and the encryption work well.
When I send the encrypted text to android, i cannot decrypt. I used the code:
public static String decryptString(String alias,String cipherText) {
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
// RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), output);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
String finalText = new String(bytes, 0, bytes.length, "UTF-8");
return finalText;
//decryptedText.setText(finalText);
} catch (Exception e) {
Toast.makeText(context, "Exception " + e.getMessage() + " occured", Toast.LENGTH_LONG).show();
Log.e("DecryptStringTAG", Log.getStackTraceString(e));
}
return "EMPTY";
}
The error is:
java.io.IOException: Error while finalizing cipher
Caused by: javax.crypto.IllegalBlockSizeException
The odd thing is that when i try to send from PHP a message like "Hello", android decrypts it successfully. But when i send the encrypted image, I get the stated error.
I've been struggling to find the error.
Any help?
Thanks
RSA asymmetric key encryption which is what public key encryption uses, that is RSA is essentially public key encryption. If you must use public/private key pair encryption the answer is hybrid encryption, similar to what SSL does.
Create a random symmetric key use it to encrypt the data with AES. Then encrypt the symmetric key with the RSA public key.
On decryption first decrypt the symmetric key with the RSA private key and use that to decrypt the data with the symmetric AES.
If you are looking for secure encryption you really need to get someone who is a domain expert to at least design and vett the implementation. Security is very hard to get right, if it isn't right is provides no security.
Related
I'm using RSA and AES encryption/Decryption
I create RSA public key and private key in Android
I send public key to PHP server
Utilizing AES encryption, PHP encrypts some large data with a password and utilizing RSA encyption and the received public key, it encodes the password and then returns back the encrypted large data with the password and the encoded encrypted password where the encode function is as following:
base64_encode(the encrypted password)
In Android, I first decode the encoded encrypted password where the decode instruction is as following:Base64.decode(the encoded encrypted password, Base64.DEFAULT)
PHP code is as following:
openssl_public_encrypt($password, $encrypted, $public_key);
$mystr= base64_encode($encrypted);
echo "mystrStart=$mystr mystrEnd\n"; //mystr will be retrieved in Android
Android code is as following:
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] encryptedBytes,decryptedBytes;
encryptedBytes = Base64.decode(mystr, Base64.DEFAULT);
decryptedBytes = cipher.doFinal(encryptedBytes);
String DecryptedPassword = new String(decryptedBytes);
The problem is I see the password at the end of DecryptedPassword but some other junk data before the password is yet seen:
The password in PHP is "Hellooooo"
mystr (the encoded encrypted password) received in Android is as following:
sNfmwifoIEqXQzzge0zOFmBTFPlDqQZkAWqOPtGe3jNuI/zdV4SsCTxzcNZvww5RaaMOZ4ubQWrGXLuyuimKeQ==
The final result (DecryptedPassword) is as following:
����/
+�*#7JY��,��7��$C�-|8�[��p��Ĭ���,9v��}��Hellooooo
edit:
The code is as following:
KeyPairGenerator kpg;
KeyPair kp;
PublicKey publicKey;
final PrivateKey privateKey;
try {
kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
kp = kpg.genKeyPair();
publicKey = kp.getPublic();
privateKey = kp.getPrivate();
byte[] pKbytes = Base64.encode(publicKey.getEncoded(), 0);
String pK = new String(pKbytes);
String pubKey = "-----BEGIN PUBLIC KEY-----\n" + pK + "-----END PUBLIC KEY-----\n";
Log.e(TAG, "pubKey:"+pubKey);
And then this pubKey is saved to a file named U.txt and then sent to the server
SendJSONToServerTest someTask = new SendJSONToServerTest(getApplicationContext(), "FileName"+".txt", PHP_address, getApplicationContext().getFilesDir().getPath() + "/" + "U.txt", new SendJSONToServerTest.OnEventListener<String>() {
#Override
public void onSuccess(String result) {
Log.e(TAG, "log1 = "+result);
String mstr = getBetweenStrings(result,"mystrStart=","mystrEnd");
Log.e(TAG, "log2 = "+mstr);
try {
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] encryptedBytes, decryptedBytes;
encryptedBytes = Base64.decode(mstr, Base64.DEFAULT);
decryptedBytes = cipher.doFinal(encryptedBytes);
String DecryptedPassword = new String(decryptedBytes);
Log.e(TAG, "log3= "+DecryptedPassword);
} catch(GeneralSecurityException e) {
System.out.println(e);
}
Log.e(TAG, "Endddddddddddddd");
}
#Override
public void onFailure(String f) {
Log.e(TAG, "errR.......");
}
});
someTask.execute();
PHP code related to file content:
$fileContentStr = file_get_contents($_FILES["uploaded_file"]["tmp_name"]);
echo "\nfileContentStr = {$fileContentStr}\n";
$public_key = $fileContentStr;
echo "\npublic_key = {$public_key}\n";
I have the same problem and went searching and found the answer here.
Basically, the message is padded and the byte just before your original method is the 0x00 byte (NUL character).
The following code was extracted from the link which removes the padding and returns the original message.
def pkcs1_unpad(text):
if len(text) > 0 and text[0] == '\x02':
# Find end of padding marked by nul
pos = text.find('\x00')
if pos > 0:
return text[pos+1:]
return None
I am decoding the encrypted message in python but it is easy to port it to PHP.
I hope this help you, too.
I am using Swift Sodium on client side as my server is using libsodium to encrypt the data before sharing it with me through API.
Now I have a existing private key and a public key in a String format with me. I want to now decrypt the encrypted data at my end on iOS using Swift.
How do I generate a Sodium Key Pair using the public and private key that I have?
Also Ideally I should use only the private key to decrypt the data. So how do I do that using only private key as String.
My Code for decryption is shown below -
func decryptData(dataString: String) -> String? {
let sodium = Sodium()
let privateKey = sodium?.utils.hex2bin("MY_SECRET_KEY")
let publicKey = sodium?.utils.hex2bin("MY_PUBLIC_KEY")
let message = dataString.data(using: .utf8)!
if let decrypted = sodium?.box.open(anonymousCipherText: message, recipientPublicKey: publicKey!, recipientSecretKey: privateKey!){
// authenticator is valid, decrypted contains the original message
return String(data: decrypted, encoding: String.Encoding.utf8) as String!
}
return nil
}
In the above Code my decrypted String is always empty.
The server is encrypting the data using the below function -
protected function crypt($response)
{
$message = new HiddenString($response);
$repository = \App::make(EncryptionKeysRepository::class);
$enc = $repository->findOneBy(['device' => 'android']);
$dir = $enc->getDevice();
$publicKey = $enc->getPublicKey();
$storage = storage_path();
if(!file_exists($storage."/{$dir}/")) {
mkdir($storage."/{$dir}/");
}
// save key pair to key store
$pubFilename = \tempnam($storage."/{$dir}/", 'pub_key');
file_put_contents($pubFilename, $publicKey);
$public = KeyFactory::loadEncryptionPublicKey($pubFilename);
unlink($pubFilename);
rmdir($storage."/{$dir}/");
$message = Crypto::seal($message, $public);
return $message;
}
Decrypting Logic at server
protected function deCrypt($response)
{
$repository = \App::make(EncryptionKeysRepository::class);
$enc = $repository->findOneBy(['device' => 'android']);
$dir = $enc->getDevice();
$publicKey = $enc->getSecretKey();
$storage = storage_path();
if(!file_exists($storage."/{$dir}/")) {
mkdir($storage."/{$dir}/");
}
// save key pair to key store
$secFilename = \tempnam($storage."/{$dir}/", 'sec_key');
file_put_contents($secFilename, $publicKey);
$secret = KeyFactory::loadEncryptionSecretKey($secFilename);
unlink($secFilename);
rmdir($storage."/{$dir}/");
$res = Crypto::unseal($response, $secret);
$message = $res->getString();
return response()->json(compact('message'));
}
So, server-side, you're apparently using PHP, with a library called Halite.
I'm not very familiar with Halite, but looking at its code, Crypto::seal() uses sealed boxes, so Box::open(anonymousCipherText: Data, recipientPublicKey: PublicKey, recipientSecretKey: SecretKey) -> Data? is the correct method to decrypt this in Swift.
However, Halite also seems to encode the result as a BASE64 string (urlsafe variant).
So, you need to decode this first. Or, and this is going to be way more efficient, do not encode the ciphertext. Unless you have to read them aloud, the keys probably don't need to be encoded either.
I am using RSA encryption with PHPSECLIB and VB.NET. The code for PHP is:
<?php
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$key='-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0
FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/
3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQAB
-----END PUBLIC KEY-----';
$rsa->loadKey($key); // public key
$plaintext = 'HELLO';
//$rsa->setEncryptionMode(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
$rsa->paddable = false;
$ciphertext = $rsa->encrypt($plaintext);
echo base64_encode($ciphertext);
?>
VB.NET CODE:
Public Function DecryptText(ByVal Str As String) As String
Try
'Convert data to byte array
Dim Enc As Encoding = Encoding.UTF8
Dim dataToDecrypt() As Byte = Convert.FromBase64String(Str)
'Make our RSA Container
Dim RSA As New RSACryptoServiceProvider
'Import PRIVATE key into container
RSA.FromXmlString("<RSAKeyValue><Modulus>AKoYq6Q7UN7vOFmPr4fSq2NORXHBMKm8p7h4JnQU+quLRxvYll9cn8OBhIXq9SnCYkbzBVBkqN4ZyMM4vlSWy66wWdwLNYFDtEo1RJ6yZBExIaRVvX/eP6yRnpS1b7m7T2Uc2yPq1DnWzVI+sIGR51s1/ROnQZswkPJHh71PThln</Modulus><Exponent>AQAB</Exponent><P>AN4DDp+IhBca6QEjh4xlm3iexzLajXYrJid6vdWmh4T42nar5nem8Ax39o3ND9b1Zoj41F9zFQmuZ8/AgabreKU=</P><Q>AMQi+R0G9m0K+AcqK3DFpv4RD9jGc0Tle98heNYT7EQvZuuiq4XjvRz0ybqN//bOafrKhsTpRS9DQ7eEpKLI4Bs=</Q><DP>FklyR1uZ/wPJjj611cdBcztlPdqoxssQGnh85BzCj/u3WqBpE2vjvyyvyI5kX6zk7S0ljKtt2jny2+00VsBerQ==</DP><DQ>AJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2eplU9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhM=</DQ><InverseQ>EaiK5KhKNp9SFXuLVwQalvzyHk0FhnNZcZnfuwnlCxb6wnKg117fEfy91eHNTt5PzYPpf+xzD1FnP7/qsIninQ==</InverseQ><D>Fijko56+qGyN8M0RVyaRAXz++xTqHBLh3tx4VgMtrQ+WEgCjhoTwo23KMBAuJGSYnRmoBZM3lMfTKevIkAidPExvYCdm5dYq3XToLkkLv5L2pIIVOFMDG+KESnAFV7l2c+cnzRMW0+b6f8mR1CJzZuxVLL6Q02fvLi55/mbSYxE=</D></RSAKeyValue>")
'Decrypt the data
Dim decryptedData() As Byte = RSA.Decrypt(dataToDecrypt, False)
'Convert output byte array to a string
DecryptText = Enc.GetString(decryptedData)
Catch ex As Exception
Return ""
End Try
End Function
The problem that I am having is that everytime I copy the Base64 output from PHP and sub it on to the VB.NET DecryptText function, I get a blank results with the error "Bad Data". Can someone point me in the right direction here?
I strongly suspect $rsa->setEncryptionMode(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); needs to be uncommented.
Also, $rsa->paddable = false... that's not doing anything. paddable isn't a variable that Crypt_RSA uses. Crypt_Base defines it but Crypt_RSA does not extend Crypt_Base.
I have a web-service in php that generates a keypair to encrypt a message, and one application in java that retrives the privatekey and decrypt the message.
For php I'm using http://phpseclib.sourceforge.net/ and have this two files:
keypair.php
<?php
set_time_limit(0);
if( file_exists('private.key') )
{
echo file_get_contents('private.key');
}
else
{
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->createKey();
$res = $rsa->createKey();
$privateKey = $res['privatekey'];
$publicKey = $res['publickey'];
file_put_contents('public.key', $publicKey);
file_put_contents('private.key', $privateKey);
}
?>
encrypt.php
<?php
include('Crypt/RSA.php');
//header("Content-type: text/plain");
set_time_limit(0);
$rsa = new Crypt_RSA();
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP);
$rsa->loadKey(file_get_contents('public.key')); // public key
$plaintext = 'Hello World!';
$ciphertext = $rsa->encrypt($plaintext);
echo base64_encode($ciphertext);
?>
and in java I have this code:
package com.example.app;
import java.io.DataInputStream;
import java.net.URL;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
public class MainClass {
/**
* #param args
*/
public static void main(String[] args)
{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
try {
BASE64Decoder decoder = new BASE64Decoder();
String b64PrivateKey = getContents("http://localhost/api/keypair.php").trim();
String b64EncryptedStr = getContents("http://localhost/api/encrypt.php").trim();
System.out.println("PrivateKey (b64): " + b64PrivateKey);
System.out.println(" Encrypted (b64): " + b64EncryptedStr);
SecretKeySpec privateKey = new SecretKeySpec( decoder.decodeBuffer(b64PrivateKey) , "AES");
Cipher cipher = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] plainText = decoder.decodeBuffer(b64EncryptedStr);
System.out.println(" Message: " + plainText);
}
catch( Exception e )
{
System.out.println(" Error: " + e.getMessage());
}
}
public static String getContents(String url)
{
try {
String result = "";
String line;
URL u = new URL(url);
DataInputStream theHTML = new DataInputStream(u.openStream());
while ((line = theHTML.readLine()) != null)
result = result + "\n" + line;
return result;
}
catch(Exception e){}
return "";
}
}
My questions are:
Why I'm having a exception saying "not an RSA key!"?
How can I improve this code? I have used base64 to avoid encoding and comunication errors between Java and PHP.
This concept is correct? I mean, I'm using it correctly?
With the help of above answer, I got that SecretKeySpec is used wrong, and I found that PEM file from OpenSSL isn't a 'standart format', so I need to use the PEMReader to convert it to PrivateKey class.
Here is my working class:
package com.example.app;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.StringReader;
import java.net.URL;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Security;
import javax.crypto.Cipher;
import org.bouncycastle.openssl.PEMReader;
import sun.misc.BASE64Decoder;
public class MainClass {
/**
* #param args
*/
public static void main(String[] args)
{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
try {
BASE64Decoder decoder = new BASE64Decoder();
String b64PrivateKey = getContents("http://localhost/api/keypair.php").trim();
String b64EncryptedStr = getContents("http://localhost/api/encrypt.php").trim();
System.out.println("PrivateKey (b64): " + b64PrivateKey);
System.out.println(" Encrypted (b64): " + b64EncryptedStr);
byte[] decodedKey = decoder.decodeBuffer(b64PrivateKey);
byte[] decodedStr = decoder.decodeBuffer(b64EncryptedStr);
PrivateKey privateKey = strToPrivateKey(new String(decodedKey));
Cipher cipher = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] plainText = cipher.doFinal(decodedStr);
System.out.println(" Message: " + new String(plainText));
}
catch( Exception e )
{
System.out.println(" Error: " + e.getMessage());
}
}
public static String getContents(String url)
{
try {
String result = "";
String line;
URL u = new URL(url);
DataInputStream theHTML = new DataInputStream(u.openStream());
while ((line = theHTML.readLine()) != null)
result = result + "\n" + line;
return result;
}
catch(Exception e){}
return "";
}
public static PrivateKey strToPrivateKey(String s)
{
try {
BufferedReader br = new BufferedReader( new StringReader(s) );
PEMReader pr = new PEMReader(br);
KeyPair kp = (KeyPair)pr.readObject();
pr.close();
return kp.getPrivate();
}
catch( Exception e )
{
}
return null;
}
}
Here is my keypair.php
<?php
set_time_limit(0);
if( file_exists('private.key') )
{
echo base64_encode(file_get_contents('private.key'));
}
else
{
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->setHash('sha1');
$rsa->setMGFHash('sha1');
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP);
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
$res = $rsa->createKey(1024);
$privateKey = $res['privatekey'];
$publicKey = $res['publickey'];
file_put_contents('public.key', $publicKey);
file_put_contents('private.key', $privateKey);
echo base64_encode($privateKey);
}
?>
and my encrypt.php
<?php
include('Crypt/RSA.php');
set_time_limit(0);
$rsa = new Crypt_RSA();
$rsa->setHash('sha1');
$rsa->setMGFHash('sha1');
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP);
$rsa->loadKey(file_get_contents('public.key')); // public key
$plaintext = 'Hello World!';
$ciphertext = $rsa->encrypt($plaintext);
$md5 = md5($ciphertext);
file_put_contents('md5.txt', $md5);
file_put_contents('encrypted.txt', base64_encode($ciphertext));
echo base64_encode($ciphertext);
?>
I hope it helps anyone and thanks.
A few thoughts.
Shouldn't you be echo'ing out $privatekey in the else as well?
Are you using the latest Git version of phpseclib? I ask because a while ago there was this commit:
https://github.com/phpseclib/phpseclib/commit/e4ccaef7bf74833891386232946d2168a9e2fce2#phpseclib/Crypt/RSA.php
The commit was inspired by https://stackoverflow.com/a/13908986/569976
Might be worthwhile if you change your tags up a bit to include bouncycastle and phpseclib. I'd add those tags but some tags will have to be removed since you're already at the limit of 5. I'll let you decide which ones to remove (if you even want to do that).
SecretKeySpec privateKey = new SecretKeySpec( decoder.decodeBuffer(b64PrivateKey) , "AES");
b64PrivateKey is supposed to contain the private key right? 'cause looking it up in the docs it looks like SecretKeySpec is only intended for symmetric algorithms (like AES) - not asymmetric ones like RSA.
I did some digging into the classes you're using and it seems like what you've posted has most of the default parameters matching your explicit parameters. However, this doesn't ensure that your configuration has those all set to match the current documentation if you're using older implementations.
Also, a tip from a senior Facebook security engineer who discussed a similar issue in a lecture recently; different libraries implementing the same security protocols will oftentimes be incompatible and even the same libraries in different environments or languages will oftentimes fail to work together. With that in mind, a few things to try given that working examples similar to your setup exist online:
Make sure you're using the latest versions of libraries. Also note that some javax functions and classes are deprecated and suggest using java.security now (didn't check if this applies to your case).
Force the key size to be consistent (1024 or 2048). The java implementation can do either and I didn't find consistent documentation for both libraries saying what your configuration default would be used (could be causing problem #2, though you might get a different exception for invalid key size).
Ensure that your privatekey matches expectation (length/reads the same between java and php).
Force default values to be explicitly defined (set CryptRSA hash to sha1, key lengths, anything else you can explicitly set).
Try encrypting the same message with both java and php to see if you can get the same outputs. Do this after ensuring your keys read the same and don't throw exceptions while being used in both applications. Encrypting a single character can tell you if the same padding scheme is actually being used (it appears from the source code that both use MGF1, but it never hurts to check outputs).
Finally try taking an example for php to java encryption which is said to already work and do one change at a time until you get back to your current encryption scheme. I saw a few examples googling quickly which used different parameters and settings with CryptRSA and java security that stated they were working together. Take a working example and try swapping the hash function and then the encryption, etc.
i need some help for solve my problem.
Problem :
I want to encrypt a number (A) with public RSA Key from Android platform and then decrypt it on PHP Server with the private key.
On each platform, i can encrypt and decrypt data (it works well), but when the PHP script try to decrypt data encrypted from ANDROID, it doesn't work !!
Problem is not from HTTP Transmission, because I try to decrypt directly a generating Encryption from ANDROID (coded in Base64) and it not work at all ...
Findhere after my PHP Code for decrypt data :
class MyEncryption
{
public $privkey = '';
public $pubkey = '';
public function __construct(){
}
public function initialize() {
$fp=fopen("./encryption/asasap_public.pub","r");
$temp=fread($fp,8192);
fclose($fp);
$this->pubkey = openssl_pkey_get_public($temp);
$fp=fopen("./encryption/asasap.pem","r");
$temp=fread($fp,8192);
fclose($fp);
$this->privkey = openssl_get_privatekey($temp,'');
}
public function encrypt($data)
{
if (openssl_public_encrypt($data, $encrypted, $this->pubkey))
$data = base64_encode($encrypted);
else
throw new Exception('Unable to encrypt data. Perhaps it is bigger than the key size?');
return $data;
}
public function decrypt($data)
{
if (openssl_private_decrypt(base64_decode($data), $decrypted, $this->privkey))
$data = $decrypted;
else
$data = '';
return $data;
}
public function hex2bin($hexdata) {
$bindata = '';
for ($i = 0; $i < strlen($hexdata); $i += 2) {
$bindata .= chr(hexdec(substr($hexdata, $i, 2)));
}
return $bindata;
}
}
And i use this class like here :
$enc = new MyEncryption();
$enc->initialize();
$data_1 = 'K27booXr0zZK4BQlI45MIPJJjPPkpCCPELGvoK/wKYUwShIWE6szlZtrmV83C5eBIrT/3lxWTH3+IOA+5mefurVUvXmQIV7fXEHNHLphyM6L9gQsMAGZMCroPjWKvJM59OMS/d5dwwhiRgzVarxXSKpxBYhEYWJTu7nRJ+bZKjumeoqnCSpmntIiV+tRYgkYflOU6j2QlesjO5tzj/TL6n7vHSO/O1qafJkzHcv8Kn2hTy+IH7QXm7z5vtjXOucHkvBm1xWORXdifh+ChyVvP16dSEmCaCAH6KqtA4viX/HwRFEi4mIWaYSIQk74NdcnQOpFcTgEu2nDwtHaBMqahw==';
$data_2 = $enc->decrypt($data_1);
Here data_1 is initialized from the encrypt data (A=5) from android with the RSA Public Key (note : decrypt works well on Android), but after decryption in PHP, i get empty String ...
------------------------------------------ UPDATE -------
Please find here after the code for ANDROID part :
public byte[] encryptRSA(final InputStream publicKeyFile, String in) throws IOException, NoSuchAlgorithmException,
InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException,
BadPaddingException {
byte[] encodedKey = new byte[5000];
publicKeyFile.read(encodedKey);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pkPublic = kf.generatePublic(publicKeySpec);
// Encrypt
Cipher pkCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
pkCipher.init(Cipher.ENCRYPT_MODE, pkPublic);
return pkCipher.doFinal(in.getBytes());
}
After encrypt data, i convert the byte[] into Base64 (Base64.encodeToString(input, Base64.DEFAULT)).
For the certificate, i use RSA 2048 Bits convert into DER Format for Android.
------------------------------------------ SOLUTION -------
Error are in following Lines :
byte[] encodedKey = new byte[5000];
publicKeyFile.read(encodedKey);
We must read exactely the Public Key :
byte[] encodedKey = new byte[/*lenght of file*/];
publicKeyFile.read(encodedKey);
There are a lot of places this can go wrong:
You are passing 5000 bytes to X509EncodedKeySpec, most of which are 0. Are you sure you are getting the proper public key?
How long is the in String?
String.getBytes() uses the platform default encoding and may have unintended results. Use getBytes("ASCII") or getBytes("UTF-8").
Generally, you should just use SSL, and don't try to implement asymmetric encryption yourself.