DES对称加密算法实现:Java,C#,Golang,Python
数据加密标准(DES,Data Encryption Standard,简写DES)是一种采用块密码加密的对称密钥算法,加密分组长度为64位,其中8、16、24、32、40、48、56、64 等8位是校验位,其余56位作为秘钥。
DES加密解密需要一个秘钥,使用这个秘钥加密的数据只能使用这个秘钥解密,这样,如果两个客户端在传输数据前先使用DES进行加密,那么就算传输密文被窃取,不知道秘钥就没办法解密,这就保证了数据的安全性。
DES是比较的老的加密算法,现已被证实可被破解,能不用就不用吧,可使用AES加密算法代替:AES对称加密算法实现:Java,C#,Golang,Python。
下面使用介绍各语言中的DES加密解密实现:
声明
1、加密解密过程分别使用比较多的ECB和CBC两种方式来实现,ECB性能更快,但是安全性没有CBC好,所以目前CBC用的比较多 2、加密解密填充方式采用PKCS7,或者PKCS5,这两者在这里的加密解密过程中的结果可以认为是一样的
3、CBC模式需要秘钥及初始向量,而ECB模式只需要秘钥即可,所以为了方便,下面封装的方法或者函数将通过判断是否存在初始向量来决定是使用CBC模式还是使用ECB模式
Java
Java中默认采用ECB模式,可以先做一个封装:

import java.security.Key; import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.IvParameterSpec; public class DesUtil { /** * DES加密 * * @param value * 待机加密明文 * @param secretKey * 秘钥 * @param iv * 初始向量,如果未空,则将采用ECB模式,否则采用CBC模式 * * @return 密文 */ public static String desEncrypt(String value, String secretKey, String iv) throws Exception { if (value == null || value.length() == 0) return ""; Cipher cipher = initCipher(Cipher.ENCRYPT_MODE, secretKey, iv); byte[] bytes = cipher.doFinal(value.getBytes("utf-8")); // 使用hex格式数据输出 StringBuffer result = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { result.append(String.format("%02x", bytes[i])); } return result.toString(); } /** * DES解密 * * @param value * 密文 * @param secretKey * 秘钥 * @param iv * 初始向量,如果未空,则将采用ECB模式,否则采用CBC模式 * * @return 解密后的明文 */ public static String desDecrypt(String value, String secretKey, String iv) throws Exception { if (value == null || value.length() == 0) return ""; // 转换hex格式数据未byte数组 int length = value.length(); byte[] buffer = new byte[length / 2]; for (int i = 0; i < buffer.length; i++) { buffer[i] = (byte) Integer.parseInt( value.substring(i * 2, i * 2 + 2), 16); } Cipher cipher = initCipher(Cipher.DECRYPT_MODE, secretKey, iv); buffer = cipher.doFinal(buffer); return new String(buffer, "utf-8"); } private static Cipher initCipher(int mode, String secretKey, String iv) throws Exception { try { // 获取秘钥数组 byte[] secretBytes = secretKey.getBytes("utf-8"); byte[] keyBytes = new byte[8]; System.arraycopy(secretBytes, 0, keyBytes, 0, Math.min(secretBytes.length, keyBytes.length)); DESKeySpec dks = new DESKeySpec(keyBytes); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); Key key = keyFactory.generateSecret(dks); if (iv == null || iv.length() == 0) { Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");// 采用ECB方式 cipher.init(mode, key); return cipher; } else { // 初始向量数组 byte[] ivBytes = iv.getBytes("utf-8"); byte[] ivKeyBytes = new byte[8]; System.arraycopy(ivBytes, 0, ivKeyBytes, 0, Math.min(ivBytes.length, ivKeyBytes.length)); IvParameterSpec ivp = new IvParameterSpec(ivKeyBytes); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");// 采用CBC方式 cipher.init(mode, key, ivp); return cipher; } } catch (Exception e) { e.printStackTrace(); throw e; } } }
然后我们可以调用这个封装好的类去进行加密解密:
public static void main(String[] args) { String text = "上山打老虎"; String key = "123456";// 秘钥 String iv = "abcdefg";// 初始向量 try { String encryptText1 = DesUtil.desEncrypt(text, key, iv); System.out.printf("【%s】经过【DES-CBC】加密后:%s\n", text, encryptText1); String decryptText1 = DesUtil.desDecrypt(encryptText1, key, iv); System.out.printf("【%s】经过【DES-CBC】解密后:%s\n", encryptText1, decryptText1); String encryptText2 = DesUtil.desEncrypt(text, key, null); System.out.printf("【%s】经过【DES-ECB】加密后:%s\n", text, encryptText2); String decryptText2 = DesUtil.desDecrypt(encryptText2, key, null); System.out.printf("【%s】经过【DES-ECB】解密后:%s\n", encryptText2, decryptText2); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
执行结果:
C#
C#中默认采用CBC模式,同样做一个封装类:

using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; namespace ConsoleApp1 { public class DesHelper { #region DES /// <summary> /// 创建算法操作对象 /// </summary> /// <param name="secretKey">秘钥</param> /// <param name="iv">初始向量为空则采用ECB,否则采用CBC</param> /// <returns></returns> private static DESCryptoServiceProvider CreateCryptoServiceProvider(string secretKey, string iv) { DESCryptoServiceProvider des = new DESCryptoServiceProvider(); //秘钥数组 byte[] secretBytes = Encoding.UTF8.GetBytes(secretKey); byte[] keyBytes = new byte[8]; Array.Copy(secretBytes, keyBytes, Math.Min(secretBytes.Length, keyBytes.Length)); des.Key = keyBytes; if (!string.IsNullOrEmpty(iv)) { //初始向量数组 byte[] array = Encoding.UTF8.GetBytes(iv); byte[] ivBytes = new byte[keyBytes.Length]; Array.Copy(array, ivBytes, Math.Min(array.Length, ivBytes.Length)); des.IV = ivBytes; des.Mode = CipherMode.CBC;//CBC模式 } else { des.Mode = CipherMode.ECB;//ECB模式 } des.Padding = PaddingMode.PKCS7;//填充方式 return des; } /// <summary> /// Des加密 /// </summary> /// <param name="value">待加密的明文</param> /// <param name="secretKey">秘钥</param> /// <param name="iv">初始向量为空则采用ECB,否则采用CBC</param> /// <returns>密文</returns> public static string DesEncrypt(string value, string secretKey, string iv) { if (string.IsNullOrEmpty(value)) return string.Empty; using (DESCryptoServiceProvider des = CreateCryptoServiceProvider(secretKey, iv)) { byte[] buffer = Encoding.UTF8.GetBytes(value); System.IO.MemoryStream ms = new System.IO.MemoryStream(); using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(buffer, 0, buffer.Length); cs.FlushFinalBlock(); buffer = ms.ToArray(); //使用hex格式数据输出 StringBuilder result = new StringBuilder(); foreach (byte b in buffer) { result.AppendFormat("{0:x2}", b); } return result.ToString(); //或者使用下面的输出 //return BitConverter.ToString(buffer).Replace("-", "").ToLower(); } } } /// <summary> /// Des解密 /// </summary> /// <param name="value">密文</param> /// <param name="secretKey">秘钥</param> /// <param name="iv">初始向量为空则采用ECB,否则采用CBC</param> /// <returns>解密后的明文</returns> public static string DesDecrypt(string value, string secretKey, string iv) { if (string.IsNullOrEmpty(value)) return string.Empty; using (DESCryptoServiceProvider des = CreateCryptoServiceProvider(secretKey, iv)) { //转换hex格式数据为byte数组 byte[] buffer = new byte[value.Length / 2]; for (var i = 0; i < buffer.Length; i++) { buffer[i] = (byte)Convert.ToInt32(value.Substring(i * 2, 2), 16); } System.IO.MemoryStream ms = new System.IO.MemoryStream(); using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(buffer, 0, buffer.Length); cs.FlushFinalBlock(); return Encoding.UTF8.GetString(ms.ToArray()); } } } #endregion } }
然后测试加密解密:
static void Main(string[] args) { string text = "上山打老虎"; string key = "123456"; // 秘钥 string iv = "abcdefg"; // 初始向量 string encryptText1 = DesHelper.DesEncrypt(text, key, iv); Console.WriteLine($"【{text}】经过【DES-CBC】加密后:{encryptText1}"); string decryptText1 = DesHelper.DesDecrypt(encryptText1, key, iv); Console.WriteLine($"【{encryptText1}】经过【DES-CBC】解密后:{decryptText1}"); string encryptText2 = DesHelper.DesEncrypt(text, key, null); Console.WriteLine($"【{text}】经过【DES-ECB】加密后:{encryptText2}"); string decryptText2 = DesHelper.DesDecrypt(encryptText2, key, null); Console.WriteLine($"【{encryptText2}】经过【DES-ECB】解密后:{decryptText2}"); }
执行结果:
Golang
可能因为ECB模式不太安全,所有go中并没有封装好ECB模式的直接加密解密过程,但是我们还是可以实现:

package main import ( "bytes" "crypto/cipher" "crypto/des" "fmt" "strconv" ) //DES加密 //iv为空则采用ECB模式,否则采用CBC模式 func DesEncrypt(value, secretKey, iv string) (string, error) { if value == "" { return "", nil } //根据秘钥生成8位的秘钥切片 keyBytes := make([]byte, des.BlockSize) copy(keyBytes, []byte(secretKey)) //获取block block, err := des.NewCipher(keyBytes) if err != nil { return "", err } blocksize := block.BlockSize() valueBytes := []byte(value) //填充 fillsize := blocksize - len(valueBytes)%blocksize repeat := bytes.Repeat([]byte{byte(fillsize)}, fillsize) valueBytes = append(valueBytes, repeat...) result := make([]byte, len(valueBytes)) //加密 if iv == "" { temp := result for len(valueBytes) > 0 { block.Encrypt(temp, valueBytes[:blocksize]) valueBytes = valueBytes[blocksize:] temp = temp[blocksize:] } } else { //向量切片 ivBytes := make([]byte, des.BlockSize) copy(ivBytes, []byte(iv)) encrypter := cipher.NewCBCEncrypter(block, ivBytes) encrypter.CryptBlocks(result, valueBytes) } //以hex格式数值输出 encryptText := fmt.Sprintf("%x", result) return encryptText, nil } //DES解密 //iv为空则采用ECB模式,否则采用CBC模式 func DesDecrypt(value, secretKey, iv string) (string, error) { if value == "" { return "", nil } //根据秘钥生成8位的秘钥切片 keyBytes := make([]byte, des.BlockSize) copy(keyBytes, []byte(secretKey)) //获取block block, err := des.NewCipher(keyBytes) if err != nil { return "", err } //将hex格式数据转换为byte切片 valueBytes := []byte(value) var encryptedData = make([]byte, len(valueBytes)/2) for i := 0; i < len(encryptedData); i++ { b, err := strconv.ParseInt(value[i*2:i*2+2], 16, 10) if err != nil { return "", err } encryptedData[i] = byte(b) } result := make([]byte, len(encryptedData)) if iv == "" { blocksize := block.BlockSize() temp := result for len(encryptedData) > 0 { block.Decrypt(temp, encryptedData[:blocksize]) encryptedData = encryptedData[blocksize:] temp = temp[blocksize:] } } else { //向量切片 ivBytes := make([]byte, des.BlockSize) copy(ivBytes, []byte(iv)) //解密 blockMode := cipher.NewCBCDecrypter(block, ivBytes) blockMode.CryptBlocks(result, encryptedData) } //取消填充 unpadding := int(result[len(result)-1]) result = result[:(len(result) - unpadding)] return string(result), nil }
调用测试:
package main import ( "fmt" "testing" ) func TestDes(t *testing.T) { text := "上山打老虎" key := "123456" // 秘钥 iv := "abcdefg" // 初始向量 encryptText1, _ := DesEncrypt(text, key, iv) fmt.Printf("【%s】经过【DES-CBC】加密后:%s\n", text, encryptText1) decryptText1, _ := DesDecrypt(encryptText1, key, iv) fmt.Printf("【%s】经过【DES-CBC】解密后:%s\n", encryptText1, decryptText1) encryptText2, _ := DesEncrypt(text, key, "") fmt.Printf("【%s】经过【DES-ECB】加密后:%s\n", text, encryptText2) decryptText2, _ := DesDecrypt(encryptText2, key, "") fmt.Printf("【%s】经过【DES-ECB】解密后:%s\n", encryptText2, decryptText2) }
执行结果:
Python
python一般需要安装pyDes包来实现DES加密解密,可以使用pip来安装:
pip install pyDes
默认也是采用ECB模式,所以要多注意,python相对简单,封装测试就放一起了:
# 需要安装pyDes包:pip install pyDes from pyDes import des, PAD_PKCS5, CBC, ECB BLOCK_SIZE = 8 def init_cipher(secret_key, iv_key): secret_bytes = secret_key.encode(encoding="utf-8") key_bytes = [] if len(secret_bytes) >= BLOCK_SIZE: key_bytes = secret_bytes[:BLOCK_SIZE] else: key_bytes.extend(secret_bytes) key_bytes.extend([0 for x in range(0, BLOCK_SIZE - len(secret_bytes))]) if iv_key is None or len(iv_key) == 0: cipher = des(key_bytes, ECB, None, padmode=PAD_PKCS5) return cipher else: iv_bytes = iv_key.encode(encoding="utf-8") iv_key_bytes = [] if len(iv_bytes) >= BLOCK_SIZE: iv_key_bytes = iv_bytes[:BLOCK_SIZE] else: iv_key_bytes.extend(iv_bytes) iv_key_bytes.extend([0 for x in range(0, BLOCK_SIZE - len(iv_bytes))]) cipher = des(key_bytes, CBC, iv_key_bytes, padmode=PAD_PKCS5) return cipher def des_encrypt(value, secret_key, iv_key): cipher = init_cipher(secret_key, iv_key) buffer = value.encode(encoding="utf-8") buffer = cipher.encrypt(buffer) return buffer.hex() # 使用hex格式输出 def des_decrypt(value, secret_key, iv_key): cipher = init_cipher(secret_key, iv_key) buffer = bytes.fromhex(value) # 读取hex格式数据 buffer = cipher.decrypt(buffer) return buffer.decode("utf-8") text = "上山打老虎" key = "123456" # 秘钥 iv = "abcdefg" # 初始向量 encryptText1 = des_encrypt(text, key, iv) print("【", text, "】经过【DES-CBC】加密后:", encryptText1) decryptText1 = des_decrypt(encryptText1, key, iv) print("【", encryptText1, "】经过【DES-CBC】解密后:", decryptText1) encryptText2 = des_encrypt(text, key, None) print("【", text, "】经过【DES-ECB】加密后:", encryptText2) decryptText2 = des_decrypt(encryptText2, key, None) print("【", encryptText2, "】经过【DES-ECB】解密后:", decryptText2)
执行结果:
一个专注于.NetCore的技术小白
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
2019-06-04 nodejs安装教程