Проблема с NaCl заключается в том, что вам нужно поместить все сообщение в ОЗУ, согласно годоку :
Сообщения должны быть маленькими, потому что: 1. Требуется все сообщениехранится в памяти для обработки.2. Использование больших сообщений заставляет реализации на небольших машинах обрабатывать открытый текст без проверки подписи.Это очень опасно, и этот API не одобряет его, но протокол, который использует чрезмерные размеры сообщений, может представлять некоторые реализации без другого выбора.3. Производительность можно улучшить, работая с сообщениями, которые помещаются в кэш данных.Таким образом, большие объемы данных должны быть разбиты на части, чтобы каждое сообщение было небольшим.
Однако существуют различные другие методы.Большинство из них в основном делают то, что вы описали первым способом.Вы в основном копируете содержимое файла в io.Writer
, который берет содержимое и вычисляет хэш-сумму - это наиболее эффективно.
Код ниже довольно взломан, но вы должны получить картину.При этом я достиг средней пропускной способности 315 МБ / с.
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"flag"
"fmt"
"io"
"log"
"math/big"
"os"
"time"
)
var filename = flag.String("file", "", "file to sign")
func main() {
flag.Parse()
if *filename == "" {
log.Fatal("file can not be empty")
}
f, err := os.Open(*filename)
if err != nil {
log.Fatalf("Error opening '%s': %s", *filename, err)
}
defer f.Close()
start := time.Now()
sum, n, err := hash(f)
duration := time.Now().Sub(start)
log.Printf("Hashed %s (%d bytes)in %s to %x", *filename, n, duration, sum)
log.Printf("Average: %.2f MB/s", (float64(n)/1000000)/duration.Seconds())
r, s, err := sign(sum)
if err != nil {
log.Fatalf("Error creatig signature: %s", err)
}
log.Printf("Signature: (0x%x,0x%x)\n", r, s)
}
func sign(sum []byte) (*big.Int, *big.Int, error) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Printf("Error creating private key: %s", err)
}
return ecdsa.Sign(rand.Reader, priv, sum[:])
}
func hash(f *os.File) ([]byte, int64, error) {
var (
hash []byte
n int64
err error
)
h := sha256.New()
// This is where the magic happens.
// We use the efficient io.Copy to feed the contents
// of the file into the hash function.
if n, err = io.Copy(h, f); err != nil {
return nil, n, fmt.Errorf("Error creating hash: %s", err)
}
hash = h.Sum(nil)
return hash, n, nil
}