Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
OlegChuev committed Nov 10, 2023
1 parent 71288ac commit 1a56ba0
Show file tree
Hide file tree
Showing 8 changed files with 341 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bin/*
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.PHONY: unix-build
unix-build: ## Build Unix binary
@$(MAKE) build GOOS=darwin GOARCH=arm64

.PHONY: win-build
win-build: ## Build Windows binary
@$(MAKE) build GOOS=windows GOARCH=386

build: ## Build binary
go build -o ./bin/encryptor

.PHONY: licenses
licenses: ## Generate LICENSE-DEPENDENCIES.md using golicense binary
@touch LICENSE-DEPENDENCIES.md
@golicense -plain ./bin/prevensys_alerts_center > LICENSE-DEPENDENCIES.md
104 changes: 104 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# File Encryption/Decryption tool

This is a small Go (Golang) application that provides functionality to encrypt and decrypt files using a specified key.

## Usage

To use the app, run the following command in your terminal:

```bash
go run main.go [flags]
```

### Flags

- **-encrypt**: Make encrypt (Specify either -encrypt or -decrypt, not both)
- **-decrypt**: Make decrypt (Specify either -encrypt or -decrypt, not both)
- **-src**: Source file (Provide the path to the source file)
- **-dest**: Destination file (Provide the path to the destination file)
- **-key**: Private key string

### Examples

#### Encrypting a File

```bash
go run main.go -encrypt -src input.txt -dest encrypted.txt -key 770A8A65DA156D24EE2A093277530142
```

or

```bash
./encryptor -encrypt -src input.txt -dest encrypted.txt -key 770A8A65DA156D24EE2A093277530142
```

#### Decrypting a File

```bash
go run main.go -decrypt -src encrypted.txt -dest decrypted.txt -key 770A8A65DA156D24EE2A093277530142
```

or

```bash
./encryptor -decrypt -src encrypted.txt -dest decrypted.txt -key 770A8A65DA156D24EE2A093277530142
```

## Important Notes

- Please provide both the source and destination file paths.
- **key** flag is mandatory and MUST be a 128-bit.

## Encryption/Decryption Logic

This small tool implements symmetric encryption and decryption using the Advanced Encryption Standard (AES) in Galois/Counter Mode (GCM). GCM is a mode of operation for symmetric key cryptographic block ciphers that provides authenticated encryption. Here's a breakdown of the encryption logic:

### Encryption Logic (Encrypt function):

1. **Key Generation:**
- The `newGcm` function generates a new Galois/Counter Mode (GCM) cipher using the provided secret key.
- It uses the Advanced Encryption Standard (AES) block cipher with a key derived from the provided secret key.

2. **Nonce Generation:**
- A nonce (number used once) is generated with a size equal to the nonce size of the GCM cipher. Nonce is a unique value that should only be used once for a given key.
- The nonce is created using a secure random number generator (`rand.Reader`).

3. **Encryption:**
- The `Seal` method of the GCM cipher is used to encrypt the data.
- The `Seal` method takes the nonce, additional authenticated data (nil in this case), and the plaintext data.
- It returns the ciphertext along with the nonce as the first part of the ciphertext.

4. **Base64 Encoding:**
- The resulting ciphertext, including the nonce, is encoded using Base64.URLEncoding.
- This encoded string is returned as the encrypted data.

### Decryption Logic (Decrypt function):

1. **Key Generation:**
- Similar to the encryption process, the `newGcm` function generates a new GCM cipher using the provided secret key.

2. **Base64 Decoding:**
- The input encrypted data (received as a Base64-encoded string) is decoded using Base64.URLEncoding.
- The decoded data is stored in the `buf` variable.

3. **Nonce Extraction:**
- The first part of the `buf` is extracted to obtain the nonce.

4. **Ciphertext Extraction:**
- The remaining part of the `buf` is considered as the ciphertext.

5. **Decryption:**
- The `Open` method of the GCM cipher is used to decrypt the data.
- It takes the nonce, additional authenticated data (nil in this case), and the ciphertext.
- It returns the original plaintext.

### Additional Notes:

- The `newGcm` function initializes the GCM cipher with the AES block cipher and the provided secret key.
- The nonce size is determined by the GCM cipher and is retrieved using `gcm.NonceSize()`.

This encryption scheme provides confidentiality and integrity for the data being encrypted. The use of a nonce ensures that the same plaintext encrypted with the same key will produce different ciphertexts, preventing certain types of attacks.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Empty file added bin/.keep
Empty file.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/OlegChuev/encryptor

go 1.20
80 changes: 80 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package main

import (
"github.com/OlegChuev/encryptor/pkg/encryption"
"github.com/OlegChuev/encryptor/pkg/filesystem"

"flag"
"fmt"
"io/ioutil"
)

func main() {
encryptFlag, decryptFlag, sourceFlag, destFlag, keyFlag, helpFlag := parseFlags()

if *helpFlag {
flag.PrintDefaults()
return
}

if *encryptFlag && *decryptFlag {
fmt.Println("Please specify either -encrypt or -decrypt, not both.")
return
}

if *sourceFlag == "" || *destFlag == "" {
fmt.Println("Please provide both source and destination file paths.")
return
}

data, err := ioutil.ReadFile(*sourceFlag)
if err != nil {
fmt.Println("Error reading source file:", err)
return
}

result, err := process(data, *encryptFlag, *keyFlag)
if err != nil {
var processName string
if *encryptFlag {
processName = "encryption"
} else {
processName = "decryption"
}

errMsg := fmt.Sprintf("Error during the %s process:", processName)
fmt.Println(errMsg, err)
return
}

err = filesystem.WriteToFile(*destFlag, result)
if err != nil {
fmt.Println("Error writing to destination file:", err)
return
}

fmt.Println("Operation completed successfully.")
}

func parseFlags() (*bool, *bool, *string, *string, *string, *bool) {
encryptFlag := flag.Bool("encrypt", false, "Encrypts data")
decryptFlag := flag.Bool("decrypt", false, "Decrypts data")
sourceFlag := flag.String("src", "", "Source file")
destFlag := flag.String("dest", "", "Destination file")
keyFlag := flag.String("key", "", "Private key string")
helpFlag := flag.Bool("help", false, "Print this help message")

flag.Parse()

return encryptFlag, decryptFlag, sourceFlag, destFlag, keyFlag, helpFlag
}

func process(data []byte, isEncryption bool, key string) (result []byte, err error) {
if isEncryption {
result, err = encryption.Encrypt(data, key)
} else {
result, err = encryption.Decrypt(data, key)
}

return
}
127 changes: 127 additions & 0 deletions pkg/encryption/encryption.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package encryption

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"io"
)

/*
Encrypt encrypts the given data using the specified secret key.
Parameters:
- data: Data to be encrypted.
- secretKey: Secret key used for encryption.
Returns:
- encoded: Encrypted data.
- err: Error, if any, encountered during the encryption process.
Example Usage:
encryptedData, err := Encrypt(originalData, "yourSecretKey")
if err != nil {
fmt.Println("Encryption failed:", err)
return
}
fmt.Println("Encryption successful. Encrypted Data:", encryptedData)
*/
func Encrypt(data []byte, secretKey string) (encoded []byte, err error) {
gcm, err := newGcm(secretKey)
if err != nil {
return
}

nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return
}

cipherText := gcm.Seal(nonce, nonce, data, nil)
encodedData := base64.URLEncoding.EncodeToString(cipherText)
encoded = []byte(encodedData)

return
}

/*
Decrypt decrypts the given encrypted data using the specified secret key.
Parameters:
- data: Encrypted data to be decrypted.
- secretKey: Secret key used for decryption.
Returns:
- decoded: Decrypted data.
- err: Error, if any, encountered during the decryption process.
Example Usage:
decryptedData, err := Decrypt(encryptedData, "yourSecretKey")
if err != nil {
fmt.Println("Decryption failed:", err)
return
}
fmt.Println("Decryption successful. Decrypted Data:", decryptedData)
*/
func Decrypt(data []byte, secretKey string) (decoded []byte, err error) {
gcm, err := newGcm(secretKey)
if err != nil {
return
}

buf, err := base64.URLEncoding.DecodeString(string(data))
if err != nil {
return
}

nonce := buf[:gcm.NonceSize()]
cipherText := buf[gcm.NonceSize():]
decoded, err = gcm.Open(nil, nonce, cipherText, nil)
if err != nil {
return
}

return
}

/*
newGcm creates a new Galois/Counter Mode (GCM) cipher for symmetric encryption using the Advanced Encryption Standard (AES).
Parameters:
- secretKey: Secret key used to derive the AES block cipher.
Returns:
- gcm: GCM cipher for encryption and decryption.
- err: Error, if any, encountered during the cipher creation process.
Implementation Details:
- It initializes an AES cipher block with the provided secret key.
- It then creates a GCM cipher using the AES block cipher.
- The resulting GCM cipher is used for secure encryption and decryption.
Example Usage:
gcmCipher, err := newGcm("yourSecretKey")
if err != nil {
fmt.Println("GCM creation failed:", err)
return
}
*/
func newGcm(secretKey string) (gcm cipher.AEAD, err error) {
block, err := aes.NewCipher([]byte(secretKey))
if err != nil {
return
}

gcm, err = cipher.NewGCM(block)
if err != nil {
return
}

return
}
11 changes: 11 additions & 0 deletions pkg/filesystem/filesystem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package filesystem

import (
"io/ioutil"
)

func WriteToFile(path string, result []byte) (err error) {
err = ioutil.WriteFile(path, result, 0644)

return
}

0 comments on commit 1a56ba0

Please sign in to comment.