This is a creation in Article, where the information may have evolved or changed.
Brief introduction
Because the project needs to use the 3DES algorithm plus decryption information in the ECB mode, Golang only provides CBC mode by default and only implements the ECB mode on its own.
Refer to HTTPS://SEGMENTFAULT.COM/A/11., the article explains the DES in the ECB mode and implements a partial des algorithm example. The algorithm is complete, providing 3DES algorithm implementation.
Basis
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.
Fill
Fill the way with pkcs5padding, the code is copied as follows:
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)]
}
The filling process is to make the clear text length into 8 integer times, a few will fill several corresponding numbers. If the number of 4 bytes is less than 8, then fill 4 0x04, if the clear text is exactly a multiple of 8, it is necessary to populate 8 0x08.
After decryption, to delete the populated data, take the last byte value, delete the last few bytes by the value. (The design is very clever)
Code
The complete code:
package tripledesecb
import (
"bytes"
"crypto/des"
"errors"
"fmt"
"golang.org/x/crypto/pbkdf2"
)
//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
}
The above code, a little change can open the ECB mode des algorithm, I do not use, I did not release.
Just started with Golang, is also the first time in Segmentfault on the posting, Pat!