storj/pkg/identity/generate.go
JT Olio 1faeeb49d5 prepare key generation for launch (#979)
* pkg/identity: use sha256 instead of sha3 for pow

Change-Id: I9b7a4f2c3e624a6e248a233e3653eaccaf23c6f3

* pkg/identity: restructure key generation a bit

Change-Id: I0061a5cc62f04b0c86ffbf046519d5c0a154e896

* cmd/identity: indefinite key generation command

you can start this command and leave it running and it will fill up your
hard drive with node certificate authority private keys ordered by
difficulty.

Change-Id: I61c7a3438b9ff6656e74b8d74fef61e557e4d95a

* pkg/storj: more node id difficulty testing

Change-Id: Ie56b1859aa14ec6ef5973caf42aacb4c494b87c7

* review comments

Change-Id: Iff019aa8121a7804f10c248bf2e578189e5b829d
2019-01-07 13:02:22 -05:00

79 lines
1.7 KiB
Go

// Copyright (c) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package identity
import (
"context"
"crypto/ecdsa"
"storj.io/storj/pkg/peertls"
"storj.io/storj/pkg/storj"
)
// GenerateKey generates a private key with a node id with difficulty at least
// minDifficulty. No parallelism is used.
func GenerateKey(ctx context.Context, minDifficulty uint16) (
k *ecdsa.PrivateKey, id storj.NodeID, err error) {
var d uint16
for {
err = ctx.Err()
if err != nil {
break
}
k, err = peertls.NewKey()
if err != nil {
break
}
id, err = NodeIDFromECDSAKey(&k.PublicKey)
if err != nil {
break
}
d, err = id.Difficulty()
if err != nil {
break
}
if d >= minDifficulty {
return k, id, nil
}
}
return k, id, storj.ErrNodeID.Wrap(err)
}
// GenerateCallback indicates that key generation is done when done is true.
// if err != nil key generation will stop with that error
type GenerateCallback func(*ecdsa.PrivateKey, storj.NodeID) (done bool, err error)
// GenerateKeys continues to generate keys until found returns done == false,
// or the ctx is canceled.
func GenerateKeys(ctx context.Context, minDifficulty uint16, concurrency int, found GenerateCallback) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
errchan := make(chan error, concurrency)
for i := 0; i < concurrency; i++ {
go func() {
for {
k, id, err := GenerateKey(ctx, minDifficulty)
if err != nil {
errchan <- err
return
}
done, err := found(k, id)
if err != nil {
errchan <- err
return
}
if done {
errchan <- nil
return
}
}
}()
}
// we only care about the first error. the rest of the errors will be
// context cancellation errors
return <-errchan
}