Skip to content

Commit

Permalink
lesson 5
Browse files Browse the repository at this point in the history
  • Loading branch information
bodrovis committed Jun 1, 2024
1 parent 2a3aa95 commit c61019e
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 0 deletions.
9 changes: 9 additions & 0 deletions lesson_5/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module lesson5

go 1.22.2

require (
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
)
6 changes: 6 additions & 0 deletions lesson_5/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
40 changes: 40 additions & 0 deletions lesson_5/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package main

import (
"bufio"
"errors"
"flag"
"fmt"
"lesson5/processor"
"lesson5/utils"
"os"
)

var cipherMode = flag.Bool("cipher", false, "Enable cipher mode.")
var decipherMode = flag.Bool("decipher", false, "Enable decipher mode.")

func main() {
flag.Parse()

if *cipherMode && *decipherMode {
utils.HaltOnErr(errors.New("please specify only one mode at a time"))
}

if *decipherMode {
decipheredBytes, err := processor.Decrypt()
utils.HaltOnErr(err)

fmt.Println(string(decipheredBytes))
} else if *cipherMode {
reader := bufio.NewReader(os.Stdin)

fmt.Print("Enter full sentence: ")

sentence, _ := reader.ReadString('\n')

err := processor.Encrypt(sentence)
utils.HaltOnErr(err)
} else {
utils.HaltOnErr(errors.New("unknown mode"))
}
}
58 changes: 58 additions & 0 deletions lesson_5/processor/decrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package processor

import (
"bytes"
"encoding/gob"
"os"
)

func Decrypt() ([]byte, error) {
pkg, err := readEncryptedFile("encrypted_data.bin")
if err != nil {
return nil, err
}

nonce := pkg.Nonce
salt := pkg.Salt
encryptedData := pkg.EncryptedData

passphrase, err := GetPassphrase()
if err != nil {
return nil, err
}

key, err := DeriveKeyFrom(passphrase, salt)
if err != nil {
return nil, err
}

crypter, err := MakeCrypterFrom(key)
if err != nil {
return nil, err
}

decipheredBytes, err := crypter.Open(nil, []byte(nonce), encryptedData, nil)
if err != nil {
return nil, err
}

return decipheredBytes, nil
}

func readEncryptedFile(filename string) (*EncryptedPackage, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}

buffer := bytes.NewBuffer(data)
decoder := gob.NewDecoder(buffer)

var pkg EncryptedPackage

if err := decoder.Decode(&pkg); err != nil {
return nil, err
}

return &pkg, nil
}
83 changes: 83 additions & 0 deletions lesson_5/processor/encrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package processor

import (
"bytes"
"crypto/cipher"
"crypto/rand"
"encoding/gob"
"os"
)

func Encrypt(data string) error {
passphrase, err := GetPassphrase()
if err != nil {
return err
}

salt, err := makeSalt()
if err != nil {
return err
}

key, err := DeriveKeyFrom(passphrase, salt)
if err != nil {
return err
}

crypter, err := MakeCrypterFrom(key)
if err != nil {
return err
}

nonce, err := makeNonceFor(crypter)
if err != nil {
return err
}

encryptedData := crypter.Seal(nil, nonce, []byte(data), nil)

err = saveToFile(encryptedData, nonce, salt)
if err != nil {
return err
}

return nil
}

func saveToFile(encryptedData, nonce, salt []byte) error {
encPackage := EncryptedPackage{
Nonce: nonce,
Salt: salt,
EncryptedData: encryptedData,
}

var buffer bytes.Buffer
encoder := gob.NewEncoder(&buffer)
if err := encoder.Encode(encPackage); err != nil {
return err
}

if err := os.WriteFile("encrypted_data.bin", buffer.Bytes(), 0644); err != nil {
return err
}

return nil
}

func makeSalt() ([]byte, error) {
salt := make([]byte, 16)
if _, err := rand.Read(salt); err != nil {
return nil, err
}

return salt, nil
}

func makeNonceFor(crypter cipher.AEAD) ([]byte, error) {
nonce := make([]byte, crypter.NonceSize())
if _, err := rand.Read(nonce); err != nil {
return nil, err
}

return nonce, nil
}
48 changes: 48 additions & 0 deletions lesson_5/processor/processor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package processor

import (
"crypto/aes"
"crypto/cipher"
"fmt"
"golang.org/x/crypto/argon2"
"golang.org/x/term"
"os"
)

type EncryptedPackage struct {
Nonce []byte
Salt []byte
EncryptedData []byte
}

func MakeCrypterFrom(key []byte) (cipher.AEAD, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}

return cipher.NewGCM(block)
}

func DeriveKeyFrom(passphrase, salt []byte) ([]byte, error) {
key := argon2.IDKey([]byte(passphrase), salt, 1, 64*1024, 4, 32)

return key, nil
}

func GetPassphrase() ([]byte, error) {
println("Enter passphrase:")
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))

if err != nil {
return nil, fmt.Errorf("failed to grab passphrase: %w", err)
}

passphrase, err := term.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
return nil, fmt.Errorf("failed to grab passphrase: %w", err)
}
defer term.Restore(int(os.Stdin.Fd()), oldState)

return passphrase, nil
}
24 changes: 24 additions & 0 deletions lesson_5/utils/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package utils

import (
"fmt"
"log"
"os"
"strings"
)

var errorLogger = log.New(os.Stderr, "ERROR: ", log.LstdFlags|log.Lshortfile)

func HaltOnErr(err error, messages ...string) {
if err == nil {
return
}

message := "An error occurred"
if len(messages) > 0 {
message = fmt.Sprintf("%s: %s", message, strings.Join(messages, " "))
}

errorLogger.Printf("%s: %v", message, err)
os.Exit(1)
}

0 comments on commit c61019e

Please sign in to comment.