diff --git a/README.md b/README.md index 2fa03b6..de6b3de 100644 --- a/README.md +++ b/README.md @@ -60,3 +60,16 @@ wif, err := crypto.WIFEncode(sk) // if something went wrong, returns error: skFromWIF, err := crypto.WIFDecode(wif) ``` + +### LoadPrivateKey + +``` +// Load private key from wif format +sk, err := crypto.LoadPrivateKey(wif_string) + +// Load private key from hex string +sk, err := crypto.LoadPrivateKey(hex_string) + +// Load private key from file +sk, err := crypto.LoadPrivateKey(file_path) +``` diff --git a/load.go b/load.go new file mode 100644 index 0000000..7c61277 --- /dev/null +++ b/load.go @@ -0,0 +1,25 @@ +package crypto + +import ( + "crypto/ecdsa" + "encoding/hex" + "io/ioutil" + + "github.com/pkg/errors" +) + +// LoadPrivateKey allows to load private key from various formats: +// - wif string +// - hex string +// - file path (D-bytes or SEC 1 / ASN.1 DER form) +func LoadPrivateKey(val string) (*ecdsa.PrivateKey, error) { + if data, err := ioutil.ReadFile(val); err == nil { + return UnmarshalPrivateKey(data) + } else if data, err = hex.DecodeString(val); err == nil { + return UnmarshalPrivateKey(data) + } else if key, err := WIFDecode(val); err == nil { + return key, nil + } + + return nil, errors.Errorf("unknown key format (%q), expect: hex-string, wif or file-path", val) +} diff --git a/load_test.go b/load_test.go new file mode 100644 index 0000000..b7c3fd4 --- /dev/null +++ b/load_test.go @@ -0,0 +1,86 @@ +package crypto + +import ( + "crypto/x509" + "encoding/hex" + "io/ioutil" + "os" + "testing" + + "github.com/nspcc-dev/neofs-crypto/test" + "github.com/stretchr/testify/require" +) + +func Test_LoadPrivateKey_FromWIF(t *testing.T) { + for i := 0; i < 10; i++ { + expected := test.DecodeKey(i) + + wif, err := WIFEncode(expected) + require.NoError(t, err) + + actual, err := LoadPrivateKey(wif) + require.NoError(t, err) + + require.Equal(t, expected, actual) + } +} + +func Test_LoadPrivateKey_FromHexString(t *testing.T) { + for i := 0; i < 10; i++ { + expected := test.DecodeKey(i) + + hs := hex.EncodeToString(expected.D.Bytes()) + + actual, err := LoadPrivateKey(hs) + require.NoError(t, err) + + require.Equal(t, expected, actual) + } +} + +func Test_LoadPrivateKey_FromFile(t *testing.T) { + for i := 0; i < 10; i++ { + expected := test.DecodeKey(i) + + file, err := ioutil.TempFile("", "_marshaled.key") + require.NoError(t, err) + + defer func() { + require.NoError(t, file.Close()) + require.NoError(t, os.Remove(file.Name())) + }() + + data, err := x509.MarshalECPrivateKey(expected) + require.NoError(t, err) + + _, err = file.Write(data) + require.NoError(t, err) + + actual, err := LoadPrivateKey(file.Name()) + require.NoError(t, err) + + require.Equal(t, expected, actual) + } +} + +func Test_LoadPrivateKey_FromCompressedFormatFile(t *testing.T) { + for i := 0; i < 10; i++ { + expected := test.DecodeKey(i) + + file, err := ioutil.TempFile("", "_compressed.key") + require.NoError(t, err) + + defer func() { + require.NoError(t, file.Close()) + require.NoError(t, os.Remove(file.Name())) + }() + + _, err = file.Write(expected.D.Bytes()) + require.NoError(t, err) + + actual, err := LoadPrivateKey(file.Name()) + require.NoError(t, err) + + require.Equal(t, expected, actual) + } +}