From e6e6e6c20616b12ea6a03dae755db79b7cb14f2c Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Nov 2017 20:08:14 +0100 Subject: [PATCH] Use BLAKE2b checksum instead of SHA-1 and SHA-512 --- admin/api/file.go | 13 +++++---- admin/main.go | 1 + admin/static/views/exercice.html | 2 +- frontend/static/views/theme.html | 4 +-- libfic/db.go | 4 +-- libfic/file.go | 47 ++++++++++++++++++++++---------- libfic/key.go | 25 +++++++++-------- 7 files changed, 58 insertions(+), 38 deletions(-) diff --git a/admin/api/file.go b/admin/api/file.go index e82b2cca..272ee16c 100644 --- a/admin/api/file.go +++ b/admin/api/file.go @@ -2,7 +2,6 @@ package api import ( "bufio" - "crypto/sha512" "encoding/base32" "encoding/hex" "errors" @@ -14,6 +13,8 @@ import ( "strings" "srs.epita.fr/fic-server/libfic" + + "github.com/dchest/blake2b" ) var CloudDAVBase string @@ -29,13 +30,13 @@ type uploadedFile struct { } func importFile(uf uploadedFile, next func(string, string, []byte) (interface{}, error)) (interface{}, error) { - var hash [sha512.Size]byte + var hash [blake2b.Size]byte var logStr string var fromURI string var getFile func(string) error if uf.URI != "" && len(uf.Parts) > 0 { - hash = sha512.Sum512([]byte(uf.URI)) + hash = blake2b.Sum512([]byte(uf.URI)) logStr = fmt.Sprintf("Import file from Cloud: %s =>", uf.Parts) fromURI = uf.URI getFile = func(dest string) error { @@ -53,12 +54,12 @@ func importFile(uf uploadedFile, next func(string, string, []byte) (interface{}, return nil } } else if uf.URI != "" { - hash = sha512.Sum512([]byte(uf.URI)) + hash = blake2b.Sum512([]byte(uf.URI)) logStr = "Import file from Cloud: " + uf.URI + " =>" fromURI = uf.URI getFile = func(dest string) error { return getCloudFile(uf.URI, dest) } } else if uf.Path != "" && len(uf.Parts) > 0 { - hash = sha512.Sum512([]byte(uf.Path)) + hash = blake2b.Sum512([]byte(uf.Path)) logStr = fmt.Sprintf("Import file from local FS: %s =>", uf.Parts) fromURI = uf.Path getFile = func(dest string) error { @@ -81,7 +82,7 @@ func importFile(uf uploadedFile, next func(string, string, []byte) (interface{}, return nil } } else if uf.Path != "" { - hash = sha512.Sum512([]byte(uf.Path)) + hash = blake2b.Sum512([]byte(uf.Path)) logStr = "Import file from local FS: " + uf.Path + " =>" fromURI = uf.Path getFile = func(dest string) error { return os.Symlink(uf.Path, dest) } diff --git a/admin/main.go b/admin/main.go index 4711eb77..ca01c7e5 100644 --- a/admin/main.go +++ b/admin/main.go @@ -74,6 +74,7 @@ func main() { flag.StringVar(&api.CloudPassword, "cloudpass", "", "Password used to sync") flag.BoolVar(&api.RapidImport, "rapidimport", false, "Don't try to reimport an existing file") flag.BoolVar(&fic.OptionalDigest, "optionaldigest", false, "Is the digest required when importing files?") + flag.BoolVar(&fic.StrongDigest, "strongdigest", false, "Are BLAKE2b digests required instead of SHA-1 or BLAKE2b?") flag.Parse() log.SetPrefix("[admin] ") diff --git a/admin/static/views/exercice.html b/admin/static/views/exercice.html index f61516ac..155eaf60 100644 --- a/admin/static/views/exercice.html +++ b/admin/static/views/exercice.html @@ -70,7 +70,7 @@
Taille : {{ file.size | size }}
- SHA-1 : {{ file.checksum | cksum }} + BLAKE2b sum : {{ file.checksum | cksum }} diff --git a/frontend/static/views/theme.html b/frontend/static/views/theme.html index 8ccba1e5..2ef90611 100644 --- a/frontend/static/views/theme.html +++ b/frontend/static/views/theme.html @@ -21,7 +21,7 @@

{{ file.name }}

-

Taille : {{ file.size | size }} – SHA-1 : {{ file.checksum }}

+

Taille : {{ file.size | size }}b2sum : {{ file.checksum }}

@@ -80,7 +80,7 @@

- Vérifiez les clefs que vous trouvez en comparant leur SHA-512 : + Vérifiez les clefs que vous trouvez en comparant leur BLAKE2b :

{{ key.slice(128) }}
diff --git a/libfic/db.go b/libfic/db.go index e10967ea..627500bd 100644 --- a/libfic/db.go +++ b/libfic/db.go @@ -110,7 +110,7 @@ CREATE TABLE IF NOT EXISTS exercice_files( path VARCHAR(255) NOT NULL UNIQUE, id_exercice INTEGER NOT NULL, name VARCHAR(255) NOT NULL, - sha1 BINARY(20) NOT NULL, + cksum BINARY(64) NOT NULL, size INTEGER NOT NULL, FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice) ); @@ -134,7 +134,7 @@ CREATE TABLE IF NOT EXISTS exercice_keys( id_key INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, id_exercice INTEGER NOT NULL, type VARCHAR(255) NOT NULL, - value BINARY(64) NOT NULL, + cksum BINARY(64) NOT NULL, FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice) ); `); err != nil { diff --git a/libfic/file.go b/libfic/file.go index 658f7a22..944e333b 100644 --- a/libfic/file.go +++ b/libfic/file.go @@ -9,10 +9,13 @@ import ( "os" "path" "strings" + + "github.com/dchest/blake2b" ) var FilesDir string var OptionalDigest bool +var StrongDigest bool type EFile struct { Id int64 `json:"id"` @@ -25,7 +28,7 @@ type EFile struct { } func GetFiles() ([]EFile, error) { - if rows, err := DBQuery("SELECT id_file, id_exercice, origin, path, name, sha1, size FROM exercice_files"); err != nil { + if rows, err := DBQuery("SELECT id_file, id_exercice, origin, path, name, cksum, size FROM exercice_files"); err != nil { return nil, err } else { defer rows.Close() @@ -47,7 +50,7 @@ func GetFiles() ([]EFile, error) { } func (e Exercice) GetFiles() ([]EFile, error) { - if rows, err := DBQuery("SELECT id_file, origin, path, name, sha1, size FROM exercice_files WHERE id_exercice = ?", e.Id); err != nil { + if rows, err := DBQuery("SELECT id_file, origin, path, name, cksum, size FROM exercice_files WHERE id_exercice = ?", e.Id); err != nil { return nil, err } else { defer rows.Close() @@ -80,28 +83,42 @@ func (e Exercice) ImportFile(filePath string, origin string, digest []byte) (int defer fd.Close() reader := bufio.NewReader(fd) - hash := sha1.New() - if _, err := io.Copy(hash, reader); err != nil { + hash160 := sha1.New() + hash512 := blake2b.New512() + + w := io.MultiWriter(hash160, hash512) + if _, err := io.Copy(w, reader); err != nil { return EFile{}, err } - result := hash.Sum(nil) + result160 := hash160.Sum(nil) + result512 := hash512.Sum(nil) - if len(digest) != len(result) { - return EFile{}, errors.New("Digests doesn't match: calculated: " + hex.EncodeToString(result) + " vs. given: " + hex.EncodeToString(digest)) - } + if len(digest) != len(result512) { + if len(digest) != len(result160) { + return EFile{}, errors.New("Digests doesn't match: calculated: sha1:" + hex.EncodeToString(result160) + " & blake2b:" + hex.EncodeToString(result512) + " vs. given: " + hex.EncodeToString(digest)) + } else if StrongDigest { + return EFile{}, errors.New("Invalid digests: SHA-1 checksums are no more accepted. Calculated sha1:" + hex.EncodeToString(result160) + " & blake2b:" + hex.EncodeToString(result512) + " vs. given: " + hex.EncodeToString(digest)) + } - for k := range result { - if result[k] != digest[k] { - return EFile{}, errors.New("Digests doesn't match: calculated: " + hex.EncodeToString(result) + " vs. given: " + hex.EncodeToString(digest)) + for k := range result160 { + if result160[k] != digest[k] { + return EFile{}, errors.New("Digests doesn't match: calculated: sha1:" + hex.EncodeToString(result160) + " & blake2b:" + hex.EncodeToString(result512) + " vs. given: " + hex.EncodeToString(digest)) + } + } + } else { + for k := range result512 { + if result512[k] != digest[k] { + return EFile{}, errors.New("Digests doesn't match: calculated: " + hex.EncodeToString(result512) + " vs. given: " + hex.EncodeToString(digest)) + } } } - return e.AddFile(strings.TrimPrefix(filePath, FilesDir), origin, path.Base(filePath), result, fi.Size()) + return e.AddFile(strings.TrimPrefix(filePath, FilesDir), origin, path.Base(filePath), result512, fi.Size()) } } func (e Exercice) AddFile(path string, origin string, name string, checksum []byte, size int64) (EFile, error) { - if res, err := DBExec("INSERT INTO exercice_files (id_exercice, origin, path, name, sha1, size) VALUES (?, ?, ?, ?, ?, ?)", e.Id, origin, path, name, checksum, size); err != nil { + if res, err := DBExec("INSERT INTO exercice_files (id_exercice, origin, path, name, cksum, size) VALUES (?, ?, ?, ?, ?, ?)", e.Id, origin, path, name, checksum, size); err != nil { return EFile{}, err } else if fid, err := res.LastInsertId(); err != nil { return EFile{}, err @@ -111,7 +128,7 @@ func (e Exercice) AddFile(path string, origin string, name string, checksum []by } func (f EFile) Update() (int64, error) { - if res, err := DBExec("UPDATE exercice_files SET id_exercice = ?, origin = ?, path = ?, name = ?, sha1 = ?, size = ? WHERE id_file = ?", f.IdExercice, f.origin, f.Path, f.Name, f.Checksum, f.Size, f.Id); err != nil { + if res, err := DBExec("UPDATE exercice_files SET id_exercice = ?, origin = ?, path = ?, name = ?, cksum = ?, size = ? WHERE id_file = ?", f.IdExercice, f.origin, f.Path, f.Name, f.Checksum, f.Size, f.Id); err != nil { return 0, err } else if nb, err := res.RowsAffected(); err != nil { return 0, err @@ -130,6 +147,6 @@ func (f EFile) Delete() (int64, error) { } } -func (f EFile) GetOrigin() (string) { +func (f EFile) GetOrigin() string { return f.origin } diff --git a/libfic/key.go b/libfic/key.go index 853f7166..1f3c43bb 100644 --- a/libfic/key.go +++ b/libfic/key.go @@ -1,19 +1,20 @@ package fic import ( - "crypto/sha512" "time" + + "github.com/dchest/blake2b" ) type Key struct { - Id int64 `json:"id"` - IdExercice int64 `json:"idExercice"` - Type string `json:"type"` - Value []byte `json:"value"` + Id int64 `json:"id"` + IdExercice int64 `json:"idExercice"` + Type string `json:"type"` + Value [blake2b.KeySize]byte `json:"value"` } func (e Exercice) GetKeys() ([]Key, error) { - if rows, err := DBQuery("SELECT id_key, id_exercice, type, value FROM exercice_keys WHERE id_exercice = ?", e.Id); err != nil { + if rows, err := DBQuery("SELECT id_key, id_exercice, type, cksum FROM exercice_keys WHERE id_exercice = ?", e.Id); err != nil { return nil, err } else { defer rows.Close() @@ -36,17 +37,17 @@ func (e Exercice) GetKeys() ([]Key, error) { } } -func getHashedKey(raw_value string) []byte { - hash := sha512.Sum512([]byte(raw_value)) - return hash[:] +func getHashedKey(raw_value string) [blake2b.KeySize]byte { + hash := blake2b.Sum512([]byte(raw_value)) + return hash } func (e Exercice) AddRawKey(name string, raw_value string) (Key, error) { return e.AddKey(name, getHashedKey(raw_value)) } -func (e Exercice) AddKey(name string, value []byte) (Key, error) { - if res, err := DBExec("INSERT INTO exercice_keys (id_exercice, type, value) VALUES (?, ?, ?)", e.Id, name, value); err != nil { +func (e Exercice) AddKey(name string, value [blake2b.KeySize]byte) (Key, error) { + if res, err := DBExec("INSERT INTO exercice_keys (id_exercice, type, cksum) VALUES (?, ?, ?)", e.Id, name, value); err != nil { return Key{}, err } else if kid, err := res.LastInsertId(); err != nil { return Key{}, err @@ -56,7 +57,7 @@ func (e Exercice) AddKey(name string, value []byte) (Key, error) { } func (k Key) Update() (int64, error) { - if res, err := DBExec("UPDATE exercice_keys SET id_exercice = ?, type = ?, value = ? WHERE id_key = ?", k.IdExercice, k.Type, k.Value, k.Id); err != nil { + if res, err := DBExec("UPDATE exercice_keys SET id_exercice = ?, type = ?, cksum = ? WHERE id_key = ?", k.IdExercice, k.Type, k.Value, k.Id); err != nil { return 0, err } else if nb, err := res.RowsAffected(); err != nil { return 0, err