Skip to content

Instantly share code, notes, and snippets.

@alex-bezverkhniy
Created February 18, 2022 16:37
Show Gist options
  • Select an option

  • Save alex-bezverkhniy/d7e2b96cbb696490f9b2568e90e3bc6d to your computer and use it in GitHub Desktop.

Select an option

Save alex-bezverkhniy/d7e2b96cbb696490f9b2568e90e3bc6d to your computer and use it in GitHub Desktop.
Simple tool to encrypt/decrypt (+ encode/decode base64)
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
b64 "encoding/base64"
"errors"
"fmt"
"os"
)
const EncryptCmd = "encrypt"
const DecryptCmd = "decrypt"
const EncodeCmd = "encode"
const DecodeCmd = "decode"
const PackCmd = "pack"
const UnpackCmd = "unpack"
const KeyCmd = "key"
func main() {
if len(os.Args) >= 2 {
cmd := os.Args[1]
switch cmd {
case EncryptCmd:
{
key, destPath, data, err := parseArgs(os.Args)
if err != nil {
fmt.Println(err.Error())
PrintUsage()
os.Exit(-1)
}
encData, err := Encrypt([]byte(key), data)
check(err)
os.WriteFile(destPath, encData, 0644)
}
case DecryptCmd:
{
key, destPath, data, err := parseArgs(os.Args)
if err != nil {
fmt.Println(err.Error())
PrintUsage()
os.Exit(-1)
}
encData, err := Decrypt([]byte(key), data)
check(err)
os.WriteFile(destPath, encData, 0644)
}
case EncodeCmd:
{
if len(os.Args) < 2 {
PrintUsage()
os.Exit(-1)
}
srcFile := os.Args[2]
data, err := os.ReadFile(srcFile)
if err != nil {
fmt.Println(err.Error())
PrintUsage()
os.Exit(-1)
}
fmt.Println(Encode(data))
}
case DecodeCmd:
{
destPath, data, err := parseArgsDecode(os.Args)
if err != nil {
fmt.Println(err.Error())
PrintUsage()
os.Exit(-1)
}
encData, err := Decode(string(data))
check(err)
err = os.WriteFile(destPath, encData, 0644)
if err != nil {
fmt.Println(err.Error())
PrintUsage()
os.Exit(-1)
}
}
case PackCmd:
{
key, destPath, data, err := parseArgs(os.Args)
d, err := Pack([]byte(key), data)
if err != nil {
fmt.Println(err.Error())
PrintUsage()
os.Exit(-1)
}
os.WriteFile(destPath, d, 0644)
if err != nil {
fmt.Println(err.Error())
PrintUsage()
os.Exit(-1)
}
}
case UnpackCmd:
{
key, destPath, data, err := parseArgs(os.Args)
d, err := Unpack([]byte(key), data)
if err != nil {
fmt.Println(err.Error())
PrintUsage()
os.Exit(-1)
}
os.WriteFile(destPath, d, 0644)
if err != nil {
fmt.Println(err.Error())
PrintUsage()
os.Exit(-1)
}
}
case KeyCmd:
{
key, err := GenerateKey()
check(err)
fmt.Println(len(key))
}
default:
PrintUsage()
}
} else {
PrintUsage()
}
}
func Encrypt(key, data []byte) ([]byte, error) {
blockCipher, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(blockCipher)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err = rand.Read(nonce); err != nil {
return nil, err
}
ciphertext := gcm.Seal(nonce, nonce, data, nil)
return ciphertext, nil
}
func Decrypt(key, data []byte) ([]byte, error) {
blockCipher, err := aes.NewCipher(key)
if err != nil {
fmt.Println("key error")
return nil, err
}
gcm, err := cipher.NewGCM(blockCipher)
if err != nil {
fmt.Println("gcm error")
return nil, err
}
nonce, ciphertext := data[:gcm.NonceSize()], data[gcm.NonceSize():]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
fmt.Println("open error")
return nil, err
}
return plaintext, nil
}
func Encode(data []byte) string {
return b64.StdEncoding.EncodeToString(data)
}
func Decode(data string) ([]byte, error) {
return b64.StdEncoding.DecodeString(data)
}
func GenerateKey() ([]byte, error) {
key := make([]byte, 32)
_, err := rand.Read(key)
if err != nil {
return nil, err
}
return key, nil
}
func Pack(key, data []byte) ([]byte, error) {
d, err := Encrypt(key, data)
if err != nil {
return nil, err
}
b64Str := Encode(d)
return []byte(b64Str), nil
}
func Unpack(key, data []byte) ([]byte, error) {
d, err := Decode(string(data))
if err != nil {
return nil, err
}
return Decrypt(key, d)
}
func PrintUsage() {
fmt.Printf(`usage:
Encrypting/Decrypting:
ende-docs <command> <key> <sourcePath> <destPath>
where:
<command> - encrypt or decrypt
Base64 Encoding/Decoding:
ende-docs <command> <sourcePath> (<destPath> for decoding)
where:
<command> - encode or decode
Encryption+Base64 Pack/Upnack:
ende-docs <command> <key> <sourcePath> <destPath>
where:
<command> - pack or unpack
`)
}
func check(e error) {
if e != nil {
fmt.Printf("%s\n", e.Error())
os.Exit(-1)
}
}
func parseArgs(args []string) (string, string, []byte, error) {
key := os.Args[2]
if len(os.Args) < 5 {
return "", "", nil, errors.New("Not enough arguments")
}
srcPath := os.Args[3]
destPath := os.Args[4]
data, err := os.ReadFile(srcPath)
if err != nil {
return "", "", nil, err
}
return key, destPath, data, nil
}
func parseArgsDecode(args []string) (string, []byte, error) {
if len(os.Args) < 4 {
return "", nil, errors.New("Not enough arguments")
}
srcPath := os.Args[2]
destPath := os.Args[3]
data, err := os.ReadFile(srcPath)
if err != nil {
return "", nil, err
}
return destPath, data, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment