├── img.png ├── README.md ├── go.mod ├── go.sum ├── LICENSE ├── filecrypt └── filecrypt.go └── main.go /img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AkhilSharma90/go-file-encrypt/HEAD/img.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### Encryption 4 | 5 | ```bash 6 | # Encrypts a file 7 | $ go run . encrypt img.png 8 | ``` 9 | 10 | ### Decryption 11 | 12 | ```bash 13 | # Decrypts a file 14 | $ go run . decrypt img.png 15 | ``` 16 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/akhilsharma90/file-encrypt 2 | 3 | go 1.18 4 | 5 | require golang.org/x/crypto v0.14.0 6 | 7 | require ( 8 | golang.org/x/sys v0.13.0 // indirect 9 | golang.org/x/term v0.13.0 // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= 2 | golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= 3 | golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= 4 | golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 5 | golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= 6 | golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /filecrypt/filecrypt.go: -------------------------------------------------------------------------------- 1 | package filecrypt 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "crypto/rand" 8 | "crypto/sha1" 9 | "encoding/hex" 10 | "io" 11 | "io/ioutil" 12 | "os" 13 | 14 | "golang.org/x/crypto/pbkdf2" 15 | ) 16 | 17 | func Encrypt(source string, password []byte) { 18 | 19 | if _, err := os.Stat(source); os.IsNotExist(err) { 20 | panic(err.Error()) 21 | } 22 | 23 | plaintext, err := ioutil.ReadFile(source) 24 | 25 | if err != nil { 26 | panic(err.Error()) 27 | } 28 | 29 | key := password 30 | nonce := make([]byte, 12) 31 | 32 | // Randomizing the nonce 33 | if _, err := io.ReadFull(rand.Reader, nonce); err != nil { 34 | panic(err.Error()) 35 | } 36 | 37 | dk := pbkdf2.Key(key, nonce, 4096, 32, sha1.New) 38 | 39 | block, err := aes.NewCipher(dk) 40 | if err != nil { 41 | panic(err.Error()) 42 | } 43 | 44 | aesgcm, err := cipher.NewGCM(block) 45 | if err != nil { 46 | panic(err.Error()) 47 | } 48 | 49 | ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil) 50 | 51 | // Append the nonce to the end of file 52 | ciphertext = append(ciphertext, nonce...) 53 | 54 | f, err := os.Create(source) 55 | if err != nil { 56 | panic(err.Error()) 57 | } 58 | _, err = io.Copy(f, bytes.NewReader(ciphertext)) 59 | if err != nil { 60 | panic(err.Error()) 61 | } 62 | } 63 | 64 | func Decrypt(source string, password []byte) { 65 | 66 | if _, err := os.Stat(source); os.IsNotExist(err) { 67 | panic(err.Error()) 68 | } 69 | 70 | ciphertext, err := ioutil.ReadFile(source) 71 | 72 | if err != nil { 73 | panic(err.Error()) 74 | } 75 | 76 | key := password 77 | salt := ciphertext[len(ciphertext)-12:] 78 | str := hex.EncodeToString(salt) 79 | 80 | nonce, err := hex.DecodeString(str) 81 | 82 | dk := pbkdf2.Key(key, nonce, 4096, 32, sha1.New) 83 | 84 | block, err := aes.NewCipher(dk) 85 | if err != nil { 86 | panic(err.Error()) 87 | } 88 | 89 | aesgcm, err := cipher.NewGCM(block) 90 | if err != nil { 91 | panic(err.Error()) 92 | } 93 | 94 | plaintext, err := aesgcm.Open(nil, nonce, ciphertext[:len(ciphertext)-12], nil) 95 | if err != nil { 96 | panic(err.Error()) 97 | } 98 | 99 | f, err := os.Create(source) 100 | if err != nil { 101 | panic(err.Error()) 102 | } 103 | _, err = io.Copy(f, bytes.NewReader(plaintext)) 104 | if err != nil { 105 | panic(err.Error()) 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/akhilsharma90/file-encrypt/filecrypt" 9 | 10 | "golang.org/x/crypto/ssh/terminal" 11 | ) 12 | 13 | func main() { 14 | 15 | // If not enough args, return help text 16 | if len(os.Args) < 2 { 17 | printHelp() 18 | os.Exit(0) 19 | } 20 | 21 | function := os.Args[1] 22 | 23 | switch function { 24 | case "help": 25 | printHelp() 26 | case "encrypt": 27 | encryptHandle() 28 | case "decrypt": 29 | decryptHandle() 30 | default: 31 | fmt.Println("Run CryptoGo encrypt to encrypt a file, and CryptoGo decrypt to decrypt a file.") 32 | os.Exit(1) 33 | } 34 | 35 | } 36 | 37 | func printHelp() { 38 | fmt.Println("CryptoGo") 39 | fmt.Println("Simple file encrypter for your day-to-day needs.") 40 | fmt.Println("") 41 | fmt.Println("Usage:") 42 | fmt.Println("") 43 | fmt.Println("\tCryptoGo encrypt /path/to/your/file") 44 | fmt.Println("") 45 | fmt.Println("Commands:") 46 | fmt.Println("") 47 | fmt.Println("\t encrypt\tEncrypts a file given a password") 48 | fmt.Println("\t decrypt\tTries to decrypt a file using a password") 49 | fmt.Println("\t help\t\tDisplays help text") 50 | fmt.Println("") 51 | } 52 | 53 | func encryptHandle() { 54 | 55 | if len(os.Args) < 3 { 56 | println("Missing the path to the file. For more information run CryptoGo help") 57 | os.Exit(0) 58 | } 59 | 60 | file := os.Args[2] 61 | 62 | if !validateFile(file) { 63 | panic("File not found") 64 | } 65 | 66 | password := getPassword() 67 | 68 | fmt.Println("\nEncrypting...") 69 | filecrypt.Encrypt(file, password) 70 | fmt.Println("\nFile successfully protected") 71 | 72 | } 73 | 74 | func getPassword() []byte { 75 | fmt.Print("Enter password: ") 76 | password, _ := terminal.ReadPassword(0) 77 | fmt.Print("\nConfirm password: ") 78 | password2, _ := terminal.ReadPassword(0) 79 | if !validatePassword(password, password2) { 80 | fmt.Print("\nPasswords do not match. Please try again.\n") 81 | return getPassword() 82 | } 83 | return password 84 | } 85 | 86 | func decryptHandle() { 87 | 88 | if len(os.Args) < 3 { 89 | println("Missing the path to the file. For more information run CryptoGo help") 90 | os.Exit(0) 91 | } 92 | 93 | file := os.Args[2] 94 | 95 | if !validateFile(file) { 96 | panic("File not found") 97 | } 98 | 99 | fmt.Print("Enter password: ") 100 | password, _ := terminal.ReadPassword(0) 101 | 102 | fmt.Println("\nDecrypting...") 103 | filecrypt.Decrypt(file, password) 104 | fmt.Println("\nFile successfully decrypted.") 105 | 106 | } 107 | 108 | func validatePassword(password1 []byte, password2 []byte) bool { 109 | if !bytes.Equal(password1, password2) { 110 | return false 111 | } 112 | 113 | return true 114 | } 115 | 116 | func validateFile(file string) bool { 117 | if _, err := os.Stat(file); os.IsNotExist(err) { 118 | return false 119 | } 120 | 121 | return true 122 | } 123 | --------------------------------------------------------------------------------