Golang中应用DES加解密
1 DES算法简介
DES算法是由IBM公司在20世纪70年代发展起来的,于1976年11月被美国政府采用,随后被美国国家标准局和美国国家标准协会承认,同时也成为全球范围内事实上的工业标准。 DES是一种对称加密算法,使用的密钥只有一个,发信方和收信方预先知道密钥,使用同一个密钥进行加密和解密。它也是一种可逆加密算法,由加密结果和密钥可以解密出原始数据。
实际应用中,DES是根据其加密算法所定义的明文分组的大小(64bits),将数据割成若干64bits的加密区块,再以加密区块为单位,分别进行加密处理。根据数据加密时每个加密区块间的关联方式,可以分为4种加密模式,包括ECB,CBC,CFB及OFB。
具体算法原理、安全性以及工作模式请参考论文1。
2 Golang中应用DES加解密(ECB和CBC模式)
需引用包 <crypto/des>
<crypto/cipher>
。
首先需要指出的是,由于ECB模式加密算法较简单,Golang中的cipher没有提供ECB模式的加密类。具体实现可参考下面代码。
工具代码<des.go>
import (
"bytes"
"crypto/des"
"encoding/base64"
"errors"
"fmt"
)
func DESECBEncrypt(data, key []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
bs := block.BlockSize()
data = PKCS5Padding(data, bs)
if len(data)%bs != 0 {
return nil, errors.New("Need a multiple of the blocksize")
}
out := make([]byte, len(data))
dst := out
for len(data) > 0 {
block.Encrypt(dst, data[:bs])
data = data[bs:]
dst = dst[bs:]
}
return out, nil
}
func DESECBDecrypt(data []byte, key []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
bs := block.BlockSize()
if len(data)%bs != 0 {
return nil, errors.New("crypto/cipher: input not full blocks")
}
out := make([]byte, len(data))
dst := out
for len(data) > 0 {
block.Decrypt(dst, data[:bs])
data = data[bs:]
dst = dst[bs:]
}
out = PKCS5UnPadding(out)
return out, nil
}
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
func encodeBase64(b []byte) string {
return base64.StdEncoding.EncodeToString(b)
}
func decodeBase64(s string) []byte {
data, err := base64.StdEncoding.DecodeString(s)
if err != nil {
panic(err)
}
return data
}
测试代码 <des_test.go>
package crypto
import (
"testing"
"time"
)
func Test_desECB(t *testing.T) {
oridate := "hello world"
key := time.Now().Format("20060102")
encryptedbyte, _ := DesECBEncrypt([]byte(oridate), []byte(key))
encryptedstr := encodeBase64(encryptedbyte)
t.Logf("data=%s,key=%s,encrypted=%s \n", oridate, key, encryptedstr)
decryptedbyte, _ := DesECBDecrypt(decodeBase64(encryptedstr), []byte(key))
decryptedstr := string(decryptedbyte)
if decryptedstr == oridate {
t.Log("decrpted ok!")
} else {
t.Fail()
}
}
func Test_desCBC(t *testing.T) {
oridate := "hello world"
key := time.Now().Format("20060102")
encryptedbyte, _ := DesCBCEncrypt([]byte(oridate), []byte(key))
encryptedstr := encodeBase64(encryptedbyte)
t.Logf("data=%s,key=%s,encrypted=%s \n", oridate, key, encryptedstr)
decryptedbyte, _ := DesCBCDecrypt(decodeBase64(encryptedstr), []byte(key))
decryptedstr := string(decryptedbyte)
if decryptedstr == oridate {
t.Log("decrpted ok!")
} else {
t.Fail()
}
}
3 C#中应用DES加解密(ECB模式)
直接贴代码 <des.cs>
using System.Globalization;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.IO;
public static string Encrypt2(string sourceString, string key)
{
byte[] btKey = Encoding.Default.GetBytes(key);
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Key = btKey;
des.Mode = CipherMode.ECB;
using (MemoryStream ms = new MemoryStream())
{
byte[] inData = Encoding.Default.GetBytes(sourceString);
try
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(inData, 0, inData.Length);
cs.FlushFinalBlock();
}
return Convert.ToBase64String(ms.ToArray());
}
catch
{
throw;
}
}
}
public static string Decrypt2(string encryptedString, string key)
{
byte[] btKey = Encoding.Default.GetBytes(key);
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Key = btKey;
des.Mode = CipherMode.ECB;
using (MemoryStream ms = new MemoryStream())
{
byte[] inData = Convert.FromBase64String(encryptedString);
try
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(inData, 0, inData.Length);
cs.FlushFinalBlock();
}
return Encoding.Default.GetString(ms.ToArray());
}
catch
{
throw;
}
}
}
#4 总结 作者对安全领域中的加解密算法原理没有深入研究。本文重点从应用角度探索了一下DES加解密的Golang代码实现。
以上Golang和C#代码中实现的ECB模式加密,经过实际验证,结果是相等的,可以实现跨语言对接。
另有网文2介绍了Golang和Java代码的DES ECB模式加密结果互换。
参考文献:
- 褚慧丽. DES算法及其工作模式分析[J]. 商情, 2012(31):194-195. [return]
- http://blog.csdn.net/scybs/article/details/38279159 [return]