网络安全DES算法java实现源代码
- 格式:doc
- 大小:60.50 KB
- 文档页数:11
DES加密算法javac#项⽬中⽤到的数据加密⽅式是ECB模式的DES加密得到的⼗六进制字符串。
技术⽀持让写⼀个.net版的加密算法。
这⾥做⼀下记录。
java版:16进制使⽤的是bouncycastle。
import com.emaxcard.codec.CodecException;import com.emaxcard.codec.Hex;import sun.misc.BASE64Encoder;import javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;public class DESEncrypt {public static String encodeECB(String src, String key) throws CodecException {try {SecretKey deskey = new SecretKeySpec(key.getBytes("UTF-8"), "DESede");Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, deskey);byte[] cipherInfo = cipher.doFinal(src.getBytes("UTF-8"));System.out.println("cipherInfo:"+new BASE64Encoder().encode(cipherInfo));return Hex.encode(cipherInfo);} catch (Exception var5) {throw new CodecException(var5);}}public static String decodeECB(String src, String key) throws CodecException {try {SecretKey deskey = new SecretKeySpec(key.getBytes("UTF-8"), "DESede");Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, deskey);byte[] decodeRes = cipher.doFinal(Hex.decode(src));return new String(decodeRes, "UTF-8");} catch (Exception var5) {throw new CodecException(var5);}}}public class Hex {public Hex() {}public static byte[] decode(String data) throws CodecException {try {return org.bouncycastle.util.encoders.Hex.decode(data);} catch (Exception var2) {throw new CodecException(var2.getMessage(), var2);}}public static String encode(byte[] data) {return new String(org.bouncycastle.util.encoders.Hex.encode(data));}public static void main(String[] args) throws CodecException {System.out.println(encode("a张y".getBytes()));System.out.println(new String(decode("")));}}.net(c#)版:using System;using System.IO;using System.Security.Cryptography;using System.Text;namespace ConsoleApplication1{class DESEncrypt{public static string encodeECB(string encryptString, String key){byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 8));byte[] keyIV = keyBytes;byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);DESCryptoServiceProvider provider = new DESCryptoServiceProvider();provider.Mode = CipherMode.ECB;provider.Padding = PaddingMode.PKCS7;MemoryStream mStream = new MemoryStream();CryptoStream cStream = new CryptoStream(mStream, provider.CreateEncryptor(keyBytes, keyIV), CryptoStreamMode.Write); cStream.Write(inputByteArray, 0, inputByteArray.Length);cStream.FlushFinalBlock();//return Convert.ToBase64String(mStream.ToArray());return Hex.encode(mStream.ToArray());}public static string DesDecrypt(string decryptString, String key){byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 8));byte[] keyIV = keyBytes;//byte[] inputByteArray = Convert.FromBase64String(decryptString);byte[] inputByteArray = Hex.decode(decryptString);DESCryptoServiceProvider provider = new DESCryptoServiceProvider();provider.Mode = CipherMode.ECB;provider.Padding = PaddingMode.PKCS7;MemoryStream mStream = new MemoryStream();CryptoStream cStream = new CryptoStream(mStream, provider.CreateDecryptor(keyBytes, keyIV), CryptoStreamMode.Write); cStream.Write(inputByteArray, 0, inputByteArray.Length);cStream.FlushFinalBlock();return Encoding.UTF8.GetString(mStream.ToArray());}}}using System;using System.Globalization;using System.Text;namespace ConsoleApplication1{sealed class Hex{public static byte[] decode(String mHex){mHex = mHex.Replace("", "");if (mHex.Length <= 0) return null;byte[] vBytes = new byte[mHex.Length / 2];for (int i = 0; i < mHex.Length; i += 2)if (!byte.TryParse(mHex.Substring(i, 2), NumberStyles.HexNumber, null, out vBytes[i / 2]))vBytes[i / 2] = 0;return vBytes;}public static String encode(byte[] data){//** 以下两种⽅式都可以//⽅式1StringBuilder hexString = new StringBuilder();for (int i = 0; i < data.Length; i++){hexString.AppendFormat("{0:x2}", data[i]); //System.Convert.ToString(data[i], 16);}return hexString.ToString();//⽅式2//return BitConverter.ToString(data).Replace("-", "").ToLower();}}}BitConverter.ToString⽅法签名://// 摘要:// 将指定的字节数组的每个元素的数值转换为它的等效⼗六进制字符串表⽰形式。
Java 加密解密之对称加密算法DES本文转自网络数据加密算法(Data Encryption Algorithm,DEA)是一种对称加密算法,很可能是使用最广泛的密钥系统,特别是在保护金融数据的安全中,最初开发的DEA 是嵌入硬件中的。
通常,自动取款机(Automated Teller Machine,ATM)都使用DEA。
它出自IBM的研究工作,IBM也曾对它拥有几年的专利权,但是在1983年已到期后,处于公有范围中,允许在特定条件下可以免除专利使用费而使用。
1977年被美国政府正式采纳。
1998年后实用化DES破译机的出现彻底宣告DES算法已不具备安全性,1999年NIST颁布新标准,规定DES算法只能用于遗留加密系统,但不限制使用DESede算法。
当今DES算法正是推出历史舞台,AES算法称为他的替代者。
(详见:Java 加密解密之对称加密算法AES)加密原理DES 使用一个56 位的密钥以及附加的8 位奇偶校验位,产生最大64 位的分组大小。
这是一个迭代的分组密码,使用称为Feistel 的技术,其中将加密的文本块分成两半。
使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。
DES 使用16 个循环,使用异或,置换,代换,移位操作四种基本运算。
JDK对DES算法的支持密钥长度:56位工作模式:ECB/CBC/PCBC/CTR/CTS/CFB/CFB8 to CFB128/OFB/OBF8 to OFB128填充方式:Nopadding/PKCS5Padding/ISO10126Padding/工作模式和填充方式请参考:JAVA加密解密基础十六进制工具类Hex.java,见:java byte数组与十六进制字符串互转DES加密解密的java实现:DESCoder.javaJava代码import java.security.Key;。
DES算法提供CBC, OFB, CFB, ECB四种模式,MAC是基于ECB实现的。
一、数据补位DES数据加解密就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,按照需求补足8个字节(通常补00或者FF,根据实际要求不同)进行计算,之后按照顺序将计算所得的数据连在一起即可。
这里有个问题就是为什么要进行数据补位?主要原因是DES算法加解密时要求数据必须为8个字节。
二、ECB模式DES ECB(电子密本方式)其实非常简单,就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,按照需求补足8个字节进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。
三、CBC模式DES CBC(密文分组链接方式)有点麻烦,它的实现机制使加密的各段数据之间有了联系。
其实现的机理如下:加密步骤如下:1)首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,用指定的PADDING数据补位)2)第一组数据D1与初始化向量I异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)3)第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C24)之后的数据以此类推,得到Cn5)按顺序连为即为加密结果。
解密是加密的逆过程,步骤如下:)首先将数据按照8个字节一组进行分组得到2)将第一组数据进行解密后与初始化向量I进行异或得到第一组明文D1(注意:一定是先解密再异或)3)将第二组数据C2进行解密后与第一组密文数据进行异或得到第二组数据D24)之后依此类推,得到Dn5)按顺序连为D1D2D3......Dn即为解密结果。
这里注意一点,解密的结果并不一定是我们原来的加密数据,可能还含有你补得位,一定要把补位去掉才是你的原来的数据。
*** DES算法*/public class DES {/**** @return DES算法密钥*/public static byte[] generateKey() {try {// DES算法要求有一个可信任的随机数源SecureRandom sr = new SecureRandom();// 生成一个DES算法的KeyGenerator对象KeyGenerator kg = KeyGenerator.getInstance("DES");kg.init(sr);// 生成密钥SecretKey secretKey = kg.generateKey();// 获取密钥数据byte[] key = secretKey.getEncoded();return key;} catch (NoSuchAlgorithmException e) {System.err.println("DES算法,生成密钥出错!");e.printStackTrace();}return null;}/*** 加密函数** @param data* 加密数据* @param key* 密钥* @return 返回加密后的数据*/public static byte[] encrypt(byte[] data, byte[] key) {try {// DES算法要求有一个可信任的随机数源SecureRandom sr = new SecureRandom();// 从原始密钥数据创建DESKeySpec对象DESKeySpec dks = new DESKeySpec(key);// 创建一个密匙工厂,然后用它把DESKeySpec转换成// 一个SecretKey对象SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");SecretKey secretKey = keyFactory.generateSecret(dks);// using DES in ECB modeCipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); // 用密匙初始化Cipher对象cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr);// 执行加密操作byte encryptedData[] = cipher.doFinal(data);return encryptedData;} catch (Exception e) {System.err.println("DES算法,加密数据出错!");e.printStackTrace();}return null;}/*** 解密函数** @param data* 解密数据* @param key* 密钥* @return 返回解密后的数据*/public static byte[] decrypt(byte[] data, byte[] key) {try {// DES算法要求有一个可信任的随机数源SecureRandom sr = new SecureRandom();// byte rawKeyData[] = /* 用某种方法获取原始密匙数据*/;// 从原始密匙数据创建一个DESKeySpec对象DESKeySpec dks = new DESKeySpec(key);// 创建一个密匙工厂,然后用它把DESKeySpec对象转换成// 一个SecretKey对象SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = keyFactory.generateSecret(dks);// using DES in ECB modeCipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");// 用密匙初始化Cipher对象cipher.init(Cipher.DECRYPT_MODE, secretKey, sr);// 正式执行解密操作byte decryptedData[] = cipher.doFinal(data);return decryptedData;} catch (Exception e) {System.err.println("DES算法,解密出错。
DES可逆加密算法JAVA源代码下面是一个实现DES可逆加密算法的Java源代码。
该代码共1281个字符(字母、符号、数字)。
```javaimport javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESKeySpec;import java.nio.charset.StandardCharsets;import java.util.Base64;public class DESprivate static final String key = "mysecret"; // 设置密钥public static void main(String[] args)String plainText = "Hello, World!"; // 要进行加密的明文String encryptedText = encrypt(plainText);System.out.println("Encrypted text: " + encryptedText);String decryptedText = decrypt(encryptedText);System.out.println("Decrypted text: " + decryptedText);}public static String encrypt(String plainText)tryDESKeySpec desKeySpec = newDESKeySpec(key.getBytes(StandardCharsets.UTF_8));SecretKeyFactory keyFactory =SecretKeyFactory.getInstance("DES");SecretKey secretKey = keyFactory.generateSecret(desKeySpec);Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, secretKey);byte[] encryptedBytes =cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder(.encodeToString(encryptedBytes);} catch (Exception e)e.printStackTrace(;}return null;}public static String decrypt(String encryptedText)tryDESKeySpec desKeySpec = newDESKeySpec(key.getBytes(StandardCharsets.UTF_8));SecretKeyFactory keyFactory =SecretKeyFactory.getInstance("DES");SecretKey secretKey = keyFactory.generateSecret(desKeySpec);Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, secretKey);byte[] decryptedBytes =cipher.doFinal(Base64.getDecoder(.decode(encryptedText));return new String(decryptedBytes, StandardCharsets.UTF_8);} catch (Exception e)e.printStackTrace(;}return null;}```该代码使用DES算法进行加密和解密,使用密钥"mysecret"对数据进行处理。
DES子密钥生成算法DES加密算法源代码1. 移位和循环移位:移位就是将一段数码按照规定的位数整体性地左移或右移。
循环右移就是当右移时,把数码的最后的位移到数码的最前头,循环左移正相反。
例如,对十进制数码12345678循环右移1位(十进制位)的结果为81234567,而循环左移1位的结果则为23456781。
当时自己在这里栽过很大的跟头,这里的循环移位,指的是前后28位密码的位置循环左移,比如49 42 35 28 21 14 7 42 35 28 21 14 7 00 50 43 36 29 22 15 循环左移一位 50 43 36 29 22 15 88 1 51 44 37 30 23 ————————> 1 51 44 37 30 23 1616 9 2 52 45 38 31 9 2 52 45 38 31 492. 置换:就是将数码中的某一位的值根据置换表的规定,用另一位代替。
它不像移位操作那样整齐有序,看上去杂乱无章。
这正是加密所需,被经常应用。
DES密钥扩展算法:for each round i = 1,2,3....nLK = cyclically left shift LK by ri bitsRK = cyclically left shift RK by ri bitsThe left half of subkey Ki consists of bits of LP of LKThe right half of subkey Ki consits of bits of RP of RKnext i具体的操作:特别注意:这里讲的数字都是指密钥的具体位置,而不是密钥的内容1. 我们将DES的56位密钥从左到右从0开始编号。
首先扩展DES 密钥的前28位,并进行置换,结果称为LK,DES密钥的LK是原始密钥的下列各位:49 42 35 28 21 14 70 50 43 36 29 22 158 1 51 44 37 30 2316 9 2 52 45 38 31通俗讲,就是说第一位前面的28位密钥中,第一位放的元素就是原先56中的第49位,第二位就是原先的42位2. 类似的,DES密钥的剩余28位称为RK,由原始密钥的下列各位构成55 48 41 34 27 20 136 54 47 40 33 26 1912 5 53 46 39 32 2518 11 4 24 17 10 33. 在进行密钥扩张算法之前,还需要定义LP置换:13 16 10 23 0 4 2 27 14 5 20 922 18 11 3 25 7 15 6 26 19 12 1这也是我刚开始百思不得其解的地方,其实也很简单,就是将经过移位之后的左边的28位密钥重现编号,再按下标放好缺少8,17,21,244.RP置换12 23 2 8 18 26 1 11 22 16 4 1915 20 10 27 5 24 17 13 21 7 0 3缺少了6,9,14,25具体实现的代码:view plaincopy to clipboardprint?#includeint secretKey[56];//密钥int subSecretKey[17][48];//16轮的子密钥1-16int leftSecretKey[28];int rightSecretKey[28];int subLeftSecretKey[24];int subRightSecretKey[24];int sumOfk[56];int LK[28] = {49,42,35,28,21,14,7,0,50,43,36,29,22,15,8,1,51,44,37,30,23,16,9,2,52,45,38,31};int RK[28] = {55,48,41,34,27,20,13,6,54,47,40,33,26,19,12,5,53,46,39,32,25,18,11,4,24,17,10,3};int LP[24] = { //缺少8,17,21,2413,16,10,23,0,4,2,27,14,5,20,9,22,18,11,3,25,7,15,6,26,19,12,1};int RP[24] = { //缺少6,9,14,2512,23,2,8,18,26,1,11,22,16,4,19,15,20,10,27,5,24,17,13,21,7,0,3};void leftshiftby1(); //循环左移一位void leftshiftby2(); //循环左移两位void leftLK(); //映射,形成leftSecretKey[28]void rightRK(); //映射,形成rightSecretKey[28]void leftLP(); //置换,形成subLeftSecretKey[24]void rightRP(); //置换,形成subRightSecretKey[24]; void printSubSecretKey(); //将16轮的子密钥全部打印出来voidcomputeSumOfk(); //计算机每个密钥位的使用次数void printSumOfk(); //将每个密钥位的使用次数打印出来int main(){ int i;//密钥的初始化for(i=0;i<56;i++){secretKey[i] = i;}//16轮的子密钥生成for(i=1;i<=16;i++){if(i==1 || i==2 ||i==9 ||i==16){//循环左移一位leftshiftby1();}else{//循环左移两位leftshiftby2();}//映射,形成leftSecretKey[28],rightSecretKey[28]leftLK();rightRK();//置换,形成subLeftSecretKey[24],subRightSecretKey[24];leftLP();rightRP();//生成第i轮的子密钥for(int s=0;s<48;s++){if(s<24){subSecretKey[i][s] = subLeftSecretKey[s];}else{subSecretKey[i][s] = subRightSecretKey[s-24];}}}//输出16轮的子密钥printSubSecretKey();computeSumOfk();printSumOfk();return 0;}void leftshiftby1(){int tempLeft = LK[0];int tempRight = RK[0];for(int i=0;i<27;i++){LK[i] = LK[i+1];RK[i] = RK[i+1];}LK[27] = tempLeft;RK[27] = tempRight;}void leftshiftby2(){int tempLeft1 = LK[0],tempLeft2 = LK[1];int tempRight1 = RK[0],tempRight2 = RK[1]; for(int i=0;i<26;i++){LK[i] = LK[i+2];RK[i] = RK[i+2];}LK[26] = tempLeft1;LK[27] = tempLeft2;RK[26] = tempRight1;RK[27] = tempRight2;}void leftLK(){for(int i=0;i<28;i++){leftSecretKey[i] = secretKey[LK[i]];}}void rightRK(){for(int i=0;i<28;i++){rightSecretKey[i] = secretKey[RK[i]];}}void leftLP(){for(int i=0;i<24;i++){ subLeftSecretKey[i] = leftSecretKey[LP[i]];}}void rightRP(){for(int i=0;i<24;i++){ subRightSecretKey[i] = rightSecretKey[RP[i]]; }}void printSubSecretKey(){int i,j;for(i=1;i<=16;i++){for(j=0;j<48;j++){printf("%3d",subSecretKey[i][j]);if(23==j)printf("\n");}printf("\n\n");}}void computeSumOfk(){int i,j;//对SumOfk清零for(i=0;i<56;i++){sumOfk[i] = 0;}for(i=1;i<=16;i++){for(j=0;j<48;j++){sumOfk[subSecretKey[i][j]]++; }}}void printSumOfk(){int i;for(i=0;i<56;i++){printf("%3d: %3d\n",i,sumOfk[i]); }}。
/** java 版的* <p>Title: DES 加解密算法</p>* <p>Description: DES 加解密算法</p>* <p>Copyright: Copyright (c) 2004</p>* <p>Company: Aspire Corp</p>* @author zhangji* @version 1.0*/import java.security.*;import javax.crypto.*;public class DES {private static String strDefaultKey = "hnzt";private Cipher encryptCipher = null;private Cipher decryptCipher = null;/*** 将byte数组转换为表示16进制值的字符串,* 如:byte[]{8,18}转换为:0813,* 和public static byte[] hexStr2ByteArr(String strIn)* 互为可逆的转换过程* @param arrB 需要转换的byte数组* @return 转换后的字符串* @throws Exception 本方法不处理任何异常,所有异常全部抛出*/public static String byteArr2HexStr(byte[] arrB)throws Exception{int iLen = arrB.length;//每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍StringBuffer sb = new StringBuffer(iLen * 2);for (int i = 0; i < iLen; i++){int intTmp = arrB[i];//把负数转换为正数while (intTmp < 0){intTmp = intTmp + 256;}//小于0F的数需要在前面补0if (intTmp < 16){sb.append("0");}sb.append(Integer.toString(intTmp, 16));}return sb.toString();}/*** 将表示16进制值的字符串转换为byte数组,* 和public static String byteArr2HexStr(byte[] arrB)* 互为可逆的转换过程* @param strIn 需要转换的字符串* @return 转换后的byte数组* @throws Exception 本方法不处理任何异常,所有异常全部抛出* @author <a href="mailto:zhangji@">ZhangJi</a> */public static byte[] hexStr2ByteArr(String strIn)throws Exception{byte[] arrB = strIn.getBytes();int iLen = arrB.length;//两个字符表示一个字节,所以字节数组长度是字符串长度除以2byte[] arrOut = new byte[iLen / 2];for (int i = 0; i < iLen; i = i + 2){String strTmp = new String(arrB, i, 2);arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);}return arrOut;}/*** 默认构造方法,使用默认密钥* @throws Exception*/public DES()throws Exception{this(strDefaultKey);}/*** 指定密钥构造方法* @param strKey 指定的密钥* @throws Exception*/public DES(String strKey)throws Exception{Security.addProvider(new com.sun.crypto.provider.SunJCE()); Key key = getKey(strKey.getBytes());encryptCipher = Cipher.getInstance("DES");encryptCipher.init(Cipher.ENCRYPT_MODE, key);decryptCipher = Cipher.getInstance("DES");decryptCipher.init(Cipher.DECRYPT_MODE, key);}/*** 加密字节数组* @param arrB 需加密的字节数组* @return 加密后的字节数组* @throws Exception*/public byte[] encrypt(byte[] arrB)throws Exception{return encryptCipher.doFinal(arrB);}/*** 加密字符串* @param strIn 需加密的字符串* @return 加密后的字符串* @throws Exception*/public String encrypt(String strIn)throws Exception{return byteArr2HexStr(encrypt(strIn.getBytes())); }/*** 解密字节数组* @param arrB 需解密的字节数组* @return 解密后的字节数组* @throws Exception*/public byte[] decrypt(byte[] arrB)throws Exception{return decryptCipher.doFinal(arrB);}/*** 解密字符串* @param strIn 需解密的字符串* @return 解密后的字符串* @throws Exception*/public String decrypt(String strIn)throws Exception{return new String(decrypt(hexStr2ByteArr(strIn)));}/*** 从指定字符串生成密钥,密钥所需的字节数组长度为8位* 不足8位时后面补0,超出8位只取前8位* @param arrBTmp 构成该字符串的字节数组* @return 生成的密钥* @throws ng.Exception*/private Key getKey(byte[] arrBTmp)throws Exception{//创建一个空的8位字节数组(默认值为0)byte[] arrB = new byte[8];//将原始字节数组转换为8位for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {arrB[i] = arrBTmp[i];}//生成密钥Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES"); return key;}/*** 单元测试方法* @param args*/public static void main(String[] args){String strOriginal = "1111";String strOp = "-de";// 检查入参个数if (args.length == 2 ){strOp = args[0] ;strOriginal = args[1];}else{System.out.println("Wrong Parameter count , try use \"java DES -de|-en 'the string you want to be Encrypted'\"");System.out.println("Now do Encrypt with \"1111\"");try{DES des = new DES();// 加密测试System.out.println("***** 加密测试 *****") ;des.enTest("1111");// 解密测试System.out.println("***** 解密测试 *****") ;des.deTest("0fc7648b53e54cfb");}catch (Exception ex){ex.printStackTrace();}return ;}try{if ( strOp.equals("-de")) {DES des = new DES();des.deTest(strOriginal);}else if ( strOp.equals("-en")) {DES des = new DES();des.enTest(strOriginal);}else{System.out.println("Wrong operater , try use \"java DES -de|-en 'the string you want to be Encrypted'\"");System.out.println("Now do Encrypt with \"1111\""); }}catch (Exception ex){ex.printStackTrace();}}/*** 单元测试方法,打印对指定字符串加密后的字符串*/private void enTest(String strOriginal){try{System.out.println("Plain String: " + strOriginal);String strEncrypt= encrypt(strOriginal);System.out.println("Encrypted String: " + strEncrypt);}catch (Exception ex){ex.printStackTrace();}}/*** 单元测试方法,打印对指定字符串解密后的字符串*/private void deTest(String strOriginal){try{System.out.println("Encrypted String: " + strOriginal); System.out.println("Encrypted String length = " + strOriginal.length());String strPlain = decrypt(strOriginal);System.out.println("Plain String: " + strPlain);}catch (Exception ex){ex.printStackTrace();}}}===============c#版的================using System;using System.Text;using System.IO;using System.Security.Cryptography;class Class1{static void Main(){Console.WriteLine("Encrypt String...");txtKey = "tkGGRmBErvc=";btnKeyGen();Console.WriteLine("Encrypt Key :{0}",txtKey);txtIV = "Kl7ZgtM1dvQ=";btnIVGen();Console.WriteLine("Encrypt IV :{0}",txtIV);Console.WriteLine();string txtEncrypted = EncryptString("1111");Console.WriteLine("Encrypt String : {0}",txtEncrypted);string txtOriginal = DecryptString(txtEncrypted);Console.WriteLine("Decrypt String : {0}",txtOriginal);}private static SymmetricAlgorithm mCSP;private static string txtKey;private static string txtIV;private static void btnKeyGen(){mCSP = SetEnc();byte[] byt2 = Convert.FromBase64String(txtKey);mCSP.Key = byt2;}private static void btnIVGen(){byte[] byt2 = Convert.FromBase64String(txtIV);mCSP.IV = byt2;}private static string EncryptString(string Value){ICryptoTransform ct;MemoryStream ms;CryptoStream cs;byte[] byt;ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV);byt = Encoding.UTF8.GetBytes(Value);ms = new MemoryStream();cs = new CryptoStream(ms, ct, CryptoStreamMode.Write); cs.Write(byt, 0, byt.Length);cs.FlushFinalBlock();cs.Close();return Convert.ToBase64String(ms.ToArray());}private static string DecryptString(string Value){ICryptoTransform ct;MemoryStream ms;CryptoStream cs;byte[] byt;ct = mCSP.CreateDecryptor(mCSP.Key, mCSP.IV);byt = Convert.FromBase64String(Value);ms = new MemoryStream();cs = new CryptoStream(ms, ct, CryptoStreamMode.Write); cs.Write(byt, 0, byt.Length);cs.FlushFinalBlock();cs.Close();return Encoding.UTF8.GetString(ms.ToArray());}private static SymmetricAlgorithm SetEnc() {return new DESCryptoServiceProvider(); }}。
DES算法实现:java语言下可以导入org.apache前缀的类库,apache组织给出了org.apache.codec类库,将基本的加密和解密方法打包成现成方法,并且提供了DES算法必备的S盒。
所以这个实现方法会采用org.apache.codec类库,采用结合源代码的方式进行编写。
工程名为ZDESAl即DES Algorithm,下面包含两个类,DESCoder负责生成密钥,DESCoderTest负责进行密钥的左移、置换选择,扩充等操作。
下面给出DESCoder类的设计思路和源代码:import java.security.Key;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESKeySpec;/***DES安全编码组件*@author Hawke7*@version 1.0*/public abstract class DESCoder {/***密钥算法<br>*Java6只支持56位密钥<br>*Bouncy Castle支持64位密钥*/public static final String KEY_ALGORITHM = "DES";/***加密/解密算法/工作模式/填充方式*/public static final String CIPHER_ALGORITHM= "DES/ECB/PKCS5Padding";/***转换密钥*@param key二进制密钥*@return key二进制密钥*@throws Exception*/private static Key toKey(byte[] key) throws Exception {// 实例化DES密钥材料DESKeySpec dks = new DESKeySpec(key);// 实例化秘密密钥工厂SecretKeyFactory keyFactory =SecretKeyFactory.getInstance(KEY_ALGORITHM);// 生成私密密钥SecretKey secretKey = keyFactory.generateSecret(dks);return secretKey;}/***解密*@param data待解密数据*@param key密钥*@return byte[]解密数据*@throws Exception*/public static byte[] decrypt(byte[] data, byte[] key) throws Exception {// 还原密钥Key k = toKey(key);// 实例化Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);// 初始化,设置为解密模式cipher.init(Cipher.DECRYPT_MODE, k);// 执行操作return cipher.doFinal(data);}/***加密*@param data待加密数据*@param key密钥*@return byte[]加密数据*@throws Exception*/public static byte[] encrypt(byte[] data, byte[] key) throws Exception {// 还原密钥Key k = toKey(key);// 实例化Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);// 初始化,设置为解密模式cipher.init(Cipher.ENCRYPT_MODE, k);// 执行操作return cipher.doFinal(data);}/***生成密钥<br>*Java6只支持56位密钥<br>*Bouncy Castle支持64位密钥<br>*@return byte[]二进制密钥*@throws Exception*/public static byte[] initKey() throws Exception {/** 实例化密钥生成器* 若要使用64位密钥注意替换* 将下述代码中的* KeyGenerator.getInstance(CIPHER_ALGORITHM);* 替换为* KeyGenerator.getInstance(CIPHER_ALGORITHM, "BC");*/KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);/** 初始化密钥生成器* 若要使用64位密钥注意替换* 将下面代码kg.init(56)* 替换为kg.init(64)*/kg.init(56);// 生成私密密钥SecretKey secretKey = kg.generateKey();// 获得密钥的二进制编码形式return secretKey.getEncoded();}}首先DESCoder要定义成抽象类,因为其中全部是static静态方法toKey,toKey初始化密钥材料,并且实例化密钥工厂,因为DES算法要进行16轮迭代,所以工厂每一次都要给出不同的密钥,从而增强雪崩效应。
JAVA加密解密DES对称加密算法1下⾯⽤DES对称加密算法(设定⼀个密钥,然后对所有的数据进⾏加密)来简单举个例⼦。
23⾸先,⽣成⼀个密钥KEY。
4我把它保存到key.txt中。
这个⽂件就象是⼀把钥匙。
谁拥有它,谁就能解开我们的类⽂件。
代码参考如下:5package com.neusoft.jiami;6import Java.io.File;7import java.io.FileOutputStream;8import java.security.SecureRandom;9import javax.crypto.KeyGenerator;10import javax.crypto.SecretKey;11class Key {12private String keyName;13public Key(String keyName) {14this.keyName = keyName;15 }16public void createKey(String keyName) throws Exception {17// 创建⼀个可信任的随机数源,DES算法需要18 SecureRandom sr = new SecureRandom();19// ⽤DES算法创建⼀个KeyGenerator对象20 KeyGenerator kg = KeyGenerator.getInstance("DES");21// 初始化此密钥⽣成器,使其具有确定的密钥长度22 kg.init(sr);23// ⽣成密匙24 SecretKey key = kg.generateKey();25// 获取密钥数据26byte rawKeyData[] = key.getEncoded();27// 将获取到密钥数据保存到⽂件中,待解密时使⽤28 FileOutputStream fo = new FileOutputStream(new File(keyName));29 fo.write(rawKeyData);30 }31public static void main(String args[]) {32try {33new Key("key.txt");34 } catch (Exception e) {35 e.printStackTrace();36 }37 }38 }39第⼆步,对我们所要进⾏加密的类⽂件进⾏加密。
DES加密算法代码java实现DES加密1.准备算法所需要的密钥在Java中,DES加密算法需要一个8字节长的密钥,这里使用原始的8字节长的密钥来实现DES加密算法,同时,还有一种是“密钥扩展”,可以将8字节长的密钥扩展为16字节长,只需要多添加8个字节,后面8个字节可以跟前面8字节保持一致即可,即扩展后的密钥和原始密钥共享后八个字节即可。
byte [] keyBytes = {0x11, 0x22, 0x4F, 0x58, (byte) 0x88,0x10, 0x40, 0x38,0x28, 0x25, 0x79, 0x51, (byte) 0xCB, (byte) 0xDD, 0x55, 0x66, 0x77, 0x29, 0x74, (byte) 0x98, 0x30, 0x40, 0x36, (byte)0xE2};下面介绍如何用Java来实现原始的8字节长的密钥:// 生成keyKeyGenerator keyGenerator = KeyGenerator.getInstance("DES");keyGenerator.init(new SecureRandom(keyBytes));SecretKey key = keyGenerator.generateKey(;2. 设置加密模式(Cipher Block Chaining Mode,简称CBC模式)在Java中,DES加密算法可以支持三种不同的加密模式:ECB,CBC,CFB。
其中ECB模式为最原始的模式,它不需要任何附加的参数,而CBC模式需要一个8字节的初始向量(Initial Vector,IV)参数,CFB模式需要一个1字节或8字节的变量参数,它们用来增加加密的强度。
这里,我们使用CBC模式,它是最常用的DES加密模式,下面是设置CBC模式所需要的参数:// 创建Cipher对象,指定其支持的DES算法Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");// 用密匙初始化Cipher对象IvParameterSpec param = new IvParameterSpec(iv);cipher.init(Cipher.ENCRYPT_MODE, key,param);3.加密。
public class DesUtil {byte[] bytekey;public DesUtil(String strKey) {this.bytekey = strKey.getBytes();}// 声明常量字节数组private static final int[] IP = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52,44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48,40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35,27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31,23, 15, 7 }; // 64private static final int[] IP_1 = { 40, 8, 48, 16, 56, 24, 64, 32, 39, 7,47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45,13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11,51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49,17, 57, 25 }; // 64private static final int[] PC_1 = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50,42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44,36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6,61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 }; // 56private static final int[] PC_2 = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47,55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36,29, 32 }; // 48private static final int[] E = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9,10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20,21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 }; // 48 private static final int[] P = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23,26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22,11, 4, 25 }; // 32private static final int[][][] S_Box = {//S-盒{// S_Box[1]{ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }, { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 }, { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 }, { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } }, { // S_Box[2]{ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },{ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 }, { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 }, { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } }, { // S_Box[3]{ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },{ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 }, { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 }, { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } }, { // S_Box[4]{ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },{ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 }, { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 }, { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } }, { // S_Box[5]{ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },{ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 }, { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 }, { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } }, { // S_Box[6]{ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },{ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },{ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },{ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } },{ // S_Box[7]{ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },{ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },{ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },{ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } },{ // S_Box[8]{ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },{ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },{ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },{ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } }};private static final int[] LeftMove = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,2, 2, 2, 1 };// 左移位置列表private byte[] UnitDes(byte[] des_key, byte[] des_data, int flag) {// 检测输入参数格式是否正确,错误直接返回空值(null)if ((des_key.length != 8) || (des_data.length != 8)|| ((flag != 1) && (flag != 0))) { throw new RuntimeException("Data Format Error !");}int flags = flag;// 二进制加密密钥int[] keydata = new int[64];// 二进制加密数据int[] encryptdata = new int[64]; // 加密操作完成后的字节数组byte[] EncryptCode = new byte[8];// 密钥初试化成二维数组int[][] KeyArray = new int[16][48];// 将密钥字节数组转换成二进制字节数组keydata = ReadDataToBirnaryIntArray(des_key);// 将加密数据字节数组转换成二进制字节数组encryptdata = ReadDataToBirnaryIntArray(des_data);// 初试化密钥为二维密钥数组KeyInitialize(keydata, KeyArray); // 执行加密解密操作EncryptCode = Encrypt(encryptdata, flags, KeyArray);return EncryptCode;}// 初试化密钥数组private void KeyInitialize(int[] key, int[][] keyarray) {int i;int j;int[] K0 = new int[56];// 特别注意:xxx[IP[i]-1]等类似变换for (i = 0; i < 56; i++) {K0[i] = key[PC_1[i] - 1]; // 密钥进行PC-1变换}for (i = 0; i < 16; i++) {LeftBitMove(K0, LeftMove[i]); // 特别注意:xxx[IP[i]-1]等类似变换for (j = 0; j < 48; j++) {keyarray[i][j] = K0[PC_2[j] - 1]; // 生成子密钥keyarray[i][j]}}} // 执行加密解密操作private byte[] Encrypt(int[] timeData, int flag, int[][] keyarray) { int i;byte[] encrypt = new byte[8];int flags = flag;int[] M = new int[64];int[] MIP_1 = new int[64];// 特别注意:xxx[IP[i]-1]等类似变换for (i = 0; i < 64; i++) {M[i] = timeData[IP[i] - 1]; // 明文IP变换}if (flags == 1) { // 加密for (i = 0; i < 16; i++) {LoopF(M, i, flags, keyarray);}} else if (flags == 0) { // 解密for (i = 15; i > -1; i--) {LoopF(M, i, flags, keyarray);}}for (i = 0; i < 64; i++) {MIP_1[i] = M[IP_1[i] - 1]; // 进行IP-1运算}GetEncryptResultOfByteArray(MIP_1, encrypt);// 返回加密数据return encrypt;}private int[] ReadDataToBirnaryIntArray(byte[] intdata) {int i;int j;// 将数据转换为二进制数,存储到数组int[] IntDa = new int[8];for (i = 0; i < 8; i++) {IntDa[i] = intdata[i];if (IntDa[i] < 0) {IntDa[i] += 256;IntDa[i] %= 256;}}int[] IntVa = new int[64];for (i = 0; i < 8; i++) {for (j = 0; j < 8; j++) {IntVa[((i * 8) + 7) - j] = IntDa[i] % 2;IntDa[i] = IntDa[i] / 2;}}return IntVa;}private void LeftBitMove(int[] k, int offset) { int i;// 循环移位操作函数int[] c0 = new int[28];int[] d0 = new int[28];int[] c1 = new int[28];int[] d1 = new int[28];for (i = 0; i < 28; i++) {c0[i] = k[i];d0[i] = k[i + 28];}if (offset == 1) {for (i = 0; i < 27; i++) { // 循环左移一位c1[i] = c0[i + 1];d1[i] = d0[i + 1];}c1[27] = c0[0];d1[27] = d0[0];} else if (offset == 2) {for (i = 0; i < 26; i++) { // 循环左移两位c1[i] = c0[i + 2];d1[i] = d0[i + 2];}c1[26] = c0[0];d1[26] = d0[0];c1[27] = c0[1];d1[27] = d0[1];}for (i = 0; i < 28; i++) {k[i] = c1[i];k[i + 28] = d1[i];}}private void LoopF(int[] M, int times, int flag, int[][] keyarray) {int i;int j;int[] L0 = new int[32];int[] R0 = new int[32];int[] L1 = new int[32];int[] R1 = new int[32];int[] RE = new int[48];int[][] S = new int[8][6];int[] sBoxData = new int[8];int[] sValue = new int[32];int[] RP = new int[32];for (i = 0; i < 32; i++) {L0[i] = M[i]; // 明文左侧的初始化R0[i] = M[i + 32]; // 明文右侧的初始化}for (i = 0; i < 48; i++) {RE[i] = R0[E[i] - 1]; // 经过E变换扩充,由32位变为48位RE[i] = RE[i] + keyarray[times][i]; // 与KeyArray[times][i]按位作不进位加法运算if (RE[i] == 2) {RE[i] = 0;}}for (i = 0; i < 8; i++) { // 48位分成8组for (j = 0; j < 6; j++) {S[i][j] = RE[(i * 6) + j];}// 下面经过S盒,得到8个数sBoxData[i] = S_Box[i][(S[i][0] << 1) + S[i][5]][(S[i][1] << 3)+ (S[i][2] << 2) + (S[i][3] << 1) + S[i][4]];// 8个数变换输出二进制for (j = 0; j < 4; j++) {sValue[((i * 4) + 3) - j] = sBoxData[i] % 2;sBoxData[i] = sBoxData[i] / 2;}}for (i = 0; i < 32; i++) {RP[i] = sValue[P[i] - 1]; // 经过P变换L1[i] = R0[i]; // 右边移到左边R1[i] = L0[i] + RP[i];if (R1[i] == 2) {R1[i] = 0;}// 重新合成M,返回数组M// 最后一次变换时,左右不进行互换。