-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into feature/converstion-algorithms
- Loading branch information
Showing
6 changed files
with
355 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// md5.go | ||
// description: The MD5 hashing function as defined in RFC 1321. | ||
// author: Simon Waldherr | ||
// ref: https://datatracker.ietf.org/doc/html/rfc1321 | ||
// see md5_test.go for testing | ||
|
||
package md5 | ||
|
||
import ( | ||
"encoding/binary" | ||
) | ||
|
||
// Constants for MD5 | ||
var ( | ||
s = [64]uint32{ | ||
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, | ||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, | ||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, | ||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, | ||
} | ||
|
||
K = [64]uint32{ | ||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, | ||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, | ||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, | ||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, | ||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, | ||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, | ||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, | ||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, | ||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, | ||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, | ||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, | ||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, | ||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, | ||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, | ||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, | ||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, | ||
} | ||
) | ||
|
||
// leftRotate rotates x left by n bits | ||
func leftRotate(x, n uint32) uint32 { | ||
return (x << n) | (x >> (32 - n)) | ||
} | ||
|
||
// pad pads the input message so that its length is congruent to 448 modulo 512 | ||
func pad(message []byte) []byte { | ||
originalLength := len(message) * 8 | ||
message = append(message, 0x80) | ||
for (len(message)*8)%512 != 448 { | ||
message = append(message, 0x00) | ||
} | ||
|
||
lengthBytes := make([]byte, 8) | ||
binary.LittleEndian.PutUint64(lengthBytes, uint64(originalLength)) | ||
message = append(message, lengthBytes...) | ||
|
||
return message | ||
} | ||
|
||
// Hash computes the MD5 hash of the input message | ||
func Hash(message []byte) [16]byte { | ||
message = pad(message) | ||
|
||
// Initialize MD5 state variables | ||
a0, b0, c0, d0 := uint32(0x67452301), uint32(0xefcdab89), uint32(0x98badcfe), uint32(0x10325476) | ||
|
||
// Process the message in successive 512-bit chunks | ||
for i := 0; i < len(message); i += 64 { | ||
chunk := message[i : i+64] | ||
var M [16]uint32 | ||
for j := 0; j < 16; j++ { | ||
M[j] = binary.LittleEndian.Uint32(chunk[j*4 : (j+1)*4]) | ||
} | ||
|
||
// Initialize hash value for this chunk | ||
A, B, C, D := a0, b0, c0, d0 | ||
|
||
// Main loop | ||
for i := 0; i < 64; i++ { | ||
var F, g uint32 | ||
if i < 16 { | ||
F = (B & C) | ((^B) & D) | ||
g = uint32(i) | ||
} else if i < 32 { | ||
F = (D & B) | ((^D) & C) | ||
g = uint32((5*i + 1) % 16) | ||
} else if i < 48 { | ||
F = B ^ C ^ D | ||
g = uint32((3*i + 5) % 16) | ||
} else { | ||
F = C ^ (B | (^D)) | ||
g = uint32((7 * i) % 16) | ||
} | ||
F = F + A + K[i] + M[g] | ||
A = D | ||
D = C | ||
C = B | ||
B = B + leftRotate(F, s[i]) | ||
} | ||
|
||
// Add this chunk's hash to result so far | ||
a0 += A | ||
b0 += B | ||
c0 += C | ||
d0 += D | ||
} | ||
|
||
// Produce the final hash value (digest) | ||
var digest [16]byte | ||
binary.LittleEndian.PutUint32(digest[0:4], a0) | ||
binary.LittleEndian.PutUint32(digest[4:8], b0) | ||
binary.LittleEndian.PutUint32(digest[8:12], c0) | ||
binary.LittleEndian.PutUint32(digest[12:16], d0) | ||
|
||
return digest | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// md5_test.go | ||
// description: Tests for the MD5 hashing function as defined in RFC 1321. | ||
// author: Simon Waldherr | ||
|
||
package md5 | ||
|
||
import ( | ||
"encoding/hex" | ||
"testing" | ||
) | ||
|
||
// Helper function to convert hash output to hex string for comparison | ||
func toHexString(hash [16]byte) string { | ||
return hex.EncodeToString(hash[:]) | ||
} | ||
|
||
// Test vectors for MD5 (from RFC 1321 and other known sources) | ||
var tests = []struct { | ||
input string | ||
expected string | ||
}{ | ||
{"", "d41d8cd98f00b204e9800998ecf8427e"}, | ||
{"a", "0cc175b9c0f1b6a831c399e269772661"}, | ||
{"abc", "900150983cd24fb0d6963f7d28e17f72"}, | ||
{"message digest", "f96b697d7cb7938d525a2f31aaf161d0"}, | ||
{"abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"}, | ||
{"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f"}, | ||
{"12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"}, | ||
} | ||
|
||
// TestHash verifies that the Hash function produces the correct MD5 hash values | ||
func TestHash(t *testing.T) { | ||
for _, tt := range tests { | ||
t.Run(tt.input, func(t *testing.T) { | ||
result := Hash([]byte(tt.input)) | ||
resultHex := toHexString(result) | ||
if resultHex != tt.expected { | ||
t.Errorf("MD5(%q) = %s; want %s", tt.input, resultHex, tt.expected) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// sha1.go | ||
// description: The SHA-1 hashing function as defined in RFC 3174. | ||
// author: Simon Waldherr | ||
// ref: https://datatracker.ietf.org/doc/html/rfc3174 | ||
// see sha1_test.go for testing | ||
|
||
package sha1 | ||
|
||
import ( | ||
"encoding/binary" // Used for interacting with uint at the byte level | ||
) | ||
|
||
// Constants for SHA-1 | ||
const ( | ||
h0 uint32 = 0x67452301 | ||
h1 uint32 = 0xEFCDAB89 | ||
h2 uint32 = 0x98BADCFE | ||
h3 uint32 = 0x10325476 | ||
h4 uint32 = 0xC3D2E1F0 | ||
) | ||
|
||
// pad pads the input message so that its length is congruent to 448 modulo 512 | ||
func pad(message []byte) []byte { | ||
originalLength := len(message) * 8 | ||
message = append(message, 0x80) | ||
for (len(message)*8)%512 != 448 { | ||
message = append(message, 0x00) | ||
} | ||
|
||
lengthBytes := make([]byte, 8) | ||
binary.BigEndian.PutUint64(lengthBytes, uint64(originalLength)) | ||
message = append(message, lengthBytes...) | ||
|
||
return message | ||
} | ||
|
||
// leftRotate rotates x left by n bits | ||
func leftRotate(x, n uint32) uint32 { | ||
return (x << n) | (x >> (32 - n)) | ||
} | ||
|
||
// Hash computes the SHA-1 hash of the input message | ||
func Hash(message []byte) [20]byte { | ||
message = pad(message) | ||
|
||
// Initialize variables | ||
a, b, c, d, e := h0, h1, h2, h3, h4 | ||
|
||
// Process the message in successive 512-bit chunks | ||
for i := 0; i < len(message); i += 64 { | ||
var w [80]uint32 | ||
chunk := message[i : i+64] | ||
|
||
// Break chunk into sixteen 32-bit big-endian words | ||
for j := 0; j < 16; j++ { | ||
w[j] = binary.BigEndian.Uint32(chunk[j*4 : (j+1)*4]) | ||
} | ||
|
||
// Extend the sixteen 32-bit words into eighty 32-bit words | ||
for j := 16; j < 80; j++ { | ||
w[j] = leftRotate(w[j-3]^w[j-8]^w[j-14]^w[j-16], 1) | ||
} | ||
|
||
// Initialize hash value for this chunk | ||
A, B, C, D, E := a, b, c, d, e | ||
|
||
// Main loop | ||
for j := 0; j < 80; j++ { | ||
var f, k uint32 | ||
switch { | ||
case j < 20: | ||
f = (B & C) | ((^B) & D) | ||
k = 0x5A827999 | ||
case j < 40: | ||
f = B ^ C ^ D | ||
k = 0x6ED9EBA1 | ||
case j < 60: | ||
f = (B & C) | (B & D) | (C & D) | ||
k = 0x8F1BBCDC | ||
default: | ||
f = B ^ C ^ D | ||
k = 0xCA62C1D6 | ||
} | ||
|
||
temp := leftRotate(A, 5) + f + E + k + w[j] | ||
E = D | ||
D = C | ||
C = leftRotate(B, 30) | ||
B = A | ||
A = temp | ||
} | ||
|
||
// Add this chunk's hash to result so far | ||
a += A | ||
b += B | ||
c += C | ||
d += D | ||
e += E | ||
} | ||
|
||
// Produce the final hash value (digest) | ||
var digest [20]byte | ||
binary.BigEndian.PutUint32(digest[0:4], a) | ||
binary.BigEndian.PutUint32(digest[4:8], b) | ||
binary.BigEndian.PutUint32(digest[8:12], c) | ||
binary.BigEndian.PutUint32(digest[12:16], d) | ||
binary.BigEndian.PutUint32(digest[16:20], e) | ||
|
||
return digest | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// sha1_test.go | ||
// description: Tests for the SHA-1 hashing function as defined in RFC 3174. | ||
// author: Simon Waldherr | ||
|
||
package sha1 | ||
|
||
import ( | ||
"encoding/hex" | ||
"testing" | ||
) | ||
|
||
// Helper function to convert hash output to hex string for comparison | ||
func toHexString(hash [20]byte) string { | ||
return hex.EncodeToString(hash[:]) | ||
} | ||
|
||
// Test vectors for SHA-1 (from RFC 3174 and other known sources) | ||
var tests = []struct { | ||
input string | ||
expected string | ||
}{ | ||
{"", "da39a3ee5e6b4b0d3255bfef95601890afd80709"}, | ||
{"a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"}, | ||
{"abc", "a9993e364706816aba3e25717850c26c9cd0d89d"}, | ||
{"message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3"}, | ||
{"abcdefghijklmnopqrstuvwxyz", "32d10c7b8cf96570ca04ce37f2a19d84240d3a89"}, | ||
{"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "761c457bf73b14d27e9e9265c46f4b4dda11f940"}, | ||
{"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "fecfd28bbc9345891a66d7c1b8ff46e60192d284"}, | ||
} | ||
|
||
// TestHash verifies that the Hash function produces the correct SHA-1 hash values | ||
func TestHash(t *testing.T) { | ||
for _, tt := range tests { | ||
t.Run(tt.input, func(t *testing.T) { | ||
result := Hash([]byte(tt.input)) | ||
resultHex := toHexString(result) | ||
if resultHex != tt.expected { | ||
t.Errorf("SHA-1(%q) = %s; want %s", tt.input, resultHex, tt.expected) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// oddevensort.go | ||
// Implementation of Odd-Even Sort (Brick Sort) | ||
// Reference: https://en.wikipedia.org/wiki/Odd%E2%80%93even_sort | ||
|
||
package sort | ||
|
||
import "github.com/TheAlgorithms/Go/constraints" | ||
|
||
// OddEvenSort performs the odd-even sort algorithm on the given array. | ||
// It is a variation of bubble sort that compares adjacent pairs, alternating | ||
// between odd and even indexed elements in each pass until the array is sorted. | ||
func OddEvenSort[T constraints.Ordered](arr []T) []T { | ||
if len(arr) == 0 { // handle empty array | ||
return arr | ||
} | ||
|
||
swapped := true | ||
for swapped { | ||
swapped = false | ||
|
||
// Perform "odd" indexed pass | ||
for i := 1; i < len(arr)-1; i += 2 { | ||
if arr[i] > arr[i+1] { | ||
arr[i], arr[i+1] = arr[i+1], arr[i] | ||
swapped = true | ||
} | ||
} | ||
|
||
// Perform "even" indexed pass | ||
for i := 0; i < len(arr)-1; i += 2 { | ||
if arr[i] > arr[i+1] { | ||
arr[i], arr[i+1] = arr[i+1], arr[i] | ||
swapped = true | ||
} | ||
} | ||
} | ||
|
||
return arr | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters