| @ -0,0 +1,28 @@ | |||||
| package Encryption | |||||
| import ( | |||||
| "crypto/aes" | |||||
| "crypto/cipher" | |||||
| "crypto/hmac" | |||||
| "crypto/sha256" | |||||
| "hash" | |||||
| ) | |||||
| func CreateHash(key string) []byte { | |||||
| var h hash.Hash | |||||
| h = hmac.New(sha256.New, []byte(key)) | |||||
| h.Write([]byte(key)) | |||||
| return h.Sum(nil) | |||||
| } | |||||
| func CreateKey(hashedKey []byte) (cipher.Block, error) { | |||||
| var ( | |||||
| block cipher.Block | |||||
| e error | |||||
| ) | |||||
| block, e = aes.NewCipher(hashedKey) | |||||
| if e != nil { | |||||
| return nil, e | |||||
| } | |||||
| return block, nil | |||||
| } | |||||
| @ -0,0 +1,101 @@ | |||||
| package Encryption | |||||
| import ( | |||||
| "bytes" | |||||
| "crypto/aes" | |||||
| "crypto/cipher" | |||||
| "errors" | |||||
| "io" | |||||
| "io/ioutil" | |||||
| "os" | |||||
| ) | |||||
| func DecryptData(password string, ciphertext []byte) ([]byte, error) { | |||||
| var ( | |||||
| hashedKey []byte | |||||
| iv []byte | |||||
| encKey []byte | |||||
| block cipher.Block | |||||
| stream cipher.Stream | |||||
| e error | |||||
| ) | |||||
| hashedKey = CreateHash(password) | |||||
| if len(ciphertext) == 0 { | |||||
| return []byte{}, errors.New("Invalid length") | |||||
| } | |||||
| iv = ciphertext[:aes.BlockSize] | |||||
| encKey = ciphertext[:32+aes.BlockSize][aes.BlockSize:] | |||||
| ciphertext = ciphertext[aes.BlockSize+32:] | |||||
| block, e = CreateKey(hashedKey) | |||||
| if e != nil { | |||||
| return []byte{}, e | |||||
| } | |||||
| stream = cipher.NewCFBDecrypter(block, iv) | |||||
| stream.XORKeyStream(encKey, encKey) | |||||
| for i := range encKey { | |||||
| if encKey[i] != hashedKey[i] { | |||||
| return []byte{}, errors.New("Incorrect Password") | |||||
| } | |||||
| } | |||||
| stream.XORKeyStream(ciphertext, ciphertext) | |||||
| return ciphertext, nil | |||||
| } | |||||
| func DecryptFile(password string, FilePath string) error { | |||||
| var ( | |||||
| OldFilePath string | |||||
| ciphertext []byte | |||||
| plaintext []byte | |||||
| plaintextFile *os.File | |||||
| e error | |||||
| ) | |||||
| OldFilePath = FilePath[:(len(FilePath) - 4)] | |||||
| ciphertext, e = ioutil.ReadFile(FilePath) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| if len(ciphertext) < aes.BlockSize { | |||||
| return errors.New("ciphertext too short") | |||||
| } | |||||
| plaintext, e = DecryptData(password, ciphertext) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| plaintextFile, e = os.Create(OldFilePath) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| _, e = io.Copy(plaintextFile, bytes.NewReader(plaintext)) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| os.Remove(FilePath) | |||||
| return nil | |||||
| } | |||||
| func DecryptAndReadFile(password string, FilePath string) (string, error) { | |||||
| var ( | |||||
| ciphertext []byte | |||||
| plaintext []byte | |||||
| e error | |||||
| ) | |||||
| ciphertext, e = ioutil.ReadFile(FilePath) | |||||
| if e != nil { | |||||
| return "", e | |||||
| } | |||||
| if len(ciphertext) < aes.BlockSize { | |||||
| return "", errors.New("ciphertext too short") | |||||
| } | |||||
| plaintext, e = DecryptData(password, ciphertext) | |||||
| if e != nil { | |||||
| return "", e | |||||
| } | |||||
| return string(plaintext), nil | |||||
| } | |||||
| @ -0,0 +1,95 @@ | |||||
| package Encryption | |||||
| import ( | |||||
| "fmt" | |||||
| "bytes" | |||||
| "crypto/aes" | |||||
| "errors" | |||||
| "os" | |||||
| "os/exec" | |||||
| "io/ioutil" | |||||
| "io" | |||||
| ) | |||||
| func EditEncryptedFile(password string, FilePath string) (error) { | |||||
| var ( | |||||
| editor string | |||||
| tmpFilePath string | |||||
| ciphertext []byte | |||||
| plaintext []byte | |||||
| tmpFile *os.File | |||||
| encryptedFile *os.File | |||||
| cmd *exec.Cmd | |||||
| e error | |||||
| ) | |||||
| editor = os.Getenv("EDITOR") | |||||
| if editor == "" { | |||||
| return errors.New("EDITOR variable cannot be blank") | |||||
| } | |||||
| tmpFilePath = "/tmp/klsadjhflk" | |||||
| ciphertext, e = ioutil.ReadFile(FilePath) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| if len(ciphertext) < aes.BlockSize { | |||||
| return errors.New("ciphertext too short") | |||||
| } | |||||
| plaintext, e = DecryptData(password, ciphertext) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| tmpFile, e = os.Create(tmpFilePath) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| _, e = io.Copy(tmpFile, bytes.NewReader(plaintext)) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| e = tmpFile.Close() | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| cmd = exec.Command(editor, tmpFilePath) | |||||
| cmd.Stdout = os.Stdout | |||||
| cmd.Stdin = os.Stdin | |||||
| cmd.Stderr = os.Stderr | |||||
| e = cmd.Run() | |||||
| if (e != nil) { | |||||
| return e | |||||
| } | |||||
| plaintext, e = ioutil.ReadFile(tmpFilePath) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| ciphertext, e = EncryptData(password, plaintext) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| // open output file | |||||
| encryptedFile, e = os.OpenFile(FilePath, os.O_RDWR, 0666) | |||||
| if e != nil { | |||||
| fmt.Println(1) | |||||
| return e | |||||
| } | |||||
| defer func() { | |||||
| encryptedFile.Close() | |||||
| SecureDelete(tmpFilePath) | |||||
| }() | |||||
| _, e = io.Copy(encryptedFile, bytes.NewReader(ciphertext)) | |||||
| if e != nil { | |||||
| fmt.Println(2) | |||||
| return e | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @ -0,0 +1,71 @@ | |||||
| package Encryption | |||||
| import ( | |||||
| "bytes" | |||||
| "crypto/aes" | |||||
| "crypto/cipher" | |||||
| "crypto/rand" | |||||
| "io" | |||||
| "io/ioutil" | |||||
| "os" | |||||
| ) | |||||
| func EncryptData(password string, data []byte) ([]byte, error) { | |||||
| var ( | |||||
| hashedKey []byte | |||||
| ciphertext []byte | |||||
| iv []byte | |||||
| block cipher.Block | |||||
| stream cipher.Stream | |||||
| e error | |||||
| ) | |||||
| hashedKey = CreateHash(password) | |||||
| ciphertext = make([]byte, aes.BlockSize+len(hashedKey)+len(data)) | |||||
| iv = ciphertext[:aes.BlockSize] | |||||
| if _, e = io.ReadFull(rand.Reader, iv); e != nil { | |||||
| return []byte{}, e | |||||
| } | |||||
| block, e = CreateKey(hashedKey) | |||||
| if e != nil { | |||||
| return []byte{}, e | |||||
| } | |||||
| stream = cipher.NewCFBEncrypter(block, iv) | |||||
| stream.XORKeyStream(ciphertext[aes.BlockSize:], []byte(hashedKey)) | |||||
| stream.XORKeyStream(ciphertext[aes.BlockSize+len([]byte(hashedKey)):], data) | |||||
| return ciphertext, nil | |||||
| } | |||||
| func EncryptFile(password string, FilePath string) error { | |||||
| var ( | |||||
| plaintext []byte | |||||
| ciphertext []byte | |||||
| encryptedFile *os.File | |||||
| e error | |||||
| ) | |||||
| plaintext, e = ioutil.ReadFile(FilePath) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| ciphertext, e = EncryptData(password, plaintext) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| // open output file | |||||
| encryptedFile, e = os.Create(FilePath + ".enc") | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| defer func() { | |||||
| encryptedFile.Close() | |||||
| SecureDelete(FilePath) | |||||
| }() | |||||
| _, e = io.Copy(encryptedFile, bytes.NewReader(ciphertext)) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @ -0,0 +1,34 @@ | |||||
| package Encryption | |||||
| import ( | |||||
| "os" | |||||
| ) | |||||
| func SecureDelete(FilePath string) error { | |||||
| var ( | |||||
| file *os.File | |||||
| fileInfo os.FileInfo | |||||
| size int64 | |||||
| zeroBytes []byte | |||||
| e error | |||||
| ) | |||||
| file, _ = os.OpenFile(FilePath, os.O_RDWR, 0666) | |||||
| defer file.Close() | |||||
| // Find out how large is the target file | |||||
| fileInfo, e = file.Stat() | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| size = fileInfo.Size() | |||||
| // Create byte array filled with zero's | |||||
| zeroBytes = make([]byte, size) | |||||
| _, e = file.Write([]byte(zeroBytes)) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| e = os.Remove(FilePath) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @ -0,0 +1,107 @@ | |||||
| package main | |||||
| import ( | |||||
| "flag" | |||||
| "fmt" | |||||
| "os" | |||||
| "syscall" | |||||
| "golang.org/x/crypto/ssh/terminal" | |||||
| "gitlab.com/tovijaeschke/FileEncryption/Encryption" | |||||
| ) | |||||
| func getPassword() (string, error) { | |||||
| var ( | |||||
| bytePassword []byte | |||||
| e error | |||||
| ) | |||||
| fmt.Print("Enter Password: ") | |||||
| bytePassword, e = terminal.ReadPassword(int(syscall.Stdin)) | |||||
| if e != nil { | |||||
| return "", e | |||||
| } | |||||
| return string(bytePassword), nil | |||||
| } | |||||
| func main() { | |||||
| var ( | |||||
| files []string | |||||
| decrypt *bool | |||||
| read *bool | |||||
| edit *bool | |||||
| plaintext string | |||||
| password string | |||||
| e error | |||||
| ) | |||||
| flag.Usage = func() { | |||||
| fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [OPTIONS]... [FILES]...\n", os.Args[0]) | |||||
| fmt.Println("\t-d: Decrypt files") | |||||
| fmt.Println("\t-r: Decrypt and read files to stdout") | |||||
| fmt.Println("\t-e: Edit encrypted file") | |||||
| } | |||||
| decrypt = flag.Bool("d", false, "Decrypt the file(s)") | |||||
| read = flag.Bool("r", false, "Read file to stdout") | |||||
| edit = flag.Bool("e", false, "Edit encrypted file") | |||||
| flag.Parse() | |||||
| files = flag.Args() | |||||
| if len(files) == 0 { | |||||
| flag.Usage() | |||||
| fmt.Println("Files cannot be null") | |||||
| os.Exit(1) | |||||
| } | |||||
| password, e = getPassword() | |||||
| if e != nil { | |||||
| fmt.Println(e.Error()) | |||||
| os.Exit(1) | |||||
| } | |||||
| if *decrypt { | |||||
| for _, file := range files { | |||||
| e = Encryption.DecryptFile(password, file) | |||||
| if e != nil { | |||||
| fmt.Println(e.Error()) | |||||
| os.Exit(1) | |||||
| } | |||||
| } | |||||
| os.Exit(0) | |||||
| } | |||||
| if *read { | |||||
| for _, file := range files { | |||||
| plaintext, e = Encryption.DecryptAndReadFile(password, file) | |||||
| if e != nil { | |||||
| fmt.Println(e.Error()) | |||||
| os.Exit(1) | |||||
| } | |||||
| fmt.Println(file) | |||||
| fmt.Println(plaintext) | |||||
| } | |||||
| os.Exit(0) | |||||
| } | |||||
| if *edit { | |||||
| for _, file := range files { | |||||
| e = Encryption.EditEncryptedFile(password, file) | |||||
| if e != nil { | |||||
| fmt.Println(e.Error()) | |||||
| os.Exit(1) | |||||
| } | |||||
| } | |||||
| os.Exit(0) | |||||
| } | |||||
| for _, file := range files { | |||||
| e = Encryption.EncryptFile(password, file) | |||||
| if e != nil { | |||||
| fmt.Println(e.Error()) | |||||
| os.Exit(1) | |||||
| } | |||||
| } | |||||
| } | |||||