From 2e76436e7801a41af13e40e0ae402f15258081ff Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Thu, 24 May 2018 02:29:57 +0200
Subject: [PATCH] Added references, significantly improved security

---
 glide.lock |  5 +++--
 glide.yaml |  2 +-
 main.go    | 62 +++++++++++++++++++++++++++++++++++++++++++-----------
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/glide.lock b/glide.lock
index 9a55495..a6584b6 100644
--- a/glide.lock
+++ b/glide.lock
@@ -1,5 +1,5 @@
-hash: 71071f00798b1f4ce22ab71a61bbaccc0a10c7cb9e0a9acd0ac8c868c843d46d
-updated: 2018-05-24T01:08:01.558664212+02:00
+hash: 9aa87de7030f5b57ee15949488773eed43794051d931d592b57d01ba08baa1b3
+updated: 2018-05-24T02:24:44.532048957+02:00
 imports:
 - name: github.com/lib/pq
   version: 90697d60dd844d5ef6ff15135d0203f65d2f53b8
@@ -10,5 +10,6 @@ imports:
 - name: golang.org/x/crypto
   version: 75e913eb8a8e3d31a97b216de09de106a7b07681
   subpackages:
+  - scrypt
   - sha3
 testImports: []
diff --git a/glide.yaml b/glide.yaml
index 10bbc8a..04ed8d7 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -4,4 +4,4 @@ import:
 - package: github.com/lib/pq
 - package: golang.org/x/crypto
   subpackages:
-  - sha3
\ No newline at end of file
+  - scrypt
\ No newline at end of file
diff --git a/main.go b/main.go
index 42f47d3..26b627f 100644
--- a/main.go
+++ b/main.go
@@ -7,11 +7,11 @@ import (
 	"strings"
 	"log"
 	"time"
-	"golang.org/x/crypto/sha3"
 	_ "github.com/lib/pq"
 	"encoding/hex"
 	"database/sql"
 	"strconv"
+	"golang.org/x/crypto/scrypt"
 )
 
 type Config struct {
@@ -59,6 +59,12 @@ func NewConfigFromEnv() Config {
 	return config
 }
 
+type IrcChannel struct {
+	Id   int
+	Name string
+	Salt string
+}
+
 type IrcMessage struct {
 	Time        time.Time
 	Channel     int
@@ -97,6 +103,14 @@ func (m *IrcMessage) ToString() string {
 	return fmt.Sprintf("IrcMessage{time=%s,channel=%d,sender=%s,words=%d,characters=%d,flags=[%s]}", m.Time.Format(time.RFC3339), m.Channel, m.Sender, m.Words, m.Characters, strings.Join(flags, ","))
 }
 
+func hashName(salt string, name string) string {
+	hash, err := scrypt.Key([]byte(name), []byte(salt), 32768, 8, 1, 32)
+	if err != nil {
+		panic(err)
+	}
+	return hex.EncodeToString(hash)
+}
+
 func main() {
 	config := NewConfigFromEnv()
 
@@ -122,20 +136,25 @@ func main() {
 	}
 	client := girc.New(ircConfig)
 
-	channels := map[string]int{}
+	channels := map[string]IrcChannel{}
 	client.Handlers.Add(girc.CONNECTED, func(c *girc.Client, e girc.Event) {
-		result, err := db.Query("SELECT id, channel FROM channels")
+		result, err := db.Query("SELECT id, channel, salt FROM channels")
 		if err != nil {
 			panic(err)
 		}
 		for result.Next() {
 			var id int
 			var name string
-			err := result.Scan(&id, &name)
+			var salt string
+			err := result.Scan(&id, &name, &salt)
 			if err != nil {
 				panic(err)
 			}
-			channels[name] = id
+			channels[name] = IrcChannel{
+				Id:   id,
+				Name: name,
+				Salt: salt,
+			}
 		}
 		for name := range channels {
 			c.Cmd.Join(name)
@@ -144,15 +163,34 @@ func main() {
 
 	client.Handlers.Add(girc.PRIVMSG, func(c *girc.Client, e girc.Event) {
 		if len(e.Params) == 1 {
-			channel := e.Params[0]
-			if id, ok := channels[channel]; ok {
-				name := hex.EncodeToString(sha3.New256().Sum([]byte(e.Source.Name)))
+			channelName := e.Params[0]
+			if channelData, ok := channels[channelName]; ok {
+				now := time.Now().UTC()
+
+				name := hashName(channelData.Salt, e.Source.Name)
 				content := strings.TrimSpace(e.Trailing)
-				// Add referenced nick part here
-				// c.LookupChannel(channel).UserList
+
+				channel := c.LookupChannel(channelName)
+
+				var users []string
+				if channel != nil {
+					for _, user := range channel.UserList {
+						if strings.Contains(content, user) {
+							users = append(users, hashName(channelData.Salt, user))
+						}
+					}
+				}
+
+				for _, user := range users {
+					_, err := db.Exec("INSERT INTO \"references\" (time, source, target) VALUES ($1, $2, $3)", now, name, user)
+					if err != nil {
+						println(err.Error())
+					}
+				}
+
 				message := IrcMessage{
-					Time:        time.Now().UTC(),
-					Channel:     id,
+					Time:        now,
+					Channel:     channelData.Id,
 					Sender:      name,
 					Words:       len(strings.Split(content, " ")),
 					Characters:  len(content),
-- 
GitLab