2016-11-13 288 views
1

我最近在Java中使用了AES CBC 128算法來加密數據。現在我需要在PHP中重建該算法,但我不知道如何,因爲互聯網上的PHP算法返回不同的結果。也許你可以幫助我。使用Java和PHP的AES CBC 128位加密

這是Java代碼進行加密:

private SecretKeySpec secretKey; 
private IvParameterSpec ivSpec; 

public void setKey(String myKey) { 
    MessageDigest sha = null; 
    try { 
     byte[] key = myKey.getBytes("UTF-8"); 
     sha = MessageDigest.getInstance("SHA-1"); 
     key = sha.digest(key); 
     key = Arrays.copyOf(key, 16); 
     secretKey = new SecretKeySpec(key, "AES"); 

     byte[] iv = new String("1010101010101010").getBytes("UTF-8"); 
     ivSpec = new IvParameterSpec(iv); 

    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } 
} 

public String encrypt(String strToEncrypt) { 
    try { 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); 
     return Base64.encode(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

public String decrypt(String strToDecrypt) { 
    try { 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec); 
     return new String(cipher.doFinal(Base64.decode(strToDecrypt))); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

public static void main(String[] args) { 

    AESText aes = new AESText(); 
    final String secretKey = "com.secure.test.projectjasdS/FjkGkGhkGjhG786Vjfg=tjGFGH"; 
    aes.setKey(secretKey); 

    String originalString = "test set se ts et set s et se"; 
    String encryptedString = aes.encrypt(originalString); 
    String decryptedString = aes.decrypt(encryptedString); 

    System.out.println("origin: " + originalString); 
    System.out.println("encrypted: " + encryptedString); 
    System.out.println("decrypted: " + decryptedString); 
} 

這是我的PHP代碼:

protected $key; 
    protected $method = 'AES-128-CBC'; 
    protected $iv = '1010101010101010'; 
    protected $option = OPENSSL_CIPHER_AES_128_CBC; 

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

    public function encrypt($data) { 
     if (is_null($data)) { 
      return "Error " . INVALID_PARAMS_ENCRYPTIONS . ": Data is null "; 
     } 
     $enc = openssl_encrypt($data, $this->method, $this->key, $this->option, $this->iv); 
     return base64_encode($enc); 
    } 

    public function decrypt($data) { 
     if (is_null($data)) { 
      return "Error " . INVALID_PARAMS_ENCRYPTIONS . ": Data is null "; 
     } 
     $data = base64_decode($data); 
     $dec = openssl_decrypt($data, $this->method, $this->key, $this->option, $this->iv); 
     return $dec; 
    } 

當我從Java加密方法加密的數據,這個結果不能在PHP解密解密。

你們可能可以幫我建立一個PHP腳本,它返回與java加密相同的結果嗎?

回答

0

乍一看,我在這裏看到的三個問題:

首先:你沒有使用相同的模式:在Java中你有AES/ECB/PKCS5Padding,而你的PHP使用AES-128-CBC

:您可能沒有使用相同的IV的在Java和PHP代碼(IV的是不相關的歐洲央行,但一旦您打開Java來CBC你會需要它):

你有$iv = '1010101010101010'(然後傳遞給openssl)在你的PHP中,但沒有像你的Java。

最起碼,你可能需要在你的Java部分類似的東西還有:

cipher.init(Cipher.DECRYPT_MODE/ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)) 

iv是一個byte[]包含你的四字節。

第三:一旦上述問題得到解決,填充可能是下一個突破的事情:您的Java密碼規範提到PKCS5Padding。你需要確保你的兩個同行使用相同的。

編輯:第四:還有一個問題是你得出要使用的關鍵位的方式。在java中,你需要sha1-hash的前16個字節,而在php中,你只需通過$key來openssl。 openssl可能會以不同的方式派生加密密鑰。


當使用分組密碼加密建設相關的工具,它總是很高興重溫經典,像維基百科上Block cipher mode of operationPadding,得到什麼是引擎蓋下事情的感覺。

+0

謝謝@Shastick。我是加密的初學者。我編輯了我的java代碼。當我在java中使用'PKCS5Padding'時,這是工作,但是當我使用'NoPadding'時,出現錯誤'javax.crypto.IllegalBlockSizeException:輸入長度不是16字節的倍數'。但是,當我用'PKCS5Padding'添加'IV'並將'ECB'更改爲'CBC'時,java和php之間的加密不匹配。你能幫我編輯我的代碼嗎? –

+0

那麼,當輸入長度不是16的倍數時,填充是填充整體的,正如在異常中提到的那樣:)您可能需要多玩一點,然後查找一些教程以使其正確。 – Shastick

相關問題