dsmupo6631 2017-06-19 20:25
浏览 104

如何从Java发送SecretKey到PHP? (使用Android Studio和PhpStorm)

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) ?

  • 写回答

1条回答 默认 最新

  • drk49438 2017-06-19 20:59
    关注

    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.

    评论

报告相同问题?

悬赏问题

  • ¥200 关于#c++#的问题,请各位专家解答!
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥15 绘制多分类任务的roc曲线时只画出了一类的roc,其它的auc显示为nan
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀