2016-01-13 19:25:25 +00:00
package fic
2016-01-07 17:43:02 +00:00
import (
2016-12-04 18:08:46 +00:00
"time"
2017-11-24 19:08:14 +00:00
2018-02-03 01:03:08 +00:00
"golang.org/x/crypto/blake2b"
2016-01-07 17:43:02 +00:00
)
2018-03-09 18:07:08 +00:00
// Key represents a flag's challenge, stored as hash.
2016-01-07 17:43:02 +00:00
type Key struct {
2017-12-04 07:40:17 +00:00
Id int64 ` json:"id" `
2018-03-09 18:07:08 +00:00
// IdExercice is the identifier of the underlying challenge
2017-12-04 07:40:17 +00:00
IdExercice int64 ` json:"idExercice" `
2018-03-09 18:07:08 +00:00
// Label is the title of the flag as displayed to players
2018-01-07 23:17:46 +00:00
Label string ` json:"label" `
2018-09-09 20:28:39 +00:00
// Help is a small piece of text that aims to add useful information like flag format, ...
Help string ` json:"help" `
2018-03-09 18:07:08 +00:00
// Checksum is the expected hashed flag
2017-12-04 07:40:17 +00:00
Checksum [ ] byte ` json:"value" `
2016-01-07 17:43:02 +00:00
}
2018-03-09 18:07:08 +00:00
// GetKeys returns a list of flags comming with the challenge.
2016-01-07 17:43:02 +00:00
func ( e Exercice ) GetKeys ( ) ( [ ] Key , error ) {
2018-09-09 20:28:39 +00:00
if rows , err := DBQuery ( "SELECT id_key, id_exercice, type, help, cksum FROM exercice_keys WHERE id_exercice = ?" , e . Id ) ; err != nil {
2016-01-07 17:43:02 +00:00
return nil , err
} else {
defer rows . Close ( )
var keys = make ( [ ] Key , 0 )
for rows . Next ( ) {
var k Key
2016-01-13 00:20:21 +00:00
k . IdExercice = e . Id
2016-01-19 12:09:36 +00:00
2018-09-09 20:28:39 +00:00
if err := rows . Scan ( & k . Id , & k . IdExercice , & k . Label , & k . Help , & k . Checksum ) ; err != nil {
2016-01-07 17:43:02 +00:00
return nil , err
}
keys = append ( keys , k )
}
if err := rows . Err ( ) ; err != nil {
return nil , err
}
return keys , nil
}
}
2018-03-09 18:07:08 +00:00
// getHashedKey calculates the expected checksum for the given raw_value.
2018-02-03 01:03:08 +00:00
func getHashedKey ( raw_value string ) [ blake2b . Size ] byte {
2017-11-24 19:08:14 +00:00
hash := blake2b . Sum512 ( [ ] byte ( raw_value ) )
return hash
2016-01-15 11:57:35 +00:00
}
2018-03-09 18:07:08 +00:00
// AddRawKey creates and fills a new struct Key, from a non-hashed flag, and registers it into the database.
2018-09-09 20:28:39 +00:00
func ( e Exercice ) AddRawKey ( name string , help string , raw_value string ) ( Key , error ) {
2017-12-04 07:40:17 +00:00
hash := getHashedKey ( raw_value )
2018-09-09 20:28:39 +00:00
return e . AddKey ( name , help , hash [ : ] )
2016-01-07 17:43:02 +00:00
}
2018-03-09 18:07:08 +00:00
// AddKey creates and fills a new struct Key, from a hashed flag, and registers it into the database.
2018-09-09 20:28:39 +00:00
func ( e Exercice ) AddKey ( name string , help string , checksum [ ] byte ) ( Key , error ) {
if res , err := DBExec ( "INSERT INTO exercice_keys (id_exercice, type, help, cksum) VALUES (?, ?, ?, ?)" , e . Id , name , help , checksum ) ; err != nil {
2016-01-07 17:43:02 +00:00
return Key { } , err
} else if kid , err := res . LastInsertId ( ) ; err != nil {
return Key { } , err
} else {
2018-09-09 20:28:39 +00:00
return Key { kid , e . Id , name , help , checksum } , nil
2016-01-07 17:43:02 +00:00
}
}
2018-03-09 18:07:08 +00:00
// Update applies modifications back to the database.
2016-01-07 17:43:02 +00:00
func ( k Key ) Update ( ) ( int64 , error ) {
2018-09-09 20:28:39 +00:00
if res , err := DBExec ( "UPDATE exercice_keys SET id_exercice = ?, type = ?, help = ?, cksum = ? WHERE id_key = ?" , k . IdExercice , k . Label , k . Help , k . Checksum , k . Id ) ; err != nil {
2016-01-07 17:43:02 +00:00
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2018-03-09 18:07:08 +00:00
// Delete the flag from the database.
2016-01-07 17:43:02 +00:00
func ( k Key ) Delete ( ) ( int64 , error ) {
2018-09-07 18:53:08 +00:00
if _ , err := DBExec ( "DELETE FROM exercice_files_deps WHERE id_key = ?" , k . Id ) ; err != nil {
return 0 , err
} else if res , err := DBExec ( "DELETE FROM exercice_keys WHERE id_key = ?" , k . Id ) ; err != nil {
2016-01-07 17:43:02 +00:00
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2016-01-15 11:57:35 +00:00
2018-03-09 18:07:08 +00:00
// WipeKeys deletes keys coming with the challenge.
2017-12-08 23:52:43 +00:00
func ( e Exercice ) WipeKeys ( ) ( int64 , error ) {
2018-09-07 18:53:08 +00:00
if _ , err := DBExec ( "DELETE FROM exercice_files_deps WHERE id_key IN (SELECT id_key FROM exercice_keys WHERE id_exercice = ?)" , e . Id ) ; err != nil {
return 0 , err
} else if res , err := DBExec ( "DELETE FROM exercice_keys WHERE id_exercice = ?" , e . Id ) ; err != nil {
2017-12-08 23:52:43 +00:00
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2018-03-09 18:07:08 +00:00
// Check if the given val is the expected one for this flag.
2016-01-15 11:57:35 +00:00
func ( k Key ) Check ( val string ) bool {
2016-01-19 12:09:36 +00:00
hash := getHashedKey ( val )
2017-12-04 07:40:17 +00:00
if len ( k . Checksum ) != len ( hash ) {
2016-01-19 12:09:36 +00:00
return false
}
for i := range hash {
2017-12-04 07:40:17 +00:00
if k . Checksum [ i ] != hash [ i ] {
2016-01-19 12:09:36 +00:00
return false
}
}
return true
2016-01-15 11:57:35 +00:00
}
2016-12-04 18:08:46 +00:00
2018-03-09 18:07:08 +00:00
// FoundBy registers in the database that the given Team solved the flag.
2016-12-04 18:08:46 +00:00
func ( k Key ) FoundBy ( t Team ) {
DBExec ( "INSERT INTO key_found (id_key, id_team, time) VALUES (?, ?, ?)" , k . Id , t . Id , time . Now ( ) )
}