Skip to content

Commit

Permalink
chore: project layout improve
Browse files Browse the repository at this point in the history
  • Loading branch information
igor-sirotin committed Jan 20, 2025
1 parent 254ffc7 commit 6f1e4b2
Show file tree
Hide file tree
Showing 22 changed files with 353 additions and 307 deletions.
20 changes: 20 additions & 0 deletions internal/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package internal

const (
MaxPINRetries = 3
MaxPUKRetries = 5
MaxFreeSlots = 5
DefMnemoLen = 12
DefPINLen = 6
DefPUKLen = 12
DefPairing = "KeycardDefaultPairing"
)

const (
MasterPath = "m"
WalletRoothPath = "m/44'/60'/0'/0"
WalletPath = WalletRoothPath + "/0"
Eip1581Path = "m/43'/60'/1581'"
WhisperPath = Eip1581Path + "/0'/0"
EncryptionPath = Eip1581Path + "/1'/0"
)
11 changes: 10 additions & 1 deletion internal/keycard_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type KeycardContext struct {
runErr error
}

// Transmit implements the Channel and Transmitter interfaces
func (kc *KeycardContext) Transmit(apdu []byte) ([]byte, error) {
kc.apdu = apdu
kc.command <- Transmit
Expand Down Expand Up @@ -366,8 +367,16 @@ func (kc *KeycardContext) loadSeed(seed []byte) ([]byte, error) {
return pubKey, nil
}

func (kc *KeycardContext) mnemonicToBinarySeed(mnemonic string, password string) []byte {
return pbkdf2.Key(
norm.NFKD.Bytes([]byte(mnemonic)),
norm.NFKD.Bytes([]byte(bip39Salt+password)),
2048, 64, sha512.New,
)
}

func (kc *KeycardContext) LoadMnemonic(mnemonic string, password string) ([]byte, error) {
seed := pbkdf2.Key(norm.NFKD.Bytes([]byte(mnemonic)), norm.NFKD.Bytes([]byte(bip39Salt+password)), 2048, 64, sha512.New)
seed := kc.mnemonicToBinarySeed(mnemonic, password)
return kc.loadSeed(seed)
}

Expand Down
61 changes: 16 additions & 45 deletions internal/types.go
Original file line number Diff line number Diff line change
@@ -1,65 +1,36 @@
package internal

import (
"encoding/json"
"github.com/status-im/status-keycard-go/pkg/utils"
)

type HexString []byte

// MarshalJSON serializes HexString to hex
func (s HexString) MarshalJSON() ([]byte, error) {
bytes, err := json.Marshal(Btox(s))
return bytes, err
}

// UnmarshalJSON deserializes HexString to hex
func (s *HexString) UnmarshalJSON(data []byte) error {
var x string
err := json.Unmarshal(data, &x)
if err != nil {
return err
}
str, err := Xtob(x)
if err != nil {
return err
}

*s = HexString([]byte(str))
return nil
}

type Signature struct {
R HexString `json:"r"`
S HexString `json:"s"`
V byte `json:"v"`
R utils.HexString `json:"r"`
S utils.HexString `json:"s"`
V byte `json:"v"`
}

type ApplicationInfo struct {
Initialized bool `json:"initialized"`
InstanceUID HexString `json:"instanceUID"`
Version int `json:"version"`
AvailableSlots int `json:"availableSlots"`
Initialized bool `json:"initialized"`
InstanceUID utils.HexString `json:"instanceUID"`
Version int `json:"version"`
AvailableSlots int `json:"availableSlots"`
// KeyUID is the sha256 of the master public key on the card.
// It's empty if the card doesn't contain any key.
KeyUID HexString `json:"keyUID"`
}

type PairingInfo struct {
Key HexString `json:"key"`
Index int `json:"index"`
KeyUID utils.HexString `json:"keyUID"`
}

type KeyPair struct {
Address string `json:"address"`
PublicKey HexString `json:"publicKey"`
PrivateKey HexString `json:"privateKey,omitempty"`
ChainCode HexString `json:"chainCode,omitempty"`
Address string `json:"address"`
PublicKey utils.HexString `json:"publicKey"`
PrivateKey utils.HexString `json:"privateKey,omitempty"`
ChainCode utils.HexString `json:"chainCode,omitempty"`
}

type Wallet struct {
Path string `json:"path"`
Address string `json:"address,omitempty"`
PublicKey HexString `json:"publicKey"`
Path string `json:"path"`
Address string `json:"address,omitempty"`
PublicKey utils.HexString `json:"publicKey"`
}

type Metadata struct {
Expand Down
19 changes: 3 additions & 16 deletions internal/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package internal

import (
"encoding/binary"
"encoding/hex"

"github.com/ebfe/scard"
keycard "github.com/status-im/keycard-go"
Expand All @@ -25,14 +24,6 @@ func GetRetries(err error) (int, bool) {
}
}

func Btox(bytes []byte) string {
return hex.EncodeToString(bytes)
}

func Xtob(str string) ([]byte, error) {
return hex.DecodeString(str)
}

func BytesToInt(s []byte) int {
if len(s) > 4 {
return 0
Expand All @@ -54,6 +45,9 @@ func ContainsString(str string, s []string) bool {
}

func ToAppInfo(r *ktypes.ApplicationInfo) ApplicationInfo {
if r == nil {
return ApplicationInfo{}
}
return ApplicationInfo{
Initialized: r.Initialized,
InstanceUID: r.InstanceUID,
Expand All @@ -63,13 +57,6 @@ func ToAppInfo(r *ktypes.ApplicationInfo) ApplicationInfo {
}
}

func ToPairInfo(r *ktypes.PairingInfo) *PairingInfo {
return &PairingInfo{
Key: r.Key,
Index: r.Index,
}
}

func ToSignature(r *ktypes.Signature) *Signature {
return &Signature{
R: r.R(),
Expand Down
38 changes: 20 additions & 18 deletions pkg/flow/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import (
"io"
"strings"

keycard "github.com/status-im/keycard-go"
"github.com/status-im/keycard-go"
"github.com/status-im/keycard-go/apdu"
"github.com/status-im/keycard-go/derivationpath"
ktypes "github.com/status-im/keycard-go/types"

"github.com/status-im/status-keycard-go/internal"
"github.com/status-im/status-keycard-go/pkg/pairing"
"github.com/status-im/status-keycard-go/pkg/utils"
)

func (f *KeycardFlow) factoryReset(kc *internal.KeycardContext) error {
Expand All @@ -33,8 +35,8 @@ func (f *KeycardFlow) selectKeycard(kc *internal.KeycardContext) error {
return restartErr()
}

f.cardInfo.instanceUID = internal.Btox(appInfo.InstanceUID)
f.cardInfo.keyUID = internal.Btox(appInfo.KeyUID)
f.cardInfo.instanceUID = utils.Btox(appInfo.InstanceUID)
f.cardInfo.keyUID = utils.Btox(appInfo.KeyUID)
f.cardInfo.freeSlots = internal.BytesToInt(appInfo.AvailableSlots)
f.cardInfo.version = internal.BytesToInt(appInfo.Version)

Expand Down Expand Up @@ -65,13 +67,13 @@ func (f *KeycardFlow) pair(kc *internal.KeycardContext) error {
pairingPass, ok := f.params[PairingPass]

if !ok {
pairingPass = DefPairing
pairingPass = internal.DefPairing
}

pairing, err := kc.Pair(pairingPass.(string))
pair, err := kc.Pair(pairingPass.(string))

if err == nil {
return f.pairings.Store(f.cardInfo.instanceUID, internal.ToPairInfo(pairing))
return f.pairings.Store(f.cardInfo.instanceUID, pairing.ToPairInfo(pair))
} else if internal.IsSCardError(err) {
return restartErr()
}
Expand Down Expand Up @@ -111,7 +113,7 @@ func (f *KeycardFlow) initCard(kc *internal.KeycardContext) error {

newPairing, pairingOK := f.params[NewPairing]
if !pairingOK {
newPairing = DefPairing
newPairing = internal.DefPairing
}

err := kc.Init(newPIN.(string), newPUK.(string), newPairing.(string))
Expand Down Expand Up @@ -146,7 +148,7 @@ func (f *KeycardFlow) verifyAuthenticity(kc *internal.KeycardContext) error {
}

func (f *KeycardFlow) openSC(kc *internal.KeycardContext, giveup bool) error {
var pairing *internal.PairingInfo
var pairing *pairing.Info

if !kc.ApplicationInfo().Initialized && !giveup {
return f.initCard(kc)
Expand Down Expand Up @@ -210,8 +212,8 @@ func (f *KeycardFlow) unblockPIN(kc *internal.KeycardContext) error {
err = kc.UnblockPIN(puk.(string), newPIN.(string))

if err == nil {
f.cardInfo.pinRetries = MaxPINRetries
f.cardInfo.pukRetries = MaxPUKRetries
f.cardInfo.pinRetries = internal.MaxPINRetries
f.cardInfo.pukRetries = internal.MaxPUKRetries
f.params[PIN] = newPIN
delete(f.params, NewPIN)
delete(f.params, PUK)
Expand Down Expand Up @@ -256,7 +258,7 @@ func (f *KeycardFlow) authenticate(kc *internal.KeycardContext) error {
err := kc.VerifyPin(pin.(string))

if err == nil {
f.cardInfo.pinRetries = MaxPINRetries
f.cardInfo.pinRetries = internal.MaxPINRetries
return nil
} else if internal.IsSCardError(err) {
return restartErr()
Expand Down Expand Up @@ -368,8 +370,8 @@ func (f *KeycardFlow) storeMetadata(kc *internal.KeycardContext) error {

paths := make([]uint32, len(wallets))
for i, p := range wallets {
if !strings.HasPrefix(p.(string), WalletRoothPath) {
return errors.New("path must start with " + WalletRoothPath)
if !strings.HasPrefix(p.(string), internal.WalletRoothPath) {
return errors.New("path must start with " + internal.WalletRoothPath)
}

_, components, err := derivationpath.Decode(p.(string))
Expand Down Expand Up @@ -406,7 +408,7 @@ func (f *KeycardFlow) exportKey(kc *internal.KeycardContext, path string, onlyPu
}

func (f *KeycardFlow) exportKeyExtended(kc *internal.KeycardContext, path string, p2 uint8) (*internal.KeyPair, error) {
keyPair, err := kc.ExportKey(true, path == MasterPath, p2, path)
keyPair, err := kc.ExportKey(true, path == internal.MasterPath, p2, path)

if internal.IsSCardError(err) {
return nil, restartErr()
Expand Down Expand Up @@ -460,7 +462,7 @@ func (f *KeycardFlow) loadKeys(kc *internal.KeycardContext) error {
return err
}

f.cardInfo.keyUID = internal.Btox(keyUID)
f.cardInfo.keyUID = utils.Btox(keyUID)
return nil
}

Expand All @@ -473,10 +475,10 @@ func (f *KeycardFlow) loadKeys(kc *internal.KeycardContext) error {
case float64:
mnemonicLength = int(t)
default:
mnemonicLength = DefMnemoLen
mnemonicLength = internal.DefMnemoLen
}
} else {
mnemonicLength = DefMnemoLen
mnemonicLength = internal.DefMnemoLen
}

indexes, err := kc.GenerateMnemonic(mnemonicLength / 3)
Expand Down Expand Up @@ -581,7 +583,7 @@ func (f *KeycardFlow) sign(kc *internal.KeycardContext) (*internal.Signature, er
var rawHash []byte

if hashOK {
rawHash, err = internal.Xtob(hash.(string))
rawHash, err = utils.Xtob(hash.(string))
if err != nil {
hashOK = false
}
Expand Down
18 changes: 9 additions & 9 deletions pkg/flow/flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,20 +323,20 @@ func (f *KeycardFlow) exportKeysFlow(kc *internal.KeycardContext, recover bool)

result := FlowStatus{KeyUID: f.cardInfo.keyUID, InstanceUID: f.cardInfo.instanceUID}

key, err := f.exportKey(kc, EncryptionPath, false)
key, err := f.exportKey(kc, internal.EncryptionPath, false)
if err != nil {
return nil, err
}
result[EncKey] = key

key, err = f.exportKey(kc, WhisperPath, false)
key, err = f.exportKey(kc, internal.WhisperPath, false)
if err != nil {
return nil, err
}
result[WhisperKey] = key

if recover {
key, err = f.exportKey(kc, Eip1581Path, true)
key, err = f.exportKey(kc, internal.Eip1581Path, true)
if err != nil {
return nil, err
}
Expand All @@ -350,21 +350,21 @@ func (f *KeycardFlow) exportKeysFlow(kc *internal.KeycardContext, recover bool)
exportP2 = keycard.P2ExportKeyExtendedPublic
}

key, err = f.exportKeyExtended(kc, WalletRoothPath, exportP2)
key, err = f.exportKeyExtended(kc, internal.WalletRoothPath, exportP2)
if err != nil {
return nil, err
}
result[WalleRootKey] = key

//if key.ChainCode == nil {
key, err = f.exportKey(kc, WalletPath, true)
key, err = f.exportKey(kc, internal.WalletPath, true)
if err != nil {
return nil, err
}
result[WalletKey] = key
//}

key, err = f.exportKey(kc, MasterPath, true)
key, err = f.exportKey(kc, internal.MasterPath, true)
if err != nil {
return nil, err
}
Expand All @@ -390,7 +390,7 @@ func (f *KeycardFlow) exportPublicFlow(kc *internal.KeycardContext) (FlowStatus,
result := FlowStatus{KeyUID: f.cardInfo.keyUID, InstanceUID: f.cardInfo.instanceUID}

if exportMaster, ok := f.params[ExportMaster]; ok && exportMaster.(bool) {
masterKey, err := f.exportKey(kc, MasterPath, true)
masterKey, err := f.exportKey(kc, internal.MasterPath, true)
result[MasterAddr] = masterKey.Address

if err != nil {
Expand Down Expand Up @@ -525,7 +525,7 @@ func (f *KeycardFlow) unpairOthersFlow(kc *internal.KeycardContext) (FlowStatus,
return nil, err
}

for i := 0; i < MaxFreeSlots; i++ {
for i := 0; i < internal.MaxFreeSlots; i++ {
if i == kc.PairingInfo().Index {
continue
}
Expand Down Expand Up @@ -604,7 +604,7 @@ func (f *KeycardFlow) getMetadataFlow(kc *internal.KeycardContext) (FlowStatus,
}

if exportMaster, ok := f.params[ExportMaster]; ok && exportMaster.(bool) {
masterKey, err := f.exportKey(kc, MasterPath, true)
masterKey, err := f.exportKey(kc, internal.MasterPath, true)
result[MasterAddr] = masterKey.Address

if err != nil {
Expand Down
Loading

0 comments on commit 6f1e4b2

Please sign in to comment.