Go File Encryption Code Example (Online Runner)

Go file encryption examples for AES/DES with mode, padding, key size, and encoding controls matching the file tool.

Online calculator: use the site File encryption tool.

Calculation method

The file tool supports AES or DES with the same modes and padding options as the text tools. This helper reads raw file bytes, encrypts them, and returns ciphertext bytes (no headers or metadata added).

Implementation notes

  • Package: built-in crypto/aes, crypto/des, and crypto/cipher.
  • Implementation: padding applies only to ECB/CBC; stream modes ignore padding.
  • Notes: store algorithm, IV, and mode alongside ciphertext; reuse of IVs is unsafe.

File encryption example

go
package main

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/hex"
	"fmt"
	"os"
)

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 aesFileEncrypt(path string, keyHex string, ivHex string) (string, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return "", err
	}
	key, err := hex.DecodeString(keyHex)
	if err != nil {
		return "", err
	}
	iv, err := hex.DecodeString(ivHex)
	if err != nil {
		return "", err
	}
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}
	padded := pkcs7Pad(data, block.BlockSize())
	ciphertext := make([]byte, len(padded))
	cipher.NewCBCEncrypter(block, iv).CryptBlocks(ciphertext, padded)
	return hex.EncodeToString(ciphertext), nil
}

func main() {
	file, err := os.CreateTemp("", "file-enc-*.bin")
	if err != nil {
		panic(err)
	}
	defer os.Remove(file.Name())
	file.WriteString("hello")
	file.Close()

	keyHex := "00112233445566778899aabbccddeeff"
	ivHex := "0102030405060708090a0b0c0d0e0f10"
	value, err := aesFileEncrypt(file.Name(), keyHex, ivHex)
	if err != nil {
		panic(err)
	}
	fmt.Println(value)
}

Complete script (implementation + tests)

go
package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/des"
	"encoding/hex"
	"errors"
	"fmt"
	"os"
)

type Algorithm string

type Mode string

type Padding string

type KeyEncoding string

const (
	AlgAES Algorithm = "aes"
	AlgDES Algorithm = "des"
)

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"
)

func decodeValue(value string, encoding KeyEncoding) ([]byte, error) {
	if encoding == EncHex {
		return hex.DecodeString(value)
	}
	return []byte(value), nil
}

func normalizeKey(key []byte, keySize int) []byte {
	if len(key) >= keySize {
		return key[:keySize]
	}
	out := make([]byte, keySize)
	copy(out, key)
	return out
}

func normalizeIV(iv []byte, blockSize int) []byte {
	out := make([]byte, blockSize)
	copy(out, iv)
	return out
}

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 buildBlock(alg Algorithm, key []byte, keySize int) (cipher.Block, int, error) {
	switch alg {
	case AlgAES:
		key = normalizeKey(key, keySize)
		block, err := aes.NewCipher(key)
		return block, aes.BlockSize, err
	case AlgDES:
		key = normalizeKey(key, des.BlockSize)
		block, err := des.NewCipher(key)
		return block, des.BlockSize, err
	default:
		return nil, 0, errors.New("unsupported algorithm")
	}
}

func encryptBytes(data []byte, alg Algorithm, mode Mode, padding Padding, key []byte, iv []byte, keySize int) ([]byte, error) {
	block, blockSize, err := buildBlock(alg, key, keySize)
	if err != nil {
		return nil, err
	}
	if mode == ModeECB || mode == ModeCBC {
		if padding == PaddingPKCS7 {
			data = pkcs7Pad(data, blockSize)
		} else {
			data = zeroPad(data, blockSize)
		}
	}
	iv = normalizeIV(iv, blockSize)
	out := make([]byte, len(data))

	switch mode {
	case ModeECB:
		for i := 0; i < len(data); i += blockSize {
			block.Encrypt(out[i:], data[i:])
		}
	case ModeCBC:
		cipher.NewCBCEncrypter(block, iv).CryptBlocks(out, data)
	case ModeCFB:
		cipher.NewCFBEncrypter(block, iv).XORKeyStream(out, data)
	case ModeOFB:
		cipher.NewOFB(block, iv).XORKeyStream(out, data)
	case ModeCTR:
		cipher.NewCTR(block, iv).XORKeyStream(out, data)
	default:
		return nil, errors.New("unsupported mode")
	}

	return out, nil
}

func decryptBytes(data []byte, alg Algorithm, mode Mode, padding Padding, key []byte, iv []byte, keySize int) ([]byte, error) {
	block, blockSize, err := buildBlock(alg, key, keySize)
	if err != nil {
		return nil, err
	}
	iv = normalizeIV(iv, blockSize)
	out := make([]byte, len(data))

	switch mode {
	case ModeECB:
		for i := 0; i < len(data); i += blockSize {
			block.Decrypt(out[i:], data[i:])
		}
	case ModeCBC:
		cipher.NewCBCDecrypter(block, iv).CryptBlocks(out, data)
	case ModeCFB:
		cipher.NewCFBDecrypter(block, iv).XORKeyStream(out, data)
	case ModeOFB:
		cipher.NewOFB(block, iv).XORKeyStream(out, data)
	case ModeCTR:
		cipher.NewCTR(block, iv).XORKeyStream(out, data)
	default:
		return nil, errors.New("unsupported mode")
	}

	if mode == ModeECB || mode == ModeCBC {
		if padding == PaddingPKCS7 {
			return pkcs7Unpad(out, blockSize)
		}
		return zeroUnpad(out), nil
	}

	return out, nil
}

func main() {
	file, err := os.CreateTemp("", "file-enc-*.bin")
	if err != nil {
		panic(err)
	}
	defer os.Remove(file.Name())
	file.WriteString("hello")
	file.Close()

	data, err := os.ReadFile(file.Name())
	if err != nil {
		panic(err)
	}

	keyHex := "00112233445566778899aabbccddeeff"
	ivHex := "0102030405060708090a0b0c0d0e0f10"
	keyBytes, _ := decodeValue(keyHex, EncHex)
	ivBytes, _ := decodeValue(ivHex, EncHex)

	ciphertext, err := encryptBytes(data, AlgAES, ModeCBC, PaddingPKCS7, keyBytes, ivBytes, 16)
	if err != nil {
		panic(err)
	}
	fmt.Println("cipher(hex)=", hex.EncodeToString(ciphertext))

	plaintext, err := decryptBytes(ciphertext, AlgAES, ModeCBC, PaddingPKCS7, keyBytes, ivBytes, 16)
	if err != nil {
		panic(err)
	}
	fmt.Println("plain=", string(plaintext))
}