2017-06-19 18 views
0

如何將SecretKeySpecSecretKey的數據從Java發送到PHP?當我將它轉換爲String(用RSA進行加密併發布到PHP)時,我會得到一些帶有問號的鑽石。如何將SecretKey從Java發送到PHP? (使用Android Studio&PhpStorm)

我試圖使用utf8_decode但這個問題仍然存在。

編輯:

我產生RSA密鑰在PHP,並將其發送公鑰到Java。在Java中,我想生成AES_Key並使用AES加密明文,並將加密的明文和AES_Key(用RSA_Public_Key加密)從Java發送到PHP。 下面的代碼表示此項目的AES加密/解密步驟:

的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); 
    } 
} 
?> 

生成祕密密鑰(如AES密鑰),明文加密(名稱),通過AES密鑰,加密AES密鑰,並準備發送到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代碼使用NameString的RSA私鑰解密的解密AES密鑰解密通過AES密鑰:

$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. 是這些類彼此匹配?

  2. 如何使用AES_Key(或Java中生成的SecretKey的副本)在Java中使用Java加密明文?

  3. 如何使用AES_key(由RSA私鑰解密)在PHP中解密純文本?

+0

你的問題沒有代碼。你應該改變這一點。此外,您不會將數據從一個IDE發送到下一個。 IDE只是編寫代碼的工具。它不承載服務。最後,你有沒有聽說過Base64編碼? –

+0

@ArtjomB。可能他試圖將相同的密鑰放到兩個平臺上進行調試。 –

+0

你對「RSA加密」有什麼意義? –

回答

1

密鑰由隨機字節組成。這意味着 - 無論您使用哪種編碼 - 都會打印一些字節。要將字節表示爲文本,通常使用十六進制或base64編碼。這兩者之間的區別在於,普通人可以從十六進制中得出字節值,而base64更有效(因爲它使用更多字符,因此可以對每個字符編碼6位,其中十六進制只對每個字符編碼4位)。

在Java 8隻立足64默認支持:

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

和Android的:

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

應該正常工作(爲SecretKeySpec爲好,因爲它實現SecretKey)。


當然發送未受保護的密鑰應在安全的環境中進行,並應一般不惜一切代價避免。

+0

謝謝,但我有一個問題。有什麼區別:Base64.getEncoder()。encodeToString(secretKey.getEncoded())和Base64.encodeToString(secretKey.getEncoded(),Base64.DEFAULT) – Yousef

+0

真的沒有,一個是Java,一個是Android。 –

+0

如果我將Base64.encodeToString(secretKey.getEncoded(),Base64.DEFAULT)使用的字符串發送到PHP,我如何訪問該secretKey以用作AES密鑰來解密PHP中的文本。我嘗試使用「base64_decode(with/without)hex2bin_function」,但它返回不同的字符串。我很感激,如果你幫助我一個合適的,有用的鏈接,與它有關。 (使用Java中的接收密鑰在PHP中使用AES進行AES解密) – Yousef

相關問題