des加密解密——java加密,php解密


最近在做項目中,遇到des加密解密的問題。

場景是安卓app端用des加密,php這邊需要解密。之前沒有接觸過des這種加密解密算法,但想着肯定會有demo。因此百度,搜了代碼來用。網上代碼也是魚龍混雜,好不容易測試在php這邊測試加密和解密成功了。為確保安卓app端提交過來的加密參數能夠解密出來,給定安卓人員一個字符串,讓他們把des加密后的字符串給我,在php這邊解密。結果一看,加密出來的字符串跟我這邊加密出來的結果不一致,自然是解密不出來。

 

要來java的des算法代碼,研究加密的過程,其中各種調試測試,外加各種百度,必應。發現能夠正確解密的規則,其中非常重要的三點就是,加密解密過程,雙方的key、加密模式(例如ECB、CBC等),以及iv(有些地方叫它偏移量,有些地方叫它向量,沒有深入研究)需要一致。需要着重說明的是這個iv,在ECB加密模式(java默認的加密模式)時,是不需要這個iv的,即使寫了,也不會影響加密的結果;而當加密模式為CBC時,則需要iv這個參數,否則會隨機生成該參數,這樣每次加密的結果會變。而關鍵在於,java端定義了iv,那么php這邊也需要跟java端保持一致,這樣才能夠正確解密出來。

 

后面就膠着在這個iv上面。查看java端代碼,iv是一個byte[],即字節數組,想都沒有想就去網上找php將字符串轉化為byte[]類型的,也試過強制轉換,解密失敗。最后才想起來去看php的數據類型,呃呃呃,壓根就沒有type類型的。真是基礎不牢,又想當然,覺得java有該數據類型,php也會有。。。慣性思維真的害人啊。這怎么辦呢?既需要byte[]去解密,又沒有該數據數據類型,已經感覺無解了。

 

通常這個時候,需要休息,休息一會兒。后面突然念頭閃過,php中有函數可以des解密,該函數肯定不會用php沒有的數據類型去解密,所以我試着將java加密中轉換成byte[]類型前的字符串作為php的iv,測試,終於解密成功。

 附上java端加密代碼,采用CBC模式:

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

public class DES {

    //加密數據入口
    public static String encryptString(String message, String key)
            throws Exception {
        byte[] bytes = encrypt(message, key);
        return toHexString(bytes).toUpperCase();
    }

  public static byte[] encrypt(String message, String key) throws Exception {
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);

        return cipher.doFinal(message.getBytes("UTF-8"));
    }
}

 

附上對應的php端解密代碼:

class DES
{
    public static function decrypt($str, $key)
    {
        $midstr = hex2bin(strtolower($str));
     //第二個參數$key就是三個重點中的$key,而最后一個參數$key是iv,只是java加密時采用了與第二個參數相同的字符串,根據具體情況來定就好
     $str = mcrypt_decrypt(MCRYPT_DES, $key, $midstr, MCRYPT_MODE_CBC, $key); 
     $pad = ord($str[($len = strlen($str)) - 1]);      return substr($str, 0, strlen($str) - $pad);   } }

其中hex2bin是將十六進制轉換成二進制,php自帶該函數,不需要再另行定義(網上看到很多該函數的代碼)。解密可以看作是加密的逆操作,所以java端將加密后字符串轉成十六進制,並大寫,解密時自然需要轉換回來。

  

可以看看下面這個鏈接,寫得不錯:

http://zhidao.baidu.com/link?url=vKbwbKxibbLc8K7oo40cJ17aYz2i2MdfZlaytdj6GLsqBwrPoc_OwHhsi7IjdaFId9fZb52SkhdDBG_U502CKNyCQDPE3ZSKr-adXB46CEO


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM