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代碼填充它爲什麼不一樣。
請幫忙。
'$ LEN =計數($的數據);'應該是'$長度= strlen的($的數據);'(在加密)因爲'$ data'是一個字符串。它不會解決問題。你的填充角色是什麼? – Michael
你對關鍵字的處理是否一致?我不太明白。 – Michael
我更新了$ len = strlen($ data);,看起來好像在試驗時發生了變化。治療關鍵意味着什麼密鑰?是的,它對PHP和Java都是一樣的。在PHP $ secretKey ='hg34sdfg4ertertr';並在Java String secretString =「hg34sdfg4ertertr」; – joy