-
-
Notifications
You must be signed in to change notification settings - Fork 36
Why are Votes "pseudo anonymous"?
Votes are stored in the database to be able to "revive" running votes after a restart of the bot. After a vote has been closed or expired, the entry is removed from the database.
A vote is stored as an gob encoded object stored as base64 encoded string into the database to ensure compatibility across multiple relational databases.
This vote object also includes all ticks stored in a map with a unique user identifier. This is done to ensure tick integrity so that a user can not tick for multiple choices and to be able to change their choice during vote lifetime.
// Vote wraps the information and current
// state of a vote and its ticks.
type Vote struct {
ID string
MsgID string
CreatorID string
GuildID string
ChannelID string
Description string
ImageURL string
Expires time.Time
Possibilities []string
Ticks map[string]*Tick
}
// Tick wraps a user ID and the index of
// the selection ticked.
type Tick struct {
UserID string
Tick int
}
As mentioned above, vote ticks are directly linked to users using unique identifiers. These identifiers are generated using the following function.
// HashUserID takes a userID as well as a salt value
// to generate a unique hash.
//
// Therefore, the first 12 bits are cut of to obscure
// the ID while keeping the risk of collissions low.
func HashUserID(userID string, salt []byte) (hash string, err error) {
sid, err := snowflake.ParseString(userID)
if err != nil {
return
}
idb := big.NewInt(sid.Int64() & int64(^uint(0)>>(64-48))).Bytes()
comb := append(idb, salt...)
hash = fmt.Sprintf("%x", sha256.Sum256(comb))
return
}
The last 48 bits of the user ID is hashed together with the ID of the vote as salt. That is done to ensure some level of obscurity and anonymity for the users to protect against database dump incidents.
The problem is, that if you have access to the vote data as well as to a list of user IDs of a guild where the vote was created, you can potentially use the function above to generate hashed for all users on a guild for the specific vote and then match which users ticked which option. But this is only possible for someone who has access to the database as well as to the guild where the vote was created on.