added BLS loader

pull/3219/head
Jacky Wang 4 years ago
parent 8057507813
commit 7842d0ea34
No known key found for this signature in database
GPG Key ID: 1085CE5F4FF5842C
  1. 118
      cmd/harmony/blsloader/basicBLSLoader.go
  2. 12
      cmd/harmony/blsloader/cmkblskey.go
  3. 7
      cmd/harmony/blsloader/const.go
  4. 84
      cmd/harmony/blsloader/passprovider.go
  5. 1
      cmd/harmony/main.go
  6. 9
      internal/blsgen/lib.go

@ -0,0 +1,118 @@
package blsloader
import (
"fmt"
"os"
"path/filepath"
"strings"
ffi_bls "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/internal/blsgen"
"github.com/harmony-one/harmony/multibls"
)
// basicBLSLoader is the structure to load bls private keys through a key file
// and passphrase combination.
type basicBLSLoader struct {
// input fields
BLSKeyFile *string // If both BLSKeyFile and blsFolder exists, use BLSKeyFile only
BLSPassFile *string // If both BLSPassFile and BLSDir exists, use BLSPassFile only
BLSDir *string
// variables in process
loadKeyFiles []string
passProvider passProvider
// results
privateKeys multibls.PrivateKey
}
func (loader *basicBLSLoader) loadKeys() (multibls.PrivateKey, error) {
if err := loader.validateInput(); err != nil {
return multibls.PrivateKey{}, err
}
loader.loadPassProvider()
keyFiles, err := loader.getTargetKeyFiles()
if err != nil {
return multibls.PrivateKey{}, err
}
res := multibls.PrivateKey{PrivateKey: make([]*ffi_bls.SecretKey, 0, len(keyFiles))}
for
}
func loadSingleBasicKeyFile(keyFile string, passFile string) {
if passFile == ""
}
func (loader *basicBLSLoader) validateInput() error {
emptyKeyFile := !stringIsSet(loader.BLSKeyFile)
emptyDir := !stringIsSet(loader.BLSDir)
if emptyKeyFile && emptyDir {
return fmt.Errorf("BLS key file or key directory has to be provided")
}
return nil
}
func (loader *basicBLSLoader) loadPassProvider() {
var provider passProvider
if stringIsSet(loader.BLSPassFile) {
provider = &filePassProvider{*loader.BLSPassFile}
} else if stringIsSet(loader.BLSKeyFile) {
provider = &promptPassProvider{}
} else {
provider = multiPassProvider{
&dirPassProvider{*loader.BLSKeyFile},
&promptPassProvider{},
}
}
loader.passProvider = provider
}
func (loader *basicBLSLoader) getTargetKeyFiles() ([]string, error) {
if loader.BLSKeyFile != nil && *loader.BLSKeyFile != "" {
return []string{*loader.BLSKeyFile}, nil
}
return loader.getKeyFilesFromDir(*loader.BLSDir)
}
func (loader *basicBLSLoader) getKeyFilesFromDir(dir string) ([]string, error) {
var keyFilePaths []string
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if isBasicKeyFile(info) {
keyFilePaths = append(keyFilePaths, path)
}
return nil
})
if err != nil {
return nil, err
}
return keyFilePaths, nil
}
func stringIsSet(val *string) bool {
return val != nil && *val != ""
}
// isBasicKeyFile return whether the given file is a bls file
func isBasicKeyFile(info os.FileInfo) bool {
if info.IsDir() {
return false
}
if !strings.HasSuffix(info.Name(), basicKeyExt) {
return false
}
return true
}
func loadBasicKey(keyStr string, keyFile string, provider passProvider) (*ffi_bls.SecretKey, error) {
pass, err := provider.getPassphrase(keyStr)
if err != nil {
return nil, err
}
return blsgen.LoadBLSKeyWithPassPhrase(keyFile, pass)
}

@ -0,0 +1,12 @@
package blsloader
import (
"sync"
"github.com/aws/aws-sdk-go/service/kms"
)
var (
kmsClient *kms.KMS
kmsInitOnce sync.Once
)

@ -0,0 +1,7 @@
package blsloader
const (
passExt = ".pass"
basicKeyExt = ".key"
kmsKeyExt = ".bls"
)

@ -0,0 +1,84 @@
package blsloader
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"syscall"
"golang.org/x/crypto/ssh/terminal"
)
// passProvider is the interface to provide the passphrase of a bls keys.
// Implemented by
// emptyPassProvider - provide empty passphrase
// promptPassProvider - provide passphrase through user-interactive prompt
// filePassProvider - provide passphrase from a .pass file
// dirPassProvider - provide passphrase from .pass files in a directory
// multiPassProvider - multiple passProviders that will provide the passphrase.
type passProvider interface {
getPassphrase(blsPubStr string) (string, error)
}
// promptPassProvider provides the bls password through console prompt.
type promptPassProvider struct{}
const pwdPromptStr = "Enter passphrase for the BLS key file %s:"
func (provider *promptPassProvider) getPassphrase(blsPubStr string) (string, error) {
fmt.Printf(pwdPromptStr, blsPubStr)
hexBytes, err := terminal.ReadPassword(syscall.Stdin)
if err != nil {
return "", err
}
return string(hexBytes), nil
}
// filePassProvider provide the bls password from the single bls pass file
type filePassProvider struct {
file string
}
func (provider *filePassProvider) getPassphrase(blsPubStr string) (string, error) {
return readPassFromFile(provider.file)
}
func readPassFromFile(file string) (string, error) {
f, err := os.Open(file)
if err != nil {
return "", fmt.Errorf("cannot open passphrase file: [%s]", file)
}
defer f.Close()
b, err := ioutil.ReadAll(f)
if err != nil {
return "", err
}
return string(b), nil
}
// dirPassProvider provide the all bls password available in the directory.
type dirPassProvider struct {
dirPath string
}
func (provider *dirPassProvider) getPassphrase(blsPubStr string) (string, error) {
file := filepath.Join(provider.dirPath, blsPubStr+passExt)
return readPassFromFile(file)
}
// multiPassProvider is a slice of passProviders to provide the passphrase
// of the given bls key. If a passProvider fails, will continue to the next provider.
type multiPassProvider []passProvider
func (provider multiPassProvider) getPassphrase(blsPubStr string) (string, error) {
for _, pp := range provider {
pass, err := pp.getPassphrase(blsPubStr)
if err != nil {
continue
}
return pass, err
}
return "", fmt.Errorf("cannot get passphrase for %s", blsPubStr)
}

@ -177,6 +177,7 @@ func passphraseForBLS() {
fmt.Println("Internal nodes need to have blspass to decrypt blskey")
os.Exit(101)
}
fmt.Println(*blsPass)
passphrase, err := utils.GetPassphraseFromSource(*blsPass)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "ERROR when reading passphrase file: %v\n", err)

@ -11,6 +11,7 @@ import (
"io"
"io/ioutil"
"os"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
@ -84,9 +85,8 @@ func LoadBLSKeyWithPassPhrase(fileName, passphrase string) (*ffi_bls.SecretKey,
if err != nil {
return nil, errors.Wrapf(err, "attemped to load from %s", fileName)
}
for len(passphrase) > 0 && passphrase[len(passphrase)-1] == '\n' {
passphrase = passphrase[:len(passphrase)-1]
}
passphrase = strings.TrimSpace(passphrase)
decryptedBytes, err := decrypt(encryptedPrivateKeyBytes, passphrase)
if err != nil {
return nil, err
@ -129,6 +129,7 @@ func Readln(timeout time.Duration) (string, error) {
}
// LoadAwsCMKEncryptedBLSKey loads aws encrypted bls key.
// TODO(Jacky): Determine whether to remove the awsSettingString
func LoadAwsCMKEncryptedBLSKey(fileName, awsSettingString string) (*ffi_bls.SecretKey, error) {
if awsSettingString == "" {
return nil, errors.New("aws credential is not set")
@ -139,7 +140,7 @@ func LoadAwsCMKEncryptedBLSKey(fileName, awsSettingString string) (*ffi_bls.Secr
return nil, errors.New(awsSettingString + " is not a valid JSON string for setting aws configuration.")
}
// Initialize a session that the aws SDK uses to load
// Initialize a session that the aws SDK uses to loLoadAwsCMKEncryptedBLSKeyad
sess, err := session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
})

Loading…
Cancel
Save