diff --git a/lib/auth/credentials/md5.go b/lib/auth/credentials/md5.go
new file mode 100644
index 0000000000000000000000000000000000000000..42fa877eaf5bf3ee3622f84d9feced261b8d77ec
--- /dev/null
+++ b/lib/auth/credentials/md5.go
@@ -0,0 +1,47 @@
+package credentials
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+	"strings"
+
+	"pggat2/lib/auth"
+	"pggat2/lib/util/slices"
+)
+
+type MD5 struct {
+	Username string
+	Hash     []byte
+}
+
+func (T MD5) GetUsername() string {
+	return T.Username
+}
+
+func (T MD5) EncodeMD5(salt [4]byte) string {
+	hexEncoded := make([]byte, hex.EncodedLen(len(T.Hash)))
+	hex.Encode(hexEncoded, T.Hash)
+	hash := md5.New()
+
+	hash.Write(hexEncoded)
+	hash.Write(salt[:])
+	sum := hash.Sum(nil)
+	hexEncoded = slices.Resize(hexEncoded, hex.EncodedLen(len(sum)))
+	hex.Encode(hexEncoded, sum)
+
+	var out strings.Builder
+	out.Grow(3 + len(hexEncoded))
+	out.WriteString("md5")
+	out.Write(hexEncoded)
+	return out.String()
+}
+
+func (T MD5) VerifyMD5(salt [4]byte, value string) error {
+	if T.EncodeMD5(salt) != value {
+		return auth.ErrFailed
+	}
+
+	return nil
+}
+
+var _ auth.MD5 = MD5{}