2016-01-26 55 views
0

我正在使用JAVA使用DES算法對字符串進行解密/加密。我有一位客戶需要解密由我的應用程序生成的安全字符串。消費者應用程序使用PHP構建。我試圖將我的Java代碼轉換爲PHP代碼,但由於我對PHP的理解有限而面臨問題。 我正面臨着在PHP中創建自定義填充的問題,並意識到PHP「mcrypt_decrypt」方法將「數據」作爲字符數組而不是Java中的字節數組。使用自定義填充將Java Tripple DES代碼轉換爲PHP代碼

以下是可供參考的Java代碼。

import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.SecretKeySpec; 

public class JEncrytion 
{ 
    private static final char[] hexDigits = { 
     '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' 
    }; 
     /** 
    * Returns a string of hexadecimal digits from a byte array. Each 
    * byte is converted to 2 hex symbols. 
    * <p> 
    * If offset and length are omitted, the whole array is used. 
    */ 
    public static String toString(byte[] ba, int offset, int length) { 
     char[] buf = new char[length * 2]; 
     int j = 0; 
     int k; 

     for (int i = offset; i < offset + length; i++) { 
      k = ba[i]; 
      buf[j++] = hexDigits[(k >>> 4) & 0x0F]; 
      buf[j++] = hexDigits[ k  & 0x0F]; 
     } 
     return new String(buf); 
    } 
    public static String toString(byte[] ba) { 
     return toString(ba, 0, ba.length); 
    } 
     /** 
    * Returns the number from 0 to 15 corresponding to the hex digit <i>ch</i>. 
    */ 
    public static int fromDigit(char ch) { 
     if (ch >= '0' && ch <= '9') 
      return ch - '0'; 
     if (ch >= 'A' && ch <= 'F') 
      return ch - 'A' + 10; 
     if (ch >= 'a' && ch <= 'f') 
      return ch - 'a' + 10; 

     throw new IllegalArgumentException("invalid hex digit '" + ch + "'"); 
    } 
    /** 
    * Returns a byte array from a string of hexadecimal digits. 
    */ 
    public static byte[] fromString(String hex) { 
     int len = hex.length(); 
     byte[] buf = new byte[((len + 1)/2)]; 

     int i = 0, j = 0; 
     if ((len % 2) == 1) 
      buf[j++] = (byte) fromDigit(hex.charAt(i++)); 

     while (i < len) { 
      buf[j++] = (byte) ((fromDigit(hex.charAt(i++)) << 4) | 
           fromDigit(hex.charAt(i++))); 
     } 
     return buf; 
    } 
    //Add padding to make key 24 bytes length i.e. 192 bits length 
    public static byte [] addPaddingToKey (byte [] keyBytes) { 
     byte[] key; 
     int keyLength = keyBytes.length; 
     int paddingLenght = 24 - keyLength; 
     if (paddingLenght != 0) { 
      key = new byte[24]; 
      //copy original key 
      System.arraycopy(keyBytes, 0, key, 0, keyLength); 
      //Adding 0 as padding for remaining 
      System.arraycopy(keyBytes, 0, key, keyLength, paddingLenght); 
     } else { 
      key = keyBytes; 
     } 
     return key; 
    } 
    //Add padding to input value to 
    public static byte[] addPadding(byte[] inData, int offset, int len) { 

     byte[] bp = null; 
     int padChars = 8;    // start with max padding value 
     int partial = (len + 1) % padChars;  // calculate how many extra bytes exist 
     if (partial == 0) padChars = 1;   // if none, set to only pad with length byte 
     else padChars = padChars - partial + 1; // calculate padding size to include length 

     bp = new byte[len + padChars]; 
     bp[0] = Byte.parseByte(Integer.toString(padChars)); 
     System.arraycopy(inData, offset, bp, 1, len); 
     return bp; 
    } 
    //remove padding added while decryption 
    public static byte[] removePadding(byte[] inData) { 

      byte[] bp = null; 
      int dataLength = 0; 
      int padLength = 0; 
      padLength = inData[0]; 
      dataLength = inData.length - padLength; 
      bp = new byte[dataLength]; 
      System.arraycopy(inData, 1, bp, 0, dataLength);  
      return bp; 
     } 
    //Get SecretKey object 
    public static SecretKey getSecretKey(String secretString) { 
      SecretKey myDesKey = null; 
      try { 
       //get bytes from key 
       byte [] keyBytes = secretString.getBytes(); 
       //add padding to key to meet 24 bytes requirement 
       byte [] bytes = addPaddingToKey(keyBytes); 
       //Generate DES key 
       myDesKey = new SecretKeySpec(bytes,"DESede"); 

      }catch (Exception e) { 
       e.printStackTrace();  
      } 
      return myDesKey; 
    } 
    //encrypt data 
    public static byte[] encrypt(byte[] text, String secretString) { 
     byte[] textEncrypted = null; 
      try { 
       //Generate DES key 
       SecretKey myDesKey = getSecretKey(secretString); 

       Cipher desCipher; 
       // Create the cipher for DES-EDE3 
       desCipher = Cipher.getInstance("DESede/ECB/NoPadding"); 

       // Initialize the cipher for encryption 
       desCipher.init(Cipher.ENCRYPT_MODE, myDesKey); 

       //Add padding to make it multiple of 8 
       text = addPadding (text, 0 , text.length); 

       // encrypt the text 
       textEncrypted = desCipher.doFinal(text); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      return textEncrypted; 

      } 
    //Decrypt given encrypted bytes 
    public static byte[] decrypt (byte [] textEncrypted, String secretString){ 
     byte[] textDecrypted = null; 
     try {    
      //Generate DES key 
      SecretKey myDesKey = getSecretKey(secretString); 

      Cipher desCipher; 
      // Create the cipher for DES-EDE3 
      desCipher = Cipher.getInstance("DESede/ECB/NoPadding"); 


      // Initialize the same cipher for decryption 
      desCipher.init(Cipher.DECRYPT_MODE, myDesKey); 

      // Decrypt the text 
      textDecrypted = desCipher.doFinal(textEncrypted); 

      //remove padding which was added during encryption 
      textDecrypted = removePadding (textDecrypted); 

     }catch (Exception e) { 
      e.printStackTrace();  
     } 
     return textDecrypted; 
    } 
    public static void main(String[] argv) {   
     try{ 
      String secretString = "hg34sdfg4ertertr"; 
      String plainTextString = "{\"name\":\"Test\"}"; 
      byte[] plainText = plainTextString.getBytes(); 
      //Encrypt given plain text 
      byte [] encryptedText = encrypt(plainText, secretString); 
      //Convert into hex 

      String hexStr = toString(encryptedText); 
      System.out.println("Encrypted String "+hexStr);   
      byte [] decryptedText = decrypt(encryptedText, secretString); 
      System.out.println(" decrypted string "+new String (decryptedText)); 

     }catch(Exception e){ 
      e.printStackTrace(); 
     } 

    } 
} 

以下是PHP代碼我試圖通過谷歌搜索,並使用http://phpfiddle.org測試:

<?php 
function byteStr2byteArray($s) { 
    return array_slice(unpack("C*", "\0".$s), 1); 
} 

function Encrypt($data, $secret) 
{  
    //Generate a key from a hash 
    $key = md5(utf8_encode($secret), true); 

    //Take first 8 bytes of $key and append them to the end of $key. 
    $key .= substr($key, 0, 8); 
    //Pad to make multiple of 8 bytes 
    $blockSize = 8; 
    $len = strlen($data); 
    $pad = $blockSize - ($len % $blockSize); 
    $data .= str_repeat(chr(0), $pad); 

    //Encrypt data 
    $encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb'); 

    //return base64_encode($encData); 
return bin2hex($encData); 
} 

function Decrypt($data, $secret) 
{ 

    //Generate a key from a hash 
    $key = md5(utf8_encode($secret), true); 

    //Take first 8 bytes of $key and append them to the end of $key. 
    $key .= substr($key, 0, 8); 

    //$data = base64_decode($data); 
    $data = hex2bin($data); 
    $data = mcrypt_decrypt('tripledes', $key, $data, 'ecb'); 

    $block = 8; 
    $len = strlen($data); 
    $pad = ord($data[$len-1]); 

    return substr($data, 0, strlen($data) - $pad); 
} 

$secretKey = 'hg34sdfg4ertertr'; 
$json = "{\"name\":\"Test\"}"; 
$textToEncrypt = json_encode($json); 
$encrypted = Encrypt($textToEncrypt, $secretKey); 
echo strtoupper($encrypted); 

/*Line break*/ 
echo "<br />"; 
/*Decryption*/ 
$textToDecrypt = $encrypted; 
$decrypted = Decrypt($textToDecrypt, $secretKey); 
echo $decrypted; 

?> 

在PHP代碼然而加密字符串不一樣的Java代碼。以下是用於例如生成的加密字符串

Plain Text: {"name":"Test"} 
PHP: 30AEE71A51DA55050F524356878EAF79522643B97EAF4C07 
Java: 27A211EE2B2032BA1F83D20AE920903F 

我理解,因爲我不能寫類似的添加/刪除PHP代碼填充它爲什麼不一樣。

請幫忙。

+0

'$ LEN =計數($的數據);'應該是'$長度= strlen的($的數據);'(在加密)因爲'$ data'是一個字符串。它不會解決問題。你的填充角色是什麼? – Michael

+0

你對關鍵字的處理是否一致?我不太明白。 – Michael

+0

我更新了$ len = strlen($ data);,看起來好像在試驗時發生了變化。治療關鍵意味着什麼密鑰?是的,它對PHP和Java都是一樣的。在PHP $ secretKey ='hg34sdfg4ertertr';並在Java String secretString =「hg34sdfg4ertertr」; – joy

回答

0

當我通過this後,我得到了PHP填充邏輯的基礎知識,然後我改變了JAVA和PHP代碼如下,然後它的工作。

Java代碼:

import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.SecretKeySpec; 

public class PHPEncryption 
{ 
    private static final char[] hexDigits = { 
     '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' 
    }; 
     /** 
    * Returns a string of hexadecimal digits from a byte array. Each 
    * byte is converted to 2 hex symbols. 
    * <p> 
    * If offset and length are omitted, the whole array is used. 
    */ 
    public static String toString(byte[] ba, int offset, int length) { 
     char[] buf = new char[length * 2]; 
     int j = 0; 
     int k; 

     for (int i = offset; i < offset + length; i++) { 
      k = ba[i]; 
      buf[j++] = hexDigits[(k >>> 4) & 0x0F]; 
      buf[j++] = hexDigits[ k  & 0x0F]; 
     } 
     return new String(buf); 
    } 
    public static String toString(byte[] ba) { 
     return toString(ba, 0, ba.length); 
    } 
     /** 
    * Returns the number from 0 to 15 corresponding to the hex digit <i>ch</i>. 
    */ 
    public static int fromDigit(char ch) { 
     if (ch >= '0' && ch <= '9') 
      return ch - '0'; 
     if (ch >= 'A' && ch <= 'F') 
      return ch - 'A' + 10; 
     if (ch >= 'a' && ch <= 'f') 
      return ch - 'a' + 10; 

     throw new IllegalArgumentException("invalid hex digit '" + ch + "'"); 
    } 
    /** 
    * Returns a byte array from a string of hexadecimal digits. 
    */ 
    public static byte[] fromString(String hex) { 
     int len = hex.length(); 
     byte[] buf = new byte[((len + 1)/2)]; 

     int i = 0, j = 0; 
     if ((len % 2) == 1) 
      buf[j++] = (byte) fromDigit(hex.charAt(i++)); 

     while (i < len) { 
      buf[j++] = (byte) ((fromDigit(hex.charAt(i++)) << 4) | 
           fromDigit(hex.charAt(i++))); 
     } 
     return buf; 
    } 

    //Add padding to input value to 
    public static byte[] addPadding(byte[] inData, int offset, int len) { 

     byte[] bp = null; 
     int padChars = 8;    // start with max padding value 
     int partial = (len + 1) % padChars;  // calculate how many extra bytes exist 
     if (partial == 0) padChars = 1;   // if none, set to only pad with length byte 
     else padChars = padChars - partial + 1; // calculate padding size to include length 

     bp = new byte[len + padChars]; 
     //bp[0] = Byte.parseByte(Integer.toString(padChars)); 
     System.arraycopy(inData, offset, bp, 0, len); 
     return bp; 
    } 
    //remove padding added while decryption 
    public static byte[] removePadding(byte[] inData) { 

      byte[] bp = null; 
      int dataLength = 0; 
      int padLength = 0; 
      //loop in to find out pad lenght 
      for(int i=inData.length -1 ; i > -1 ; i--) { 
       byte currentData = inData[i]; 
       if(i != inData.length -1) { 
        //check for current and previous data and both must be 0 
        byte previousData = inData[i+1]; 
        if(previousData == currentData && currentData == 0) { 
         padLength++; 
        } else { 
         //break the loop 
         break; 
        } 
       } else { 
        //if last data is null then increase the pad length 
        if(currentData == 0) { 
         padLength++; 
        } 
       } 
      } 
      dataLength = inData.length - padLength; 
      bp = new byte[dataLength]; 
      System.arraycopy(inData, 0, bp, 0, dataLength);  
      return bp; 
     } 
    //Get SecretKey object 
    public static SecretKey getSecretKey(String secretString) { 
      SecretKey myDesKey = null; 
      try { 
       //get bytes from key 
       byte [] keyBytes = secretString.getBytes(); 

       //Generate DES key 
       myDesKey = new SecretKeySpec(keyBytes,"DESede"); 

      }catch (Exception e) { 
       e.printStackTrace();  
      } 
      return myDesKey; 
    } 
    //encrypt data 
    public static byte[] encrypt(byte[] text, String secretString) { 
     byte[] textEncrypted = null; 
      try { 
       //Generate DES key 
       SecretKey myDesKey = getSecretKey(secretString); 

       Cipher desCipher; 
       // Create the cipher for DES-EDE3 
       desCipher = Cipher.getInstance("DESede/ECB/NoPadding"); 

       // Initialize the cipher for encryption 
       desCipher.init(Cipher.ENCRYPT_MODE, myDesKey); 

       //Add padding to make it multiple of 8 
       text = addPadding (text, 0 , text.length); 

       // encrypt the text 
       textEncrypted = desCipher.doFinal(text); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      return textEncrypted; 

      } 
    //Decrypt given encrypted bytes 
    public static byte[] decrypt (byte [] textEncrypted, String secretString){ 
     byte[] textDecrypted = null; 
     try {    
      //Generate DES key 
      SecretKey myDesKey = getSecretKey(secretString); 

      Cipher desCipher; 
      // Create the cipher for DES-EDE3 
      desCipher = Cipher.getInstance("DESede/ECB/NoPadding"); 


      // Initialize the same cipher for decryption 
      desCipher.init(Cipher.DECRYPT_MODE, myDesKey); 

      // Decrypt the text 
      textDecrypted = desCipher.doFinal(textEncrypted); 

      //remove padding which was added during encryption 
      textDecrypted = removePadding (textDecrypted); 

     }catch (Exception e) { 
      e.printStackTrace();  
     } 
     return textDecrypted; 
    } 
    public static void main(String[] argv) {   
     try{ 
      String secretString = "1234567890qwertyuiopasdf"; //key must be 24 chars 
      String plainTextString = "Hello World"; 
      byte[] plainText = plainTextString.getBytes(); 
      //Encrypt given plain text 
      byte [] encryptedText = encrypt(plainText, secretString); 
      //Convert into hex 

      String hexStr = toString(encryptedText); 
      System.out.println("Encrypted String "+hexStr);   
      byte [] decryptedText = decrypt(encryptedText, secretString); 
      System.out.println("Decrypted string "+new String (decryptedText)); 

     }catch(Exception e){ 
      e.printStackTrace(); 
     } 

    } 
} 

PHP代碼:

<?php 
function Encrypt($data, $secret) {  
    // get the amount of bytes to pad 
    $extra = 8 - (strlen($data) % 8); 
    // add the zero padding 
    if($extra > 0) { 
     for($i = 0; $i < $extra; $i++) { 
      $data .= "\0"; 
     } 
    } 
    //Encrypt data 
    $encData = mcrypt_encrypt('tripledes',$secret, $data, 'ecb'); 
    //return hex format 
    return bin2hex($encData); 
} 

function Decrypt($data, $secret) { 
    $data = hex2bin($data); 
    $data = mcrypt_decrypt('tripledes', $secret, $data, 'ecb'); 
    return $data; 
} 

$secretKey = '1234567890qwertyuiopasdf'; //key must be 24 chars 

$textToEncrypt = "Hello World"; 

$encrypted = Encrypt($textToEncrypt, $secretKey); 
echo strtoupper($encrypted); 

/*Line break*/ 
echo "<br />"; 
/*Decryption*/ 
$textToDecrypt = $encrypted; 
$decrypted = Decrypt($textToDecrypt, $secretKey); 
echo $decrypted; 

?> 

現在兩個人都在做同樣的加密和解密。下面是示例輸出 的Java:

Encrypted String 753DE4F18233AD9BCD8CA71D3E501EEF 
Decrypted string Hello World 

PHP:

753DE4F18233AD9BCD8CA71D3E501EEF 
Hello World