Go DES Encryption Code Example (Online Runner)
Go DES examples with mode, padding, key size, and encoding controls to mirror the DES tool.
Online calculator: use the site DES tool.
Calculation method
The DES tool supports ECB/CBC/CFB/OFB/CTR modes, PKCS7 or zero padding (for block modes), and hex/base64 encodings.
Implementation notes
- Package: built-in
crypto/desandcrypto/cipher. - Implementation: keys and IVs are normalized to 8 bytes to match the tool behavior.
- Notes: DES is legacy and not considered secure; prefer AES or ChaCha20.
Text encryption example
go
package main
import (
"crypto/cipher"
"crypto/des"
"encoding/hex"
"fmt"
)
func desCBCEncryptHex(plaintext string, keyHex string, ivHex string) (string, error) {
key, err := hex.DecodeString(keyHex)
if err != nil {
return "", err
}
iv, err := hex.DecodeString(ivHex)
if err != nil {
return "", err
}
block, err := des.NewCipher(key)
if err != nil {
return "", err
}
padded := pkcs7Pad([]byte(plaintext), block.BlockSize())
out := make([]byte, len(padded))
cipher.NewCBCEncrypter(block, iv).CryptBlocks(out, padded)
return hex.EncodeToString(out), nil
}
func pkcs7Pad(data []byte, blockSize int) []byte {
padLen := blockSize - (len(data) % blockSize)
out := make([]byte, len(data)+padLen)
copy(out, data)
for i := len(data); i < len(out); i++ {
out[i] = byte(padLen)
}
return out
}
func main() {
keyHex := "0011223344556677"
ivHex := "0102030405060708"
value, err := desCBCEncryptHex("hello", keyHex, ivHex)
if err != nil {
panic(err)
}
fmt.Println(value)
}Complete script (implementation + tests)
go
package main
import (
"crypto/cipher"
"crypto/des"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
)
type Mode string
type Padding string
type KeyEncoding string
type CipherEncoding string
const (
ModeECB Mode = "ECB"
ModeCBC Mode = "CBC"
ModeCFB Mode = "CFB"
ModeOFB Mode = "OFB"
ModeCTR Mode = "CTR"
)
const (
PaddingPKCS7 Padding = "PKCS7"
PaddingZero Padding = "Zero"
)
const (
EncUTF8 KeyEncoding = "utf8"
EncHex KeyEncoding = "hex"
)
const (
CipherHex CipherEncoding = "hex"
CipherBase64 CipherEncoding = "base64"
)
func normalizeKey(key []byte) []byte {
if len(key) >= des.BlockSize {
return key[:des.BlockSize]
}
out := make([]byte, des.BlockSize)
copy(out, key)
return out
}
func normalizeIV(iv []byte, blockSize int) []byte {
out := make([]byte, blockSize)
copy(out, iv)
return out
}
func decodeValue(value string, encoding KeyEncoding) ([]byte, error) {
if encoding == EncHex {
return hex.DecodeString(value)
}
return []byte(value), nil
}
func encodeCiphertext(data []byte, encoding CipherEncoding) string {
if encoding == CipherHex {
return hex.EncodeToString(data)
}
return base64.StdEncoding.EncodeToString(data)
}
func decodeCiphertext(value string, encoding CipherEncoding) ([]byte, error) {
if encoding == CipherHex {
return hex.DecodeString(value)
}
return base64.StdEncoding.DecodeString(value)
}
func pkcs7Pad(data []byte, blockSize int) []byte {
padLen := blockSize - (len(data) % blockSize)
out := make([]byte, len(data)+padLen)
copy(out, data)
for i := len(data); i < len(out); i++ {
out[i] = byte(padLen)
}
return out
}
func pkcs7Unpad(data []byte, blockSize int) ([]byte, error) {
if len(data) == 0 || len(data)%blockSize != 0 {
return nil, errors.New("invalid PKCS7 padding")
}
padLen := int(data[len(data)-1])
if padLen == 0 || padLen > blockSize {
return nil, errors.New("invalid PKCS7 padding")
}
for i := 0; i < padLen; i++ {
if data[len(data)-1-i] != byte(padLen) {
return nil, errors.New("invalid PKCS7 padding")
}
}
return data[:len(data)-padLen], nil
}
func zeroPad(data []byte, blockSize int) []byte {
if len(data)%blockSize == 0 {
return data
}
padLen := blockSize - (len(data) % blockSize)
out := make([]byte, len(data)+padLen)
copy(out, data)
return out
}
func zeroUnpad(data []byte) []byte {
end := len(data)
for end > 0 && data[end-1] == 0 {
end--
}
return data[:end]
}
func encryptECB(block cipher.Block, data []byte) []byte {
out := make([]byte, len(data))
for i := 0; i < len(data); i += block.BlockSize() {
block.Encrypt(out[i:], data[i:])
}
return out
}
func decryptECB(block cipher.Block, data []byte) []byte {
out := make([]byte, len(data))
for i := 0; i < len(data); i += block.BlockSize() {
block.Decrypt(out[i:], data[i:])
}
return out
}
func desEncrypt(plaintext, key string, mode Mode, padding Padding, keyEncoding KeyEncoding, iv string, ivEncoding KeyEncoding, outEncoding CipherEncoding) (string, error) {
keyBytes, err := decodeValue(key, keyEncoding)
if err != nil {
return "", err
}
ivBytes, err := decodeValue(iv, ivEncoding)
if err != nil {
return "", err
}
keyBytes = normalizeKey(keyBytes)
block, err := des.NewCipher(keyBytes)
if err != nil {
return "", err
}
data := []byte(plaintext)
blockSize := block.BlockSize()
if mode == ModeECB || mode == ModeCBC {
if padding == PaddingPKCS7 {
data = pkcs7Pad(data, blockSize)
} else {
data = zeroPad(data, blockSize)
}
}
ivBytes = normalizeIV(ivBytes, blockSize)
var encrypted []byte
switch mode {
case ModeECB:
encrypted = encryptECB(block, data)
case ModeCBC:
encrypted = make([]byte, len(data))
cipher.NewCBCEncrypter(block, ivBytes).CryptBlocks(encrypted, data)
case ModeCFB:
encrypted = make([]byte, len(data))
cipher.NewCFBEncrypter(block, ivBytes).XORKeyStream(encrypted, data)
case ModeOFB:
encrypted = make([]byte, len(data))
cipher.NewOFB(block, ivBytes).XORKeyStream(encrypted, data)
case ModeCTR:
encrypted = make([]byte, len(data))
cipher.NewCTR(block, ivBytes).XORKeyStream(encrypted, data)
default:
return "", errors.New("unsupported mode")
}
return encodeCiphertext(encrypted, outEncoding), nil
}
func desDecrypt(ciphertext, key string, mode Mode, padding Padding, keyEncoding KeyEncoding, iv string, ivEncoding KeyEncoding, inEncoding CipherEncoding) (string, error) {
keyBytes, err := decodeValue(key, keyEncoding)
if err != nil {
return "", err
}
ivBytes, err := decodeValue(iv, ivEncoding)
if err != nil {
return "", err
}
keyBytes = normalizeKey(keyBytes)
block, err := des.NewCipher(keyBytes)
if err != nil {
return "", err
}
data, err := decodeCiphertext(ciphertext, inEncoding)
if err != nil {
return "", err
}
blockSize := block.BlockSize()
ivBytes = normalizeIV(ivBytes, blockSize)
var decrypted []byte
switch mode {
case ModeECB:
decrypted = decryptECB(block, data)
case ModeCBC:
decrypted = make([]byte, len(data))
cipher.NewCBCDecrypter(block, ivBytes).CryptBlocks(decrypted, data)
case ModeCFB:
decrypted = make([]byte, len(data))
cipher.NewCFBDecrypter(block, ivBytes).XORKeyStream(decrypted, data)
case ModeOFB:
decrypted = make([]byte, len(data))
cipher.NewOFB(block, ivBytes).XORKeyStream(decrypted, data)
case ModeCTR:
decrypted = make([]byte, len(data))
cipher.NewCTR(block, ivBytes).XORKeyStream(decrypted, data)
default:
return "", errors.New("unsupported mode")
}
if mode == ModeECB || mode == ModeCBC {
if padding == PaddingPKCS7 {
decrypted, err = pkcs7Unpad(decrypted, blockSize)
if err != nil {
return "", err
}
} else {
decrypted = zeroUnpad(decrypted)
}
}
return string(decrypted), nil
}
func main() {
keyHex := "0011223344556677"
ivHex := "0102030405060708"
ciphertext, err := desEncrypt("hello", keyHex, ModeCBC, PaddingPKCS7, EncHex, ivHex, EncHex, CipherHex)
if err != nil {
panic(err)
}
fmt.Println("cipher=", ciphertext)
plain, err := desDecrypt(ciphertext, keyHex, ModeCBC, PaddingPKCS7, EncHex, ivHex, EncHex, CipherHex)
if err != nil {
panic(err)
}
fmt.Println("plain=", plain)
}