0

How can I send the data of a SecretKeySpec or SecretKey from Java to PHP? When I convert it to String (to encrypt with RSA and post to PHP), I get some diamond with a question mark in it.

I tried to use utf8_decode but this problem is still remains.

EDIT:

I generated RSA Keypair in PHP, and sent the Public Key to Java. In Java I want to generate an AES_Key and encrypt a plaintext using AES, and send an encrypted plaintext and AES_Key (that is encrypted with RSA_Public_Key) from Java to PHP. The following codes represent the AES Encryption/Decryption steps of this project:

Java:

public static class ApiCrypter {

    private String iv = "0000000000000000";
    private byte[] secretkey;     //="mysecretkeyyyyyy";
    private IvParameterSpec ivspec;
    private SecretKeySpec keyspec;
    private Cipher cipher;

    public ApiCrypter(byte[] key)
    {
        secretkey=key;
        ivspec = new IvParameterSpec(iv.getBytes());
        keyspec = new SecretKeySpec(secretkey, "AES");

        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    public byte[] encrypt(String text) throws Exception
    {
        if(text == null || text.length() == 0) {
            throw new Exception("Empty string");
        }
        byte[] encrypted = null;
        try {
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            encrypted = cipher.doFinal(text.getBytes("UTF-8"));
        }
        catch (Exception e) {
            throw new Exception("[encrypt] " + e.getMessage());
        }
        return encrypted;
    }

    public byte[] decrypt(String code) throws Exception
    {
        if(code == null || code.length() == 0) {
            throw new Exception("Empty string");
        }
        byte[] decrypted = null;
        try {
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            decrypted = cipher.doFinal(hexToBytes(code));
        }
        catch (Exception e) {
            throw new Exception("[decrypt] " + e.getMessage());
        }
        return decrypted;
    }

    public static String bytesToHex(byte[] data)
    {
        if (data==null) {
            return null;
        }
        int len = data.length;
        String str = "";
        for (int i=0; i<len; i++) {
            if ((data[i]&0xFF)<16) {
                str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
            }
            else {
                str = str + java.lang.Integer.toHexString(data[i]&0xFF);
            }
        }
        return str;
    }

    public static byte[] hexToBytes(String str) {
        if (str==null) {
            return null;
        }
        else if (str.length() < 2) {
            return null;
        }
        else {
            int len = str.length() / 2;
            byte[] buffer = new byte[len];
            for (int i=0; i<len; i++) {
                buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
            }
            return buffer;
        }
    }
}

PHP:

<?php

class ApiCrypter
{
    private $iv = '0000000000000000';
    private $key;// = '89432hjfsd891787';

    public function __construct($keyy)
    {
        $this->key = $keyy;
    }

    public function encrypt($str)
    {
        $encrypted = openssl_encrypt($str, 'AES-128-CBC', $this->key, 0, $this->iv);//
        return bin2hex($encrypted);

    }

    public function decrypt($code)
    {
        $code = $this->hex2bin($code);
        $decrypted = openssl_decrypt($code, 'AES-128-CBC', $this->key, 0, $this->iv);
        $ut = utf8_encode(trim($decrypted));
        //  return $this->pkcs5_unpad($ut);
        return $ut;
    }

    protected function hex2bin($hexdata)
    {
        $bindata = '';
        for ($i = 0; $i < strlen($hexdata); $i += 2) {
            $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
        }
        return $bindata;
    }

    protected function pkcs5_pad($text)
    {
        $blocksize = 16;
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }

    protected function pkcs5_unpad($text)
    {
        $pad = ord($text{strlen($text) - 1});
        if ($pad > strlen($text)) {
            return false;
        }
        if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) {
            return false;
        }
        return substr($text, 0, -1 * $pad);
    }
}
?>

Generating a secretKey (as AES key), encryption of the plaintext(name) by AES key, Encrypt AES key, and preparing them for sending to PHP:

SecureRandom secureRandom = new SecureRandom();
KeyGenerator keyGenerator;
keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256, secureRandom);
SecretKey key = keyGenerator.generateKey();

secret_key = key.getEncoded();
Byte[] encodedSessionKey = RSA.encryptByPublicKey(secret_key, public_key);

ApiCrypter apiCrypter=new ApiCrypter(encodedSessionKey);
String encryptedName = ApiCrypter.bytesToHex(apiCrypter.encrypt(nameStr));

String encodedStr = Base64.encodeToString(encodedSessionKey, Base64.DEFAULT);
AsyncDataClass asyncRequestObject = new AsyncDataClass();
asyncRequestObject.execute(serverUrl,encodedStr,encryptedName);

PHP code to decrypt AES key using of the RSA private key and decryption of the NameString by decrypted AES key:

$encodedStr = "";
$encryptedName = "";

if(isset($_POST['encodedStr'])){
    $encodedSecretKey = $_POST['encodedStr'];
}

if(isset($_POST['encryptedName'])){
    $encryptedName = $_POST['encryptedName'];
}


$rsa = new \phpseclib\Crypt\RSA();
$rsa->setHash('sha1');
$rsa->setMGFHash('sha1');
$rsa->setEncryptionMode(1);
$rsa->loadKey(file_get_contents('private.key')); // RSA Private key


$AES_session_key = $rsa->decrypt(base64_decode($encodedSecretKey));

$ApiCrypter= new ApiCrypter($AES_session_key);
$decryptedName = $ApiCrypter->decrypt($encryptedName);
  1. Are these classes match to each other?

  2. How to encrypt a plaintext in Java using of the AES_Key (or a copy of a SecretKey that is generated in Java)?

  3. How to decrypt a plaintext in PHP, using the AES_key(that is decrypted by RSA Private Key) ?

5
  • There is no code in your question. You should change that. Also, you don't send data from one IDE to the next. An IDE is just a vehicle to write code. It doesn't host the service. Finally, have you heard of Base64 encoding? Commented Jun 19, 2017 at 20:48
  • @ArtjomB. Possibly he's trying to put the same key into both platforms for debugging purposes. Commented Jun 19, 2017 at 20:51
  • What do you mean with "for RSA encryption"? Commented Jun 19, 2017 at 21:03
  • @MaartenBodewes thank you for editing my question. In fact, i'm trying to develop an app to implement this scenario and now, i'm in step 6, and as i said, i have problem with that. Commented Jun 19, 2017 at 22:36
  • @ArtjomB. I have edited my question. Commented Jun 21, 2017 at 10:34

1 Answer 1

1

A secret key consists of random bytes. That means that - whatever encoding you use - that some bytes won't print. To represent bytes as text usually you use hexadecimal or base64 encoding. The difference between those two is that a normal person can make out the byte values from hexadecimals while base64 is more efficient (as it uses more characters and therefore can encode 6 bits per character where hexadecimals only encodes 4 bits per character).

Within Java 8 only base 64 is supported by default:

System.out.println(Base64.getEncoder().encodeToString(secretKey.getEncoded()));

and for Android:

Base64.encodeToString(secretKey.getEncoded(),Base64.DEFAULT);

should work fine (for SecretKeySpec as well, as it implements SecretKey).


Of course sending an unprotected secret key should be performed in a secure environment and should in general be avoided at all costs.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, but i have a question. What's difference between: Base64.getEncoder().encodeToString(secretKey.getEncoded()) and Base64.encodeToString(secretKey.getEncoded(),Base64.DEFAULT)
Nothing really, one is for Java, one for Android.
If I send the string that used by Base64.encodeToString(secretKey.getEncoded(),Base64.DEFAULT) to PHP, how can I access that secretKey to use as AES key to decrypt a text in PHP. I tried to use "base64_decode (with/without) hex2bin_function", but it returns different string. I appreciate it if you help me with a suitable and useful link, related to it. (AES decryptin in PHP using of the recieved key from Java)
This is the part where you have to amend your question with code...both Java and PHP.
Yeah I saw that. You only need base 64 or hex if you need to communicate over a non-binary interface. The AES key does not need to be encoded if you're just going to wrap it with an RSA key later. You may want to encode the RSA ciphertext holding the AES key though, again only if you want to transport if over the text interface (or if you want to print it to screen).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.