1// Copyright (c) 2019 Storj Labs, Inc. 2// See LICENSE for copying information. 3 4package identity 5 6import ( 7 "context" 8 "crypto" 9 10 "storj.io/common/pkcrypto" 11 "storj.io/common/storj" 12) 13 14// GenerateKey generates a private key with a node id with difficulty at least 15// minDifficulty. No parallelism is used. 16func GenerateKey(ctx context.Context, minDifficulty uint16, version storj.IDVersion) ( 17 k crypto.PrivateKey, id storj.NodeID, err error) { 18 defer mon.Task()(&ctx)(&err) 19 20 var d uint16 21 for { 22 err = ctx.Err() 23 if err != nil { 24 break 25 } 26 k, err = version.NewPrivateKey() 27 if err != nil { 28 break 29 } 30 31 var pubKey crypto.PublicKey 32 pubKey, err = pkcrypto.PublicKeyFromPrivate(k) 33 if err != nil { 34 break 35 } 36 37 id, err = NodeIDFromKey(pubKey, version) 38 if err != nil { 39 break 40 } 41 d, err = id.Difficulty() 42 if err != nil { 43 break 44 } 45 if d >= minDifficulty { 46 return k, id, nil 47 } 48 } 49 return k, id, storj.ErrNodeID.Wrap(err) 50} 51 52// GenerateCallback indicates that key generation is done when done is true. 53// if err != nil key generation will stop with that error. 54type GenerateCallback func(crypto.PrivateKey, storj.NodeID) (done bool, err error) 55 56// GenerateKeys continues to generate keys until found returns done == false, 57// or the ctx is canceled. 58func GenerateKeys(ctx context.Context, minDifficulty uint16, concurrency int, version storj.IDVersion, found GenerateCallback) (err error) { 59 defer mon.Task()(&ctx)(&err) 60 ctx, cancel := context.WithCancel(ctx) 61 defer cancel() 62 errchan := make(chan error, concurrency) 63 64 for i := 0; i < concurrency; i++ { 65 go func() { 66 for { 67 k, id, err := GenerateKey(ctx, minDifficulty, version) 68 if err != nil { 69 errchan <- err 70 return 71 } 72 73 done, err := found(k, id) 74 if err != nil { 75 errchan <- err 76 return 77 } 78 if done { 79 errchan <- nil 80 return 81 } 82 } 83 }() 84 } 85 86 // we only care about the first error. the rest of the errors will be 87 // context cancellation errors 88 return <-errchan 89} 90