Skip to content

Commit

Permalink
Merge pull request #36 from phires/issue-#9
Browse files Browse the repository at this point in the history
Issue #9
  • Loading branch information
phires authored Jun 10, 2024
2 parents 35cb46e + c621504 commit f81a546
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 7 deletions.
7 changes: 5 additions & 2 deletions backends/p_guerrilla_db_redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,11 +415,14 @@ func GuerrillaDbRedis() Decorator {
if err := e.ParseHeaders(); err != nil {
Log().WithError(err).Error("failed to parse headers")
}
hash := MD5Hex(
hash, err := BLAKE2s128Hex(
to,
e.MailFrom.String(),
e.Subject,
ts)
if err != nil {
Log().WithError(err).Error("failed to hash")
}
e.QueuedId = hash

// Add extra headers
Expand Down Expand Up @@ -469,7 +472,7 @@ func GuerrillaDbRedis() Decorator {
e.TLS)
// give the values to a random query batcher
var index int
err := binary.Read(rand.Reader, binary.LittleEndian, &index)
err = binary.Read(rand.Reader, binary.LittleEndian, &index)
if err != nil {
panic(err)
}
Expand Down
60 changes: 55 additions & 5 deletions backends/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,28 @@ package backends
import (
"bytes"
"compress/zlib"
"crypto/md5"
"crypto/md5" //#nosec G501 - Deprecated, kept for backwards compatibility
"fmt"
"io"
"net/textproto"
"regexp"
"strings"

"golang.org/x/crypto/blake2s"
)

// First capturing group is header name, second is header value.
// Accounts for folding headers.
var headerRegex, _ = regexp.Compile(`^([\S ]+):([\S ]+(?:\r\n\s[\S ]+)?)`)

// ParseHeaders is deprecated, see mail.Envelope.ParseHeaders instead
// ParseHeaders parses the headers from the given mailData string and returns a map of header names to their values.
//
// Parameters:
// - mailData: a string containing the mail data.
//
// Return:
// - a map[string]string containing the parsed headers, where the keys are the header names and the values are the header values.
// Deprecated: use mail.Envelope.ParseHeader
func ParseHeaders(mailData string) map[string]string {
var headerSectionEnds int
for i, char := range mailData[:len(mailData)-4] {
Expand All @@ -35,9 +44,16 @@ func ParseHeaders(mailData string) map[string]string {
return headers
}

// returns an md5 hash as string of hex characters
// MD5Hex generates a hexadecimal representation of the MD5 hash of the given string arguments.
//
// Parameters:
// - stringArguments: A variadic parameter that accepts one or more string arguments.
//
// Returns:
// - string: The hexadecimal representation of the MD5 hash.
// Deprecated: use BLAKE128s128Hex instead
func MD5Hex(stringArguments ...string) string {
h := md5.New()
h := md5.New() //#nosec G401 - Deprecated, kept for backwards compatibility
var r *strings.Reader
for i := 0; i < len(stringArguments); i++ {
r = strings.NewReader(stringArguments[i])
Expand All @@ -47,7 +63,41 @@ func MD5Hex(stringArguments ...string) string {
return fmt.Sprintf("%x", sum)
}

// concatenate & compress all strings passed in
// BLAKE2s128Hex generates a Blake2s-128 hash as a string of hex characters from the given string arguments.
//
// Parameters:
// - stringArguments: A variadic parameter that accepts one or more string arguments.
//
// Returns:
// - string: The Blake2s-128 hash as a string of hex characters.
// - error: An error if the hash generation fails.
func BLAKE2s128Hex(stringArguments ...string) (string, error) {
// Create a zeroed 16-byte slice for unkeyed hashing.
key := make([]byte, 16) // Zeroed key for unkeyed BLAKE2s

h, err := blake2s.New128(key)
if err != nil {
return "", err
}
var r *strings.Reader
for i := 0; i < len(stringArguments); i++ {
r = strings.NewReader(stringArguments[i])
_, err := io.Copy(h, r)
if err != nil {
return "", err
}
}
sum := h.Sum([]byte{})
return fmt.Sprintf("%x", sum), nil
}

// Compress concatenates and compresses all the strings passed in using zlib.
//
// Parameters:
// - stringArguments: A variadic parameter that accepts one or more string arguments.
//
// Returns:
// - string: The compressed string.
func Compress(stringArguments ...string) string {
var b bytes.Buffer
var r *strings.Reader
Expand Down
160 changes: 160 additions & 0 deletions backends/util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package backends

import (
"encoding/base64"
"testing"
)

func TestBLAKE2s128Hex(t *testing.T) {
tests := []struct {
name string
input []string
want string
expectErr bool
}{
{
name: "single string",
input: []string{"example"},
want: "8b944eb07157cea5041a4b209fda1f09",
expectErr: false,
},
{
name: "multiple strings",
input: []string{"example", "string", "arguments"},
want: "9645451b82265ee62552a4a1a12bc285",
expectErr: false,
},
{
name: "empty input",
input: []string{""},
want: "69c907decfc59db6ceec48fb3412eccc",
expectErr: false,
},
{
name: "no input",
input: []string{},
want: "69c907decfc59db6ceec48fb3412eccc",
expectErr: false,
},
{
name: "♥️ unicode input",
input: []string{"♥️ unicode input"},
want: "900fdd1d2a1c73d69a60fe08721e8ddc",
expectErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := BLAKE2s128Hex(tt.input...)
if (err != nil) != tt.expectErr {
t.Errorf("BLAKE2s128Hex() error = %v, expectErr %v", err, tt.expectErr)
return
}
if got != tt.want {
t.Errorf("BLAKE2s128Hex() = %v, want %v", got, tt.want)
}
})
}
}

func TestMD5Hex(t *testing.T) {
tests := []struct {
name string
input []string
want string
expectErr bool
}{
{
name: "single string",
input: []string{"example"},
want: "1a79a4d60de6718e8e5b326e338ae533",
expectErr: false,
},
{
name: "multiple strings",
input: []string{"example", "string", "arguments"},
want: "3a64be4275748ae9b712864a9d827405",
expectErr: false,
},
{
name: "empty input",
input: []string{""},
want: "d41d8cd98f00b204e9800998ecf8427e",
expectErr: false,
},
{
name: "no input",
input: []string{},
want: "d41d8cd98f00b204e9800998ecf8427e",
expectErr: false,
},
{
name: "♥️ unicode input",
input: []string{"♥️ unicode input"},
want: "a4b99076d321097b647088684692363f",
expectErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := MD5Hex(tt.input...)
if got != tt.want {
t.Errorf("MD5Hex() = %v, want %v", got, tt.want)
}
})
}
}

// TestCompress tests the compress function
// It converts the compressed string to base64 to make it comparable
func TestCompress(t *testing.T) {
tests := []struct {
name string
input []string
want string
expectErr bool
}{
{
name: "single string",
input: []string{"example"},
want: "eAEABwD4/2V4YW1wbGUBAAD//wvAAu0=",
expectErr: false,
},
{
name: "multiple strings",
input: []string{"example", "string", "arguments"},
want: "eAEAFgDp/2V4YW1wbGVzdHJpbmdhcmd1bWVudHMBAAD//2sQCVo=",
expectErr: false,
},
{
name: "empty input",
input: []string{""},
want: "eAEBAAD//wAAAAE=",
expectErr: false,
},
{
name: "no input",
input: []string{},
want: "eAEBAAD//wAAAAE=",
expectErr: false,
},
{
name: "♥️ unicode input",
input: []string{"♥️ unicode input"},
want: "eAEAFADr/+KZpe+4jyB1bmljb2RlIGlucHV0AQAA//9yqAmu",
expectErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Compress(tt.input...)
base64 := base64.StdEncoding.EncodeToString([]byte(got))
if base64 != tt.want {
t.Errorf("Compress() = %v, want %v", base64, tt.want)
}
})
}
}

0 comments on commit f81a546

Please sign in to comment.