I want to replicate the encryption/decryption from JAVA to PHP. But my problem the result is not match. I have no idea about java so I'm trying to understand each line of codes from java and write in PHP.
JAVA
secretkey: thisisasecretkey
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class TDESEncrypter {
public String _encrypt(String message, String secretKey) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digestOfPassword = md.digest(secretKey.getBytes("utf-8"));
byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
SecretKey key = new SecretKeySpec(keyBytes, "DESede");
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] plainTextBytes = message.getBytes("utf-8");
byte[] buf = cipher.doFinal(plainTextBytes);
byte [] base64Bytes = Base64.encodeBase64(buf);
String base64EncryptedString = new String(base64Bytes);
return base64EncryptedString;
}
public String _decrypt(String encryptedText, String secretKey) throws Exception {
byte[] message = Base64.decodeBase64(encryptedText.getBytes("utf-8"));
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digestOfPassword = md.digest(secretKey.getBytes("utf-8"));
byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
SecretKey key = new SecretKeySpec(keyBytes, "DESede");
Cipher decipher = Cipher.getInstance("DESede");
decipher.init(Cipher.DECRYPT_MODE, key);
byte[] plainText = decipher.doFinal(message);
return new String(plainText, "UTF-8");
}
}
Here's the steps using java that might be useful to replicate the functions in PHP.
initialize Secretkey with keybytes from step3 using DESede
create cipher with DESede instance
What I have done so far,
function encrypt($data, $secret) {
$key = sha1(utf8_encode($secret), true); <-- Step 1 & 2
$iv = utf8_encode("jvz8bUAx"); <-- Do I use initialise vector on it?
$key .= substr($key, 0, 8);
$method = 'des-ede3-cbc'; //<-- Is this cypher method correct from the above?
if (strlen($data) % 8) {
$data = str_pad($data, strlen($data) + 8 - strlen($data) % 8, "\0");
}
$encrypted = openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); //Force zero padding.
$encrypted = urlencode(base64_encode($encrypted)); // Added the urlencode.....
return $encrypted;
}
In the Java-code, the encryption-algorithm is specified as DESede
. This corresponds to DESede/ECB/PKCS5Padding
, i.e. the ECB-mode and PKCS5-padding are used. This means for the PHP-code:
des-ede3
must be applied openssl_encrypt
uses PKCS5-padding by default)In the Java-code, the SHA1-hash (with a size of 20 bytes) is extended to 24 bytes by appending 0-values. This extension must also be done in the PHP-code.
A possible PHP-counterpart to the Java _encrypt
-method is:
function encrypt($data, $secret) {
$key = sha1(mb_convert_encoding($secret, "UTF-8"), true); // Create SHA-1 hash (20 byte)
$key = str_pad($key, 24, "\0"); // Extend to 24 byte by appending 0-values (would also happen automatically on openssl_encrypt-call)
$encrypted = openssl_encrypt($data, 'DES-EDE3', $key, OPENSSL_RAW_DATA); // Encryption: DESede (24 byte key), ECB-mode, PKCS5-Padding
return base64_encode($encrypted); // Base64-encoding
}
Finally: The Java-code has a number of disadvantages, e.g.
The latter just for the sake of completeness, as it's probably legacy code that can't be changed for any reason.