c35b93766d
this change removes the cryptopasta dependency. a couple possible sources of problem with this change: * the encoding used for ECDSA signatures on SignedMessage has changed. the encoding employed by cryptopasta was workable, but not the same as the encoding used for such signatures in the rest of the world (most particularly, on ECDSA signatures in X.509 certificates). I think we'll be best served by using one ECDSA signature encoding from here on, but if we need to use the old encoding for backwards compatibility with existing nodes, that can be arranged. * since there's already a breaking change in SignedMessage, I changed it to send and receive public keys in raw PKIX format, instead of PEM. PEM just adds unhelpful overhead for this case.
80 lines
1.8 KiB
Go
80 lines
1.8 KiB
Go
// Copyright (c) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package identity
|
|
|
|
import (
|
|
"context"
|
|
"crypto"
|
|
|
|
"storj.io/storj/pkg/pkcrypto"
|
|
"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 crypto.PrivateKey, id storj.NodeID, err error) {
|
|
var d uint16
|
|
for {
|
|
err = ctx.Err()
|
|
if err != nil {
|
|
break
|
|
}
|
|
k, err = pkcrypto.GeneratePrivateKey()
|
|
if err != nil {
|
|
break
|
|
}
|
|
id, err = NodeIDFromKey(pkcrypto.PublicKeyFromPrivate(k))
|
|
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(crypto.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
|
|
}
|