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;
}
}
}
DesUtil
然后我们可以调用这个封装好的类去进行加密解密:
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
}
}
DesHelper
然后测试加密解密:
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
}
desutil.go
调用测试:
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)
执行结果:
DES对称加密算法实现:Java,C#,Golang,Python的更多相关文章
- JAVA加密解密DES对称加密算法
下面用DES对称加密算法(设定一个密钥,然后对所有的数据进行加密)来简单举个例子. 首先,生成一个密钥KEY. 我把它保存到key.txt中.这个文件就象是一把钥匙.谁拥有它,谁就能解开我们的类文件. ...
- DES对称加密算法简析
1 对称加密算法 在了解DES算法前,先加单介绍一下对称加密算法,因为DES属于对称加密算法的一种. 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密 ...
- DES对称加密算法详解和c++代码实现(带样例和详细的中间数据)
特点: 1.DES是对称性加密算法,即加密和解密是对称的,用的是同一个密钥 2.DES只处理二进制数据,所以需要将明文转换成为2进制数据 3.DES每次处理64位的数据,所以应该将明文切割成64位的分 ...
- pyDes 实现 Python 版的 DES 对称加密/解密--转
https://my.oschina.net/leejun2005/blog/586451 手头有个 Java 版的 DES 加密/解密程序,最近想着将其 Python 重构下,方便后续脚本解析,捣鼓 ...
- 对称加密算法-DES以及DESede算法
一.简述 对称加密算法就是能将数据加解密.加密的时候用密钥对数据进行加密,解密的时候使用同样的密钥对数据进行解密. DES是美国国家标准研究所提出的算法.因为加解密的数据安全性和密钥长度成正比.des ...
- AES对称加密算法实现:Java,C#,Golang,Python
高级加密标准(Advanced Encryption Standard,简写AES),是一种用来替代DES的对称加密算法,相比DES,AES安全性更高,加密速度更快,因此被广泛使用. 理论上看,AES ...
- 常用加密算法的Java实现总结(二) ——对称加密算法DES、3DES和AES
1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...
- 使用java库中的对称加密算法
对称加密算法是说加密方和解密方使用相同的密钥.常见的对称加密算法包括4个,DES,DESede(3DES),AES,PBE. 本文讨论的内容是加密算法,不是Message Digest,不是编码.下面 ...
- [转] 对称加密算法DES、3DES
转自:http://www.blogjava.net/amigoxie/archive/2014/07/06/415503.html 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法, ...
随机推荐
- proguard 混淆工具的用法 (适用于初学者参考)
一. ProGuard简介 附:proGuard官网 因为Java代码是非常容易反编码的,况且Android开发的应用程序是用Java代码写的,为了很好的保护Java源代码,我们需要对编译好后的cla ...
- Spring Cloud声明式调用Feign负载均衡FeignClient详解
为了深入理解Feign,下面将从源码的角度来讲解Feign.首先来看看FeignClient注解@FeignClient的源码,代码如下: FeignClient注解被@Target(ElementT ...
- 【Linux】【Commands】基础概念及常用基础命令
命令的语法通用格式: ------------------------------------------------ #COMMAND OPTIONS ARGUMENTS 发起命令:请求内核将某个二 ...
- angular过滤器在html和js中的使用
在HTML中使用格式为:{{数据 | 过滤器名称:条件一:条件二--}}:过滤条件间使用:隔开 例如: 在代码中一般格式为: 变量 = $filter("过滤器名称")(被过滤数 ...
- 【C/C++】n皇后问题/全排列/递归/回溯/算法笔记4.3
按常规,先说一下我自己的理解. 递归中的return常用来作为递归终止的条件,但是对于返回数值的情况,要搞明白它是怎么返回的.递归的方式就是自己调用自己,而在有返回值的函数中,上一层的函数还没执行完就 ...
- 在Eclipse中编写jQuery代码时产生的错误(连载)
1.Error:启动Eclipse中的服务,显示错误,端口号被占用 解决方法: 方式一:修改对应的端口号(实际情况实际处理) 方式二:在进程中关闭Eclispe重新打开即可(截图说明) 2.Error ...
- 使用plantuml,业务交接就是这么简单
使用plantuml,业务交接就是这么简单 你好,我是轩脉刃. 最近交接了一个业务,原本还是有挺复杂的业务逻辑的,但发现交接过来的项目大有文章,在项目代码中有一个docs文件夹,里面躺着若干个 pum ...
- MySQL如何把varchar类型字段转换成int类型进行倒叙排序
SELECT * FROM sheet2 t1 WHERE t1.`金额`+'0' ORDER BY t1.`金额` DESC;
- CTF 自动拼图
忘记在哪个群里面看见有师傅说过这样一句加,百度搜索"CTF拼图脚本,有惊喜". 在做JUSTCTF的题时候,看到一道拼图题.就想着试一试. 先百度搜了,看到了fjh1997师傅的一 ...
- CF808A Lucky Year 题解
Content 年份中有不超过 \(1\) 个非 \(0\) 数字的年份是幸运年份.现给出当前年份 \(n\),求到下一个幸运年份还要等多久. 数据范围:\(1\leqslant n\leqslant ...