php des加密用java解析不了 改個模式 加個IV php金鑰/IV要求都是8位
php des加密用java解析不了 Wrong IV length: must be 8 bytes long
PHP的DES加密和Java解密不相容的問題通常是因為PHP預設使用ECB模式,而Java可能預設使用其他模式如CBC,或者使用不同的padding方式。
解決方法:
確保PHP和Java使用相同的加密模式(如CBC)和padding方式(如PKCS5Padding或NoPadding)。
確保兩邊使用相同的金鑰和初始化向量(IV)。
以下是PHP和Java分別使用CBC模式和PKCS5Padding的示例程式碼:
PHP:
<?php $key = '12345678'; // 金鑰 $iv = '12345678'; // 初始化向量 $data = 'Data to encrypt'; $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($td, $key, $iv); $encrypted = mcrypt_generic($td, $data); mcrypt_generic_deinit($td); mcrypt_module_close($td); echo base64_encode($encrypted); ?>
JAVA:
import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class Main { public static void main(String[] args) throws Exception { String key = "12345678"; // 金鑰 String iv = "12345678"; // 初始化向量 String data = "Data to encrypt"; Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "DES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] encrypted = cipher.doFinal(data.getBytes()); System.out.println(Base64.getEncoder().encodeToString(encrypted)); } }
import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class Main { public static void main(String[] args) throws Exception { String key = "12345678"; // 金鑰 String iv = "12345678"; // 初始化向量 String data = "Data to encrypt"; Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "DES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] encrypted = cipher.doFinal(data.getBytes()); System.out.println(Base64.getEncoder().encodeToString(encrypted)); } }
在這兩個示例中,我們都使用了CBC模式和PKCS5Padding,並且金鑰和初始化向量都是固定的字串。在實際應用中,你需要確保金鑰和向量的安全性,並且在解密時使用相同的引數。
連結:des加密,url編碼,url解碼,des解密 DES加解密及Wrong key size錯誤處理
https://www.cnblogs.com/oktokeep/p/17917821.html
工具類DEMO:
package com.example.core.mydemo.des; import com.example.core.mydemo.MD5; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; /** * output:原始字串 = {"phone":"1391111","username":"張三"} * des加密 = LHFFScjfDE1kEyz27Y4ffRb0aM98qONoW8HGHzqjCqBqX9fwlPb28w== * url編碼 = LHFFScjfDE1kEyz27Y4ffRb0aM98qONoW8HGHzqjCqBqX9fwlPb28w%3D%3D * url解碼 = LHFFScjfDE1kEyz27Y4ffRb0aM98qONoW8HGHzqjCqBqX9fwlPb28w== * 不相同 * des解密 = {"phone":"1391111","username":"張三"} */ public class CbcIvDesUtls { private static String CHARSETNAME="UTF-8"; static String iv = "12345678"; // 初始化向量 /** * DES加解密及Wrong key size錯誤處理 * @param key * @return * @throws UnsupportedEncodingException */ private static byte[] getKeyBytes(String key) throws UnsupportedEncodingException { byte[] keyBytes = key.getBytes(CHARSETNAME); if (keyBytes.length < 8) { byte[] bytes = new byte[8]; System.arraycopy(keyBytes, 0, bytes, 0, keyBytes.length); keyBytes = bytes; } return keyBytes; } public static String getDESStr(String str, String encryptKey, String type, String charset) throws Exception { Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); SecretKeySpec secretKeySpec = new SecretKeySpec(encryptKey.getBytes(), "DES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); //加密 if ("ENCRYPT".equals(type)) { cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); return Base64Encoder.encode(cipher.doFinal(str.getBytes(charset))); }else if ("DECRYPT".equals(type)) { byte[] encodeByte = Base64Encoder.decode(str.getBytes()); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] decoder = cipher.doFinal(encodeByte); return new String(decoder, charset); } return "type error"; } public static void main(String[] args) { //java.security.InvalidKeyException: Wrong key size //金鑰要求是8位 String encryptKey = "abcdefgh"; String type = "ENCRYPT"; String charset = "UTF-8"; String str = "{\"phone\":\"1391111\",\"username\":\"張三\"}"; System.out.println("原始字串 = " + str); try { //des加密 String DESStr= getDESStr(str,encryptKey,type,charset); System.out.println("des加密 = " + DESStr); // url編碼 DESStr = URLEncoder.encode(DESStr,"UTF-8"); System.out.println("url編碼 = " + DESStr); //url解碼 String s = URLDecoder.decode(DESStr,"UTF-8"); System.out.println("url解碼 = " + s); //javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher /** * 報錯原因是因為:解密字串不是url解碼後的,所以會報該錯誤。 */ // System.out.println("des解密2 = " + getDESStr(DESStr,encryptKey,"DECRYPT","UTF-8")); //des解密 if(DESStr.equals(s)){ System.out.println("相同"); }else{ System.out.println("不相同"); } System.out.println("des解密 = " + getDESStr(s,encryptKey,"DECRYPT","UTF-8")); //ENCRYPT(des加密) encode(url編碼) >> decode(url解碼) encrypt(des解密) } catch (Exception e) { e.printStackTrace(); } } }
package com.example.core.mydemo.des; import com.example.core.mydemo.MD5; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; /** * output:原始字串 = {"phone":"1391111","username":"張三"} * des加密 = LHFFScjfDE1kEyz27Y4ffRb0aM98qONoW8HGHzqjCqBqX9fwlPb28w== * url編碼 = LHFFScjfDE1kEyz27Y4ffRb0aM98qONoW8HGHzqjCqBqX9fwlPb28w%3D%3D * url解碼 = LHFFScjfDE1kEyz27Y4ffRb0aM98qONoW8HGHzqjCqBqX9fwlPb28w== * 不相同 * des解密 = {"phone":"1391111","username":"張三"} */ public class CbcIvDesUtls { private static String CHARSETNAME="UTF-8"; static String iv = "12345678"; // 初始化向量 /** * DES加解密及Wrong key size錯誤處理 * @param key * @return * @throws UnsupportedEncodingException */ private static byte[] getKeyBytes(String key) throws UnsupportedEncodingException { byte[] keyBytes = key.getBytes(CHARSETNAME); if (keyBytes.length < 8) { byte[] bytes = new byte[8]; System.arraycopy(keyBytes, 0, bytes, 0, keyBytes.length); keyBytes = bytes; } return keyBytes; } public static String getDESStr(String str, String encryptKey, String type, String charset) throws Exception { Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); SecretKeySpec secretKeySpec = new SecretKeySpec(encryptKey.getBytes(), "DES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); //加密 if ("ENCRYPT".equals(type)) { cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); return Base64Encoder.encode(cipher.doFinal(str.getBytes(charset))); }else if ("DECRYPT".equals(type)) { byte[] encodeByte = Base64Encoder.decode(str.getBytes()); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] decoder = cipher.doFinal(encodeByte); return new String(decoder, charset); } return "type error"; } public static void main(String[] args) { //java.security.InvalidKeyException: Wrong key size //金鑰要求是8位 String encryptKey = "abcdefgh"; String type = "ENCRYPT"; String charset = "UTF-8"; String str = "{\"phone\":\"1391111\",\"username\":\"張三\"}"; System.out.println("原始字串 = " + str); try { //des加密 String DESStr= getDESStr(str,encryptKey,type,charset); System.out.println("des加密 = " + DESStr); // url編碼 DESStr = URLEncoder.encode(DESStr,"UTF-8"); System.out.println("url編碼 = " + DESStr); //url解碼 String s = URLDecoder.decode(DESStr,"UTF-8"); System.out.println("url解碼 = " + s); //javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher /** * 報錯原因是因為:解密字串不是url解碼後的,所以會報該錯誤。 */ // System.out.println("des解密2 = " + getDESStr(DESStr,encryptKey,"DECRYPT","UTF-8")); //des解密 if(DESStr.equals(s)){ System.out.println("相同"); }else{ System.out.println("不相同"); } System.out.println("des解密 = " + getDESStr(s,encryptKey,"DECRYPT","UTF-8")); //ENCRYPT(des加密) encode(url編碼) >> decode(url解碼) encrypt(des解密) } catch (Exception e) { e.printStackTrace(); } } }
工具類DEMO簡化版本:
package com.example.core.mydemo.des; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class IvDesTest { public static void main(String[] args) throws Exception{ String key = "12345678"; // 金鑰8位 String iv = "12345678"; // 初始化向量 Wrong IV length: must be 8 bytes long String data = "Data to encrypt"; Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "DES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); //加密 byte[] encrypted = cipher.doFinal(data.getBytes()); String encryptStr = Base64.getEncoder().encodeToString(encrypted); System.out.println("encryptStr=" + encryptStr); //解密 byte[] encodeByte = Base64Encoder.decode(encryptStr.getBytes()); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] decoder = cipher.doFinal(encodeByte); String decryptStr = new String(decoder); System.out.println("decryptStr=" + decryptStr); } }
package com.example.core.mydemo.des; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class IvDesTest { public static void main(String[] args) throws Exception{ String key = "12345678"; // 金鑰8位 String iv = "12345678"; // 初始化向量 Wrong IV length: must be 8 bytes long String data = "Data to encrypt"; Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "DES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); //加密 byte[] encrypted = cipher.doFinal(data.getBytes()); String encryptStr = Base64.getEncoder().encodeToString(encrypted); System.out.println("encryptStr=" + encryptStr); //解密 byte[] encodeByte = Base64Encoder.decode(encryptStr.getBytes()); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] decoder = cipher.doFinal(encodeByte); String decryptStr = new String(decoder); System.out.println("decryptStr=" + decryptStr); } }