3DES-自定义秘钥
- 固定秘钥长度(24位)
- 不固定秘钥长度(大于24位)
固定秘钥长度(24位)
public static void main(String[] arges) {
String st="cdacxe20200820cdwtybdgjl";
//秘钥(固定24位)
byte[] keyBytes = st.getBytes();
//明文(16位)
String src="asefgt1634zxcvfm";
byte[] by= src.getBytes(StandardCharsets.ISO_8859_1);
byte[] encryptMode = Des3Utils.encryptMode(keyBytes, src.getBytes());
System.out.println("加密后=="+new String(encryptMode));
byte[] decryptMode = Des3Utils.decryptMode(keyBytes, hexToByteArray(bytesToHexString(encryptMode)));
System.out.println("解密后=="+new String(decryptMode));
}
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class Des3Utils {
public static final String KEY_ALGORITHM = "DESede";
private static final String Algorithm = "DESede"; //定义加密算法,可用 DES,DESede,Blowfish
//keybyte为加密密钥,长度为24字节
//src为被加密的数据缓冲区(源)
public static byte[] encryptMode(byte[] keybyte, byte[] src) {
try {
//生成密钥
//SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
DESedeKeySpec dks = new DESedeKeySpec(keybyte);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey deskey = keyFactory.generateSecret(dks);
//加密
//明文可以任意长度,长度小于8位,补齐到8位,8到16位,补齐到16位、16到24位补齐到24位,以此类推
// Cipher c1 = Cipher.getInstance("DESede");
//明文必须是8的倍数及8位、16位、24位
Cipher c1 = Cipher.getInstance("DESede/ECB/NoPadding");
c1.init(Cipher.ENCRYPT_MODE, deskey);
return c1.doFinal(src);//在单一方面的加密或解密
} catch (java.security.NoSuchAlgorithmException e1) {
// TODO: handle exception
e1.printStackTrace();
} catch (javax.crypto.NoSuchPaddingException e2) {
e2.printStackTrace();
} catch (java.lang.Exception e3) {
e3.printStackTrace();
}
return null;
}
//keybyte为加密密钥,长度为24字节
//src为加密后的缓冲区
public static byte[] decryptMode(byte[] keybyte, byte[] src) {
try {
//生成密钥
// SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
DESedeKeySpec dks = new DESedeKeySpec(keybyte);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey deskey = keyFactory.generateSecret(dks);
//解密
//明文可以任意长度,长度小于8位,补齐到8位,8到16位,补齐到16位、16到24位补齐到24位,以此类推
// Cipher c1 = Cipher.getInstance("DESede");
//明文必须是8的倍数及8位、16位、24位
Cipher c1 = Cipher.getInstance("DESede/ECB/NoPadding");
c1.init(Cipher.DECRYPT_MODE, deskey);
return c1.doFinal(src);
} catch (java.security.NoSuchAlgorithmException e1) {
// TODO: handle exception
e1.printStackTrace();
} catch (javax.crypto.NoSuchPaddingException e2) {
e2.printStackTrace();
} catch (java.lang.Exception e3) {
e3.printStackTrace();
}
return null;
}
}
不固定秘钥长度(大于24位)
public static void main(String[] arges) {
String str = encryption("cdeyun20200820eyunkjyxgs", "123456789123456a");
System.out.println("加密后的密文为====="+str);
String decryption = decryption("cdeyun20200820eyunkjyxgs", str);
System.out.println("解密后=="+decryption);
}
/**
* dec:(解密).
* @param key 密钥
* @param content 密文内容 16位
* @return 返回结果:String
*/
public static String decryption(String key, String content) {
Des3EncryptUtils des = new Des3EncryptUtils();
String enKey = "";//最终解密秘钥 48位
String enContent = "";//解密内容
if (key.length()<24) {
throw new RuntimeException("the key length less than 24");
}
else if(key.length()>=24&&key.length() <= 32){
enKey = (key + key).substring(0, 48);
}else if(key.length() >= 48){
enKey = key.substring(0, 48);
}
if(content.length() == 16){
enContent = content;
}else{
if(content.length() > 16){
throw new RuntimeException("the encrypt content length more than 16");
}else if(content.length() < 16){
throw new RuntimeException("the encrypt content length less than 16");
}
}
des.setKey(enKey.getBytes());
byte[] fromString = HexUtils.fromString(enContent);
System.out.println();
for (byte b : fromString) {
System.out.print(b+",");
}
System.out.println();
byte[] get3DesDesCode = des.get3DesDesCode(fromString);
System.out.println("解密 de 长度="+get3DesDesCode.length);
return HexUtils.toString(get3DesDesCode).trim();
}
/**
* dec:(加密).
* @param key 密钥
* @param content 明文内容 为16位十六进制字符串
* @return 返回结果:String
*/
public static String encryption(String key, String content) {
Des3EncryptUtils des = new Des3EncryptUtils();
String enKey = "";//最终加密秘钥48位
String enContent = "";//加密内容
if(key.length() <= 32){
enKey = (key + key).substring(0, 48);
}else if(key.length() >= 48){
enKey = key.substring(0, 48);
}
if(content.length() == 16){
enContent = content;
}else{
if(content.length() > 16){
throw new RuntimeException("the encrypt content length more than 16");
}else if(content.length() < 16){
throw new RuntimeException("the encrypt content length less than 16");
}
}
des.setKey(enKey.getBytes());
byte[] bye = des.get3DesEncCode(HexUtils.fromString(enContent));
System.out.println("加密 de 长度="+bye.length);
return HexUtils.toString(bye).trim();
}
/**
* 十六进制帮助类
* @author jg
*/
public class HexUtils {
/** 转换数据 */
private static final char[] HEXDIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/**
* toString(控制长度的将byte[]的转换为相应的十六进制String表示)
*/
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);
}
/**
* 功能:将byte[]的转换为相应的十六进制字符串
* @param ba 字节数组
* @return 十六进制字符串
*/
public static String toString(byte[] ba) {
return toString(ba, 0, ba.length);
}
/**
* 功能:将十六进制字符串转换为字节数组
* @param hex 十六进制字符串
* @return 字节数组
*/
public static byte[] fromString(String hex) {
int len = hex.length();
byte[] buf = new byte[(len + 1) / 2];
int i = 0;
int 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;
}
/**
* fromDigit(将十六进制的char转换为十进制的int值)
*/
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 + "'");
}
}
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
/**
* 3DES加密工具类
* @author jg
*/
public class Des3EncryptUtils {
/** 密钥 */
private SecretKey securekey;
/**
* 功能:算法中需要通过秘钥的字节数组来得到加密用的key
* @param key 秘钥的字节数组
*/
public void setKey(byte[] key) {
try {
DESedeKeySpec dks = new DESedeKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
securekey = keyFactory.generateSecret(dks);
System.out.println("sss"+securekey.getEncoded().length);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/**
* 功能:对明文进行加密
* @param byteS 明文对应的字节数组
* @return 密文对应的字节数组
*/
public byte[] get3DesEncCode(byte[] byteS) {
System.out.println("aa"+byteS.length);
byte[] byteFina = null;
Cipher cipher;
try {
cipher = Cipher.getInstance("DESede/ECB/NoPadding"); //算法/分组模式/填充模式
cipher.init(Cipher.ENCRYPT_MODE, securekey);
byteFina = cipher.doFinal(byteS);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
cipher = null;
}
return byteFina;
}
/**
* 功能:对密文进行解密
* @param byteD 密文对应的字节数组
* @return 明文对应的字节数组
*/
public byte[] get3DesDesCode(byte[] byteD) {
System.out.println(byteD.length);
Cipher cipher;
byte[] byteFina = null;
try {
cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, securekey);
byteFina = cipher.doFinal(byteD);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
cipher = null;
}
return byteFina;
}
}
总结:
3des秘钥自己可以定义,但必须满足大于24位并是24的倍数,思路,比如你的秘钥是10位,可以重复2次并拼接4位;如果你你的秘钥是32位,可以截取也可拼接,如果要保证提供的秘钥完整型就重复再拼接。
明文也可选择填充或者固定为8位的倍数