hns/main.go

169 lines
3.3 KiB
Go

package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/rand"
"fmt"
"io"
"io/ioutil"
"os"
"regexp"
"syscall"
"golang.org/x/crypto/ssh/terminal"
)
var debug bool = false
var FileName string
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
match, _ := regexp.Match(`.*\.hdn$`,[]byte(FileName))
if match {
return "s"
}
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() {
FileName = readFn()
fn := FileName
fmt.Println(fn)
mode := getMode()
switch mode {
case "h":
pw := checkPass()
key := keyMkr(pw)
data := file2data(fn)
secret := encrypt(data,key)
secretfn := fn + ".hdn"
clearfn := fn + ".origin"
err := os.Rename(fn,clearfn)
checkErr(err)
data2file(secretfn,secret)
case "s":
fmt.Print("password: ")
pw := readPass()
fmt.Print("\n")
key := keyMkr(pw)
secret := file2data(fn)
datafn := fn + ".clr"
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)))
*/
}