Skip to content

Commit

Permalink
Make ToAIP80 return error, fix bytes parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
GhostWalker562 committed Nov 20, 2024
1 parent 682ec6b commit c906687
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 42 deletions.
18 changes: 7 additions & 11 deletions crypto/ed25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,13 @@ func (key *Ed25519PrivateKey) Bytes() []byte {
// Implements:
// - [CryptoMaterial]
func (key *Ed25519PrivateKey) FromBytes(bytes []byte) (err error) {
bytes, err = ParsePrivateKey(bytes, PrivateKeyVariant("ed25519"), false)
if len(bytes) != ed25519.SeedSize {
return fmt.Errorf("invalid ed25519 private key size %d", len(bytes))
}
bytes, err = ParsePrivateKey(bytes, PrivateKeyVariantEd25519, false)
if err != nil {
return err
}
if len(bytes) != ed25519.SeedSize {
return fmt.Errorf("invalid ed25519 private key size %d", len(bytes))
}
key.Inner = ed25519.NewKeyFromSeed(bytes)
return nil
}
Expand All @@ -172,12 +172,8 @@ func (key *Ed25519PrivateKey) ToHex() string {
}

// ToAIP80 formats the private key to AIP-80 compliant string
func (key *Ed25519PrivateKey) ToAIP80() string {
var res, err = FormatPrivateKey(key.ToHex(), PrivateKeyVariant("ed25519"))
if err != nil {
panic(err)
}
return res
func (key *Ed25519PrivateKey) ToAIP80() (formattedString string, err error) {
return FormatPrivateKey(key.ToHex(), PrivateKeyVariantEd25519)
}

// FromHex sets the [Ed25519PrivateKey] to the bytes represented by the hex string, with or without a leading 0x
Expand All @@ -187,7 +183,7 @@ func (key *Ed25519PrivateKey) ToAIP80() string {
// Implements:
// - [CryptoMaterial]
func (key *Ed25519PrivateKey) FromHex(hexStr string) (err error) {
bytes, err := ParsePrivateKey(hexStr, PrivateKeyVariant("ed25519"))
bytes, err := ParsePrivateKey(hexStr, PrivateKeyVariantEd25519)
if err != nil {
return err
}
Expand Down
7 changes: 5 additions & 2 deletions crypto/ed25519_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package crypto

import (
"crypto/ed25519"
"testing"

"github.com/aptos-labs/aptos-go-sdk/bcs"
"github.com/aptos-labs/aptos-go-sdk/internal/util"
"github.com/stretchr/testify/assert"
"testing"
)

const testEd25519PrivateKey = "ed25519-priv-0xc5338cd251c22daa8c9c9cc94f498cc8a5c7e1d2e75287a5dda91096fe64efa5"
Expand Down Expand Up @@ -35,7 +36,9 @@ func TestEd25519Keys(t *testing.T) {
// The outputs should match as well
assert.Equal(t, privateKey.Bytes(), testEd25519PrivateKeyBytes)
assert.Equal(t, privateKey.ToHex(), testEd25519PrivateKeyHex)
assert.Equal(t, privateKey.ToAIP80(), testEd25519PrivateKey)
formattedString, err := privateKey.ToAIP80()
assert.NoError(t, err)
assert.Equal(t, formattedString, testEd25519PrivateKey)

// Auth key should match
assert.Equal(t, testEd25519Address, privateKey.AuthKey().ToHex())
Expand Down
29 changes: 12 additions & 17 deletions crypto/privateKey.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,29 @@ import (
type PrivateKeyVariant string

const (
Ed25519 PrivateKeyVariant = "ed25519"
Secp256k1 PrivateKeyVariant = "secp256k1"
PrivateKeyVariantEd25519 PrivateKeyVariant = "ed25519"
PrivateKeyVariantSecp256k1 PrivateKeyVariant = "secp256k1"
)

// AIP80Prefixes contains the AIP-80 compliant prefixes for each private key type
var AIP80Prefixes = map[PrivateKeyVariant]string{
Ed25519: "ed25519-priv-",
Secp256k1: "secp256k1-priv-",
PrivateKeyVariantEd25519: "ed25519-priv-",
PrivateKeyVariantSecp256k1: "secp256k1-priv-",
}

// FormatPrivateKey formats a hex input to an AIP-80 compliant string
func FormatPrivateKey(privateKey interface{}, keyType PrivateKeyVariant) (string, error) {
func FormatPrivateKey(privateKey any, keyType PrivateKeyVariant) (formattedString string, err error) {
aip80Prefix := AIP80Prefixes[keyType]

var hexStr string
switch v := privateKey.(type) {
case string:
// Remove the prefix if it exists
if strings.HasPrefix(v, aip80Prefix) {
parts := strings.Split(v, "-")
v = parts[2]
}

// If it's already a string, just ensure it's properly formatted
var strBytes, err = util.ParseHex(v)
if err != nil {
Expand All @@ -48,7 +54,7 @@ func FormatPrivateKey(privateKey interface{}, keyType PrivateKeyVariant) (string
// ParseHexInput parses a hex input that may be bytes, hex string, or an AIP-80 compliant string to bytes.
//
// You may optionally pass in a boolean to strictly enforce AIP-80 compliance.
func ParsePrivateKey(value interface{}, keyType PrivateKeyVariant, strict ...bool) ([]byte, error) {
func ParsePrivateKey(value any, keyType PrivateKeyVariant, strict ...bool) (bytes []byte, err error) {
aip80Prefix := AIP80Prefixes[keyType]

// Get the first boolean if it exists, otherwise nil
Expand Down Expand Up @@ -80,17 +86,6 @@ func ParsePrivateKey(value interface{}, keyType PrivateKeyVariant, strict ...boo
}
return nil, fmt.Errorf("invalid hex string input while parsing private key. Must be AIP-80 compliant string")
case []byte:
// If strictness is not explicitly false, warn about non-AIP-80 compliance
if strictness == nil {
fmt.Printf("[Aptos SDK] It is recommended that private keys are parsed as AIP-80 compliant strings " +
"instead of byte arrays (https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-80.md). " +
"You can fix the private key by formatting it with crypto.FormatPrivateKey")
}

if strictness != nil && *strictness {
return nil, fmt.Errorf("invalid private key bytes while parsing private key. Must be AIP-80 compliant string")
}

return v, nil
default:
return nil, fmt.Errorf("unsupported private key type: must be string or []byte")
Expand Down
19 changes: 8 additions & 11 deletions crypto/secp256k1.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func (key *Secp256k1PrivateKey) SignMessage(msg []byte) (sig Signature, err erro
//region Secp256k1PrivateKey CryptoMaterial

// Bytes outputs the raw byte representation of the [Secp256k1PrivateKey]
//
// Implements:
// - [CryptoMaterial]
func (key *Secp256k1PrivateKey) Bytes() []byte {
Expand All @@ -98,13 +99,13 @@ func (key *Secp256k1PrivateKey) Bytes() []byte {
// Implements:
// - [CryptoMaterial]
func (key *Secp256k1PrivateKey) FromBytes(bytes []byte) (err error) {
bytes, err = ParsePrivateKey(bytes, PrivateKeyVariant("secp256k1"), false)
if len(bytes) != Secp256k1PrivateKeyLength {
return fmt.Errorf("invalid secp256k1 private key size %d", len(bytes))
}
bytes, err = ParsePrivateKey(bytes, PrivateKeyVariantSecp256k1, false)
if err != nil {
return err
}
if len(bytes) != Secp256k1PrivateKeyLength {
return fmt.Errorf("invalid secp256k1 private key size %d", len(bytes))
}
newKey, err := ethCrypto.ToECDSA(bytes)
if err != nil {
return err
Expand All @@ -122,12 +123,8 @@ func (key *Secp256k1PrivateKey) ToHex() string {
}

// ToAIP80 formats the private key to AIP-80 compliant string
func (key *Secp256k1PrivateKey) ToAIP80() string {
var res, err = FormatPrivateKey(key.ToHex(), PrivateKeyVariant("secp256k1"))
if err != nil {
panic(err)
}
return res
func (key *Secp256k1PrivateKey) ToAIP80() (formattedString string, err error) {
return FormatPrivateKey(key.ToHex(), PrivateKeyVariantSecp256k1)
}

//endregion
Expand All @@ -139,7 +136,7 @@ func (key *Secp256k1PrivateKey) ToAIP80() string {
// Implements:
// - [CryptoMaterial]
func (key *Secp256k1PrivateKey) FromHex(hexStr string) (err error) {
bytes, err := ParsePrivateKey(hexStr, PrivateKeyVariant("secp256k1"))
bytes, err := ParsePrivateKey(hexStr, PrivateKeyVariantSecp256k1)
if err != nil {
return err
}
Expand Down
4 changes: 3 additions & 1 deletion crypto/secp256k1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ func TestSecp256k1Keys(t *testing.T) {
// The outputs should match as well
assert.Equal(t, privateKey.Bytes(), testSecp256k1PrivateKeyBytes)
assert.Equal(t, privateKey.ToHex(), testSecp256k1PrivateKeyHex)
assert.Equal(t, privateKey.ToAIP80(), testSecp256k1PrivateKey)
formattedString, err := privateKey.ToAIP80()
assert.NoError(t, err)
assert.Equal(t, formattedString, testSecp256k1PrivateKey)


// Auth key should match
Expand Down

0 comments on commit c906687

Please sign in to comment.