Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: restructured files - less ambiguous. Removed use of "utils" #15

Merged
merged 2 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions analysis/frequency.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package analysis

// scoreText evaluates the likelihood that a given byte slice (input) is
// meaningful or coherent English text. It does so by scoring each byte
// according to its frequency of appearance in English, with a higher score
// indicating a higher likelihood of the input being English.
func ScoreText(input []byte) float64 {
// englishFreq maps English letters and the space character to their
// relative frequencies in English text
englishFreq := map[byte]float64{
'a': 8.167, 'b': 1.492, 'c': 2.782, 'd': 4.253, 'e': 12.702,
'f': 2.228, 'g': 2.015, 'h': 6.094, 'i': 6.966, 'j': 0.153,
'k': 0.772, 'l': 4.025, 'm': 2.406, 'n': 6.749, 'o': 7.507,
'p': 1.929, 'q': 0.095, 'r': 5.987, 's': 6.327, 't': 9.056,
'u': 2.758, 'v': 0.978, 'w': 2.360, 'x': 0.150, 'y': 1.974,
'z': 0.074, ' ': 13.000,
}

score := 0.0

for _, b := range input {
// If the byte is found in the englishFreq map,add its frequency value
// to the total score.
if val, ok := englishFreq[b]; ok {
score += val
}
}

return score
}
27 changes: 27 additions & 0 deletions analysis/frequency_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package analysis

import (
"testing"
)

func TestScoreText(t *testing.T) {
tests := []struct {
name string
text string
score float64
}{
{name: "Valid score", text: "What Do You Want From Me", score: 158.66299999999998},
{name: "No text", text: "", score: 0.0},
{name: "Single letter", text: "a", score: 8.167},
{name: "Space", text: " ", score: 13.000},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ScoreText([]byte(tt.text))
if got != tt.score {
t.Fatalf("expected: %f, got: %f", tt.score, got)
}
})
}
}
19 changes: 19 additions & 0 deletions encoding/base64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package encoding

import "encoding/base64"

// Decodes Base64 encoded string. Returns bytes.
func DecodeBase64(encoded string) ([]byte, error) {
return base64.StdEncoding.DecodeString(encoded)
}

// isBase64Encoded checks if the input string is Base64 encoded.
// This function performs a basic check to see if the input is decodable from Base64.
func isBase64Encoded(input string) bool {
if input == "" {
return false
}
// Attempt to decode the input string from Base64
_, err := base64.StdEncoding.DecodeString(input)
return err == nil
}
24 changes: 24 additions & 0 deletions encoding/base64_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package encoding

import "testing"

func TestIsBase64Encoded(t *testing.T) {
tests := []struct {
name string
input string
want bool
}{
{name: "Valid Base64", input: "dGVzdCBpbnB1dA==", want: true},
{name: "Invalid Base64", input: "test input", want: false},
{name: "Empty String", input: "", want: false},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := isBase64Encoded(tt.input)
if got != tt.want {
t.Errorf("want: %v, got: %v", tt.want, got)
}
})
}
}
26 changes: 26 additions & 0 deletions encoding/decode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package encoding

func Decode(encodedData string) ([]byte, error) {
var verifiedData []byte
var err error
if isHexEncoded(encodedData) {
verifiedData, err = DecodeHex(encodedData)
if err != nil {
return nil, err
}
return verifiedData, nil
}

if isBase64Encoded(encodedData) {
verifiedData, err = DecodeBase64(encodedData)
if err != nil {
return nil, err
}
return verifiedData, nil
}

// plaintext, or some other encoded data type not checked for.
verifiedData = []byte(encodedData)

return verifiedData, nil
}
29 changes: 29 additions & 0 deletions encoding/decode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package encoding

import "testing"

func TestDecode(t *testing.T) {
tests := []struct {
name string
encoded string
want string
wantErr bool
}{
{name: "Hex Encoded Text", encoded: "7465737420696e707574", want: "test input", wantErr: false},
{name: "Non-Encoded Text", encoded: "not encoded text", want: "not encoded text", wantErr: false},
{name: "Base64 Encoded Text", encoded: "dGVzdCBpbnB1dA==", want: "test input", wantErr: false},
{name: "Invalid Hex", encoded: "7465737420696e70757", want: "", wantErr: true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Decode(tt.encoded)
if err == nil && tt.wantErr {
t.Errorf("expected error and didn't get one")
}
if string(got) != tt.want {
t.Errorf("want: %v, got: %v", tt.want, got)
}
})
}
}
28 changes: 28 additions & 0 deletions encoding/hex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package encoding

import (
"encoding/hex"
"fmt"
"regexp"
)

// Decodes hex encoded string. Returns bytes.
func DecodeHex(encoded string) ([]byte, error) {
return hex.DecodeString(encoded)
}

// isHexEncoded checks if the input string is hex encoded.
// This function uses a regex pattern to ensure the string consists only of hexadecimal characters.
func isHexEncoded(input string) bool {
if input == "" {
return false
}
// Hex regex pattern to match valid hexadecimal characters
hexPattern := `^[0-9A-Fa-f]+$`
matched, err := regexp.MatchString(hexPattern, input)
if err != nil {
fmt.Println("Regex match error:", err)
return false
}
return matched
}
23 changes: 23 additions & 0 deletions encoding/hex_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package encoding

import "testing"

func TestIsHexEncoded(t *testing.T) {
tests := []struct {
name string
input string
want bool
}{
{name: "Valid Hex", input: "7465737420696e707574", want: true},
{name: "Invalid Hex", input: "test input", want: false},
{name: "Empty String", input: "", want: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := isHexEncoded(tt.input)
if got != tt.want {
t.Errorf("want: %v, got: %v", tt.want, got)
}
})
}
}
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"time"

"github.com/nronzel/xoracle/pkg/handlers"
limiter "github.com/nronzel/xoracle/pkg/rate_limiter"
mw "github.com/nronzel/xoracle/pkg/middleware"
)

func main() {
Expand All @@ -16,7 +16,7 @@ func main() {
mux.HandleFunc("GET /", handlers.HandlerRoot)
mux.HandleFunc("POST /decrypt", handlers.HandlerDecrypt)

rl := limiter.NewRateLimiter(1, 3)
rl := mw.NewRateLimiter(1, 3)

server := &http.Server{
Addr: ":8080",
Expand Down
5 changes: 3 additions & 2 deletions pkg/decryption/decryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package decryption

import (
"fmt"
"github.com/nronzel/xoracle/utils"
"math"
"sort"

"github.com/nronzel/xoracle/analysis"
)

// singleByteXORCipher attempts to decrypt a message that has been XOR'ed
Expand All @@ -30,7 +31,7 @@ func singleByteXORCipher(encoded []byte) (byte, []byte) {
}

// Evaluate the decrypted message using a scoring function.
score := utils.ScoreText(decoded)
score := analysis.ScoreText(decoded)

// If the current message's score is higher than the highest score found
// so far - update maxScore, key, and message with the current values.
Expand Down
6 changes: 3 additions & 3 deletions pkg/decryption/decryption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import (
"reflect"
"testing"

"github.com/nronzel/xoracle/utils"
"github.com/nronzel/xoracle/encoding"
)

func TestProcessKeySizes(t *testing.T) {
decodedBase64, _ := utils.DecodeBase64("MiciMCQ2YTYkOjViJTclJyQ=")
decodedHex, _ := utils.DecodeHex("3227223024366136243a35622537252724")
decodedBase64, _ := encoding.DecodeBase64("MiciMCQ2YTYkOjViJTclJyQ=")
decodedHex, _ := encoding.DecodeHex("3227223024366136243a35622537252724")
tests := []struct {
name string
topKeySizes []int
Expand Down
File renamed without changes.
6 changes: 4 additions & 2 deletions pkg/decryption/dc_util.go → pkg/decryption/score.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package decryption

import "github.com/nronzel/xoracle/utils"
import (
"github.com/nronzel/xoracle/analysis"
)

// Scores the resulting decrypted data after attempting to decrypt with the guessed
// key and keySize. Higher score means it is more likely English text and it will
Expand All @@ -11,7 +13,7 @@ func ScoreResults(results []DecryptionResult) DecryptionResult {
var highScore float64
var best DecryptionResult
for _, result := range results {
score := utils.ScoreText([]byte(result.DecryptedData))
score := analysis.ScoreText([]byte(result.DecryptedData))
if score > highScore {
highScore = score
best.DecryptedData = result.DecryptedData
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions pkg/handlers/handlerDecrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"net/http"
"strings"

en "github.com/nronzel/xoracle/encoding"
dc "github.com/nronzel/xoracle/pkg/decryption"
"github.com/nronzel/xoracle/utils"
)

func HandlerDecrypt(w http.ResponseWriter, r *http.Request) {
Expand All @@ -23,7 +23,7 @@ func HandlerDecrypt(w http.ResponseWriter, r *http.Request) {
// Checks if data is Base64 or Hex encoded, and decodes, otherwise just
// returns the data as is. It's either plaintext, or some other encoding
// not checked for.
verifiedData, err := utils.Decode(encodedData)
verifiedData, err := en.Decode(encodedData)
if err != nil {
w.Header().Set("Content-Type", "text/plaintext")
http.Error(w, "problem decoding data", http.StatusInternalServerError)
Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions scripts/buildmac.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o xoracle-macos-amd64
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o xoracle-macos-arm64
3 changes: 3 additions & 0 deletions scripts/buildwindows.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o xoracle.exe
Loading