如何在golang中使用32字节密钥实现TripleDES DESede/ECB/PKCS5Padding加密?

huangapple go评论82阅读模式
英文:

How to implement TripleDES DESede/ECB/PKCS5Padding encryption with 32-bytes key for golang?

问题

我真的需要在Golang中实现3DES/ECB/PKCS5Padding,我找到了一个实现的代码,链接是<https://gist.github.com/cuixin/10612934>,但是我的密钥长度是32字节,无法正常工作。我需要你们的帮助。非常感谢!

英文:

I really need to implement 3DES/ECB/PKCS5Padding for Golang, which I found for implementation like <https://gist.github.com/cuixin/10612934> but my secret key length is 32 bytes and is not working. I need your help, guys. Thank you very much

答案1

得分: 3

3DES
3DES算法使用24字节长度的密钥将密钥分为3个8字节的子密钥:K1、K2、K3。使用这3个密钥对明文进行加密和解密,具体如下:
E(K,d)和D(K,d)分别使用密钥K对数据d进行加密或解密,返回加密或解密后的数据。

3DES加密过程:
E(k3,D(k2,E(k1,d)))
意思是:首先将明文D使用K1进行加密,得到密文D1,然后将D1使用K2进行解密处理,得到密文D2;接着将D2使用K3进行加密处理,得到最终的密文。
3DES解密过程与加密过程相反:
D(k1,E(k2,D(k3,d)))
将密文d使用K3进行解密,得到密文D1,然后将D1使用K2进行加密,得到密文D2,最后将D2使用K1进行解密,得到最终的明文。

你可以尝试使用以下代码,它与你的代码兼容:


package main

import (
	"bytes"
	"crypto/des"
	"errors"
	"fmt"
	"log"
)

//ECB PKCS5Padding
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

//ECB PKCS5Unpadding
func PKCS5Unpadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

//Des encryption
func encrypt(origData, key []byte) ([]byte, error) {
	if len(origData) < 1 || len(key) < 1 {
		return nil, errors.New("wrong data or key")
	}
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	bs := block.BlockSize()
	if len(origData)%bs != 0 {
		return nil, errors.New("wrong padding")
	}
	out := make([]byte, len(origData))
	dst := out
	for len(origData) > 0 {
		block.Encrypt(dst, origData[:bs])
		origData = origData[bs:]
		dst = dst[bs:]
	}
	return out, nil
}

//Des Decrypt
func decrypt(crypted, key []byte) ([]byte, error) {
	if len(crypted) < 1 || len(key) < 1 {
		return nil, errors.New("wrong data or key")
	}
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	out := make([]byte, len(crypted))
	dst := out
	bs := block.BlockSize()
	if len(crypted)%bs != 0 {
		return nil, errors.New("wrong crypted size")
	}

	for len(crypted) > 0 {
		block.Decrypt(dst, crypted[:bs])
		crypted = crypted[bs:]
		dst = dst[bs:]
	}

	return out, nil
}

//[golang ECB 3DES Encrypt]
func TripleEcbDesEncrypt(origData, key []byte) ([]byte, error) {
	tkey := make([]byte, 24, 24)
	copy(tkey, key)
	k1 := tkey[:8]
	k2 := tkey[8:16]
	k3 := tkey[16:]

	block, err := des.NewCipher(k1)
	if err != nil {
		return nil, err
	}
	bs := block.BlockSize()
	origData = PKCS5Padding(origData, bs)

	buf1, err := encrypt(origData, k1)
	if err != nil {
		return nil, err
	}
	buf2, err := decrypt(buf1, k2)
	if err != nil {
		return nil, err
	}
	out, err := encrypt(buf2, k3)
	if err != nil {
		return nil, err
	}
	return out, nil
}

//[golang ECB 3DES Decrypt]
func TripleEcbDesDecrypt(crypted, key []byte) ([]byte, error) {
	tkey := make([]byte, 24, 24)
	copy(tkey, key)
	k1 := tkey[:8]
	k2 := tkey[8:16]
	k3 := tkey[16:]
	buf1, err := decrypt(crypted, k3)
	if err != nil {
		return nil, err
	}
	buf2, err := encrypt(buf1, k2)
	if err != nil {
		return nil, err
	}
	out, err := decrypt(buf2, k1)
	if err != nil {
		return nil, err
	}
	out = PKCS5Unpadding(out)
	return out, nil
}

func main() {

	key2 := []byte("5e8487e65e8487e65e8487e6")
	origtext2 := []byte("hello world123563332")

	erytext2, err := TripleEcbDesEncrypt(origtext2, key2)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%v\n", origtext2)
	destext2, err2 := TripleEcbDesDecrypt(erytext2, key2)
	if err2 != nil {
		log.Fatal(err2)
	}
	fmt.Println(string(destext2))
	fmt.Println(len(origtext2), len(string(destext2)))
	fmt.Println(string(origtext2) == string(destext2))

}
英文:

3DES
The 3DES algorithm uses a 24-byte length key to divide the key into 3 sub-keys of 8 bytes: K1, K2, K3. Use these 3 keys to encrypt and decrypt plaintext, as follows:
E (K,d), D (k,d), respectively, uses the key k to encrypt or decrypt data d, returning the encrypted or decrypted data.

3DES Encryption Process:
E(k3,D(k2,E(k1,d)))
The meaning is: will clear text D first uses K1 to encrypt, obtains the ciphertext D1, to D1 again uses K2 to do the decryption processing, obtains the ciphertext D2; then the D2 uses the K3 to do the encryption processing, obtains the final cipher text.
The 3DES decryption process is the opposite of encryption:
D(k1,E(k2,D(k3,d)))
The ciphertext d is decrypted with K3, the ciphertext is D1, the D1 is encrypted with K2, the cipher is D2, and the D2 is decrypted with K1, and the final plaintext is obtained.

You can try this code witch is compatiable with your gist code:


package main

import (
	&quot;bytes&quot;
	&quot;crypto/des&quot;
	&quot;errors&quot;
	&quot;fmt&quot;
	&quot;log&quot;
)

//ECB PKCS5Padding
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

//ECB PKCS5Unpadding
func PKCS5Unpadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

//Des encryption
func encrypt(origData, key []byte) ([]byte, error) {
	if len(origData) &lt; 1 || len(key) &lt; 1 {
		return nil, errors.New(&quot;wrong data or key&quot;)
	}
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	bs := block.BlockSize()
	if len(origData)%bs != 0 {
		return nil, errors.New(&quot;wrong padding&quot;)
	}
	out := make([]byte, len(origData))
	dst := out
	for len(origData) &gt; 0 {
		block.Encrypt(dst, origData[:bs])
		origData = origData[bs:]
		dst = dst[bs:]
	}
	return out, nil
}

//Des Decrypt
func decrypt(crypted, key []byte) ([]byte, error) {
	if len(crypted) &lt; 1 || len(key) &lt; 1 {
		return nil, errors.New(&quot;wrong data or key&quot;)
	}
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	out := make([]byte, len(crypted))
	dst := out
	bs := block.BlockSize()
	if len(crypted)%bs != 0 {
		return nil, errors.New(&quot;wrong crypted size&quot;)
	}

	for len(crypted) &gt; 0 {
		block.Decrypt(dst, crypted[:bs])
		crypted = crypted[bs:]
		dst = dst[bs:]
	}

	return out, nil
}

//[golang ECB 3DES Encrypt]
func TripleEcbDesEncrypt(origData, key []byte) ([]byte, error) {
	tkey := make([]byte, 24, 24)
	copy(tkey, key)
	k1 := tkey[:8]
	k2 := tkey[8:16]
	k3 := tkey[16:]

	block, err := des.NewCipher(k1)
	if err != nil {
		return nil, err
	}
	bs := block.BlockSize()
	origData = PKCS5Padding(origData, bs)

	buf1, err := encrypt(origData, k1)
	if err != nil {
		return nil, err
	}
	buf2, err := decrypt(buf1, k2)
	if err != nil {
		return nil, err
	}
	out, err := encrypt(buf2, k3)
	if err != nil {
		return nil, err
	}
	return out, nil
}

//[golang ECB 3DES Decrypt]
func TripleEcbDesDecrypt(crypted, key []byte) ([]byte, error) {
	tkey := make([]byte, 24, 24)
	copy(tkey, key)
	k1 := tkey[:8]
	k2 := tkey[8:16]
	k3 := tkey[16:]
	buf1, err := decrypt(crypted, k3)
	if err != nil {
		return nil, err
	}
	buf2, err := encrypt(buf1, k2)
	if err != nil {
		return nil, err
	}
	out, err := decrypt(buf2, k1)
	if err != nil {
		return nil, err
	}
	out = PKCS5Unpadding(out)
	return out, nil
}

func main() {

	key2 := []byte(&quot;5e8487e65e8487e65e8487e6&quot;)
	origtext2 := []byte(&quot;hello world123563332&quot;)

	erytext2, err := TripleEcbDesEncrypt(origtext2, key2)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf(&quot;%v\n&quot;, origtext2)
	destext2, err2 := TripleEcbDesDecrypt(erytext2, key2)
	if err2 != nil {
		log.Fatal(err2)
	}
	fmt.Println(string(destext2))
	fmt.Println(len(origtext2), len(string(destext2)))
	fmt.Println(string(origtext2) == string(destext2))

}

huangapple
  • 本文由 发表于 2022年3月12日 01:39:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/71442568.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定