160 lines
3.1 KiB
Go
160 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/md5"
|
|
"crypto/rand"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
// "strings"
|
|
"syscall"
|
|
"golang.org/x/crypto/ssh/terminal"
|
|
)
|
|
|
|
var debug bool = false
|
|
|
|
func checkErr(err error) {
|
|
if err != nil {
|
|
if debug {
|
|
panic(err.Error())
|
|
} else {
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
func keyMkr(passwd string) []byte {
|
|
key := md5.New()
|
|
key.Write([]byte(passwd))
|
|
return key.Sum(nil)
|
|
}
|
|
|
|
func encrypt(data []byte, key []byte) []byte {
|
|
block, err := aes.NewCipher(key)
|
|
checkErr(err)
|
|
gcm, err := cipher.NewGCM(block)
|
|
checkErr(err)
|
|
nonce := make([]byte, gcm.NonceSize())
|
|
_ , err= io.ReadFull(rand.Reader, nonce)
|
|
checkErr(err)
|
|
sealed := gcm.Seal(nonce, nonce, data, nil)
|
|
return sealed
|
|
}
|
|
|
|
func decrypt(sealed []byte, key []byte) []byte {
|
|
block, err := aes.NewCipher(key)
|
|
checkErr(err)
|
|
gcm, err := cipher.NewGCM(block)
|
|
nonceSize := gcm.NonceSize()
|
|
nonce, ctxt := sealed[:nonceSize], sealed[nonceSize:]
|
|
data, err := gcm.Open(nil, nonce, ctxt, nil)
|
|
checkErr(err)
|
|
return data
|
|
}
|
|
|
|
func file2data(filename string) []byte {
|
|
data, err := ioutil.ReadFile(filename)
|
|
checkErr(err)
|
|
return data
|
|
}
|
|
|
|
func data2file(filename string, data []byte) {
|
|
f, err := os.Create(filename)
|
|
checkErr(err)
|
|
defer f.Close()
|
|
f.Write(data)
|
|
}
|
|
|
|
func getMode() string {
|
|
var mode string
|
|
fmt.Print("mode: ")
|
|
fmt.Fscan(os.Stdin, &mode)
|
|
if mode == "q" {os.Exit(1)}
|
|
if mode != "h" && mode != "s" {
|
|
fmt.Println("not a mode")
|
|
fmt.Println("type 'h' for hide, 's' for show or 'q' to quit")
|
|
mode = getMode()
|
|
}
|
|
return mode
|
|
}
|
|
|
|
func readFn() string {
|
|
var filename string
|
|
arg := os.Args[1:]
|
|
if len(arg) != 1 {
|
|
fmt.Println("hns only takes file name as arg")
|
|
os.Exit(1)
|
|
}
|
|
fn := arg[0]
|
|
if _, err := os.Stat(fn); err == nil {
|
|
filename = fn
|
|
} else {
|
|
fmt.Println("No such file")
|
|
os.Exit(1)
|
|
}
|
|
return filename
|
|
}
|
|
|
|
func readPass() string {
|
|
pw, err := terminal.ReadPassword(int(syscall.Stdin))
|
|
checkErr(err)
|
|
return string(pw)
|
|
}
|
|
|
|
func checkPass() string {
|
|
var pw string
|
|
fmt.Print("password: ")
|
|
pw1 := readPass()
|
|
fmt.Print("\nagain: ")
|
|
pw2 := readPass()
|
|
fmt.Print("\n")
|
|
if pw1 == pw2 {
|
|
pw = pw1
|
|
} else {
|
|
fmt.Println("passwords don't match")
|
|
checkPass()
|
|
}
|
|
return pw
|
|
}
|
|
|
|
func main() {
|
|
fn := readFn()
|
|
fmt.Println(fn)
|
|
mode := getMode()
|
|
switch mode {
|
|
case "h":
|
|
pw := checkPass()
|
|
key := keyMkr(pw)
|
|
data := file2data(fn)
|
|
secret := encrypt(data,key)
|
|
secretfn := fn + ".hdn"
|
|
data2file(secretfn,secret)
|
|
case "s":
|
|
fmt.Print("password: ")
|
|
pw := readPass()
|
|
fmt.Print("\n")
|
|
key := keyMkr(pw)
|
|
secret := file2data(fn)
|
|
datafn := fn + "clear"
|
|
data := decrypt(secret, key)
|
|
data2file(datafn, data)
|
|
}
|
|
/*
|
|
var passwd string = "ThisAnnPassphrase"
|
|
fmt.Println(passwd)
|
|
key := keyMkr(passwd)
|
|
fmt.Println(string(key))
|
|
data := []byte("Thi is some data")
|
|
fmt.Println(string(data))
|
|
fmt.Println("encryption:")
|
|
dataSealed := encrypt(data,key)
|
|
fmt.Println(string(dataSealed))
|
|
fmt.Println("decryption:")
|
|
fmt.Println(string(decrypt(dataSealed,key)))
|
|
*/
|
|
}
|
|
|