Skip to content

Commit

Permalink
added addressing for ecdsa and rsa types
Browse files Browse the repository at this point in the history
fixed default return for private key string, and
added formatting for eth and btc secret types
  • Loading branch information
bunfield authored and firelizzard18 committed Jun 10, 2024
1 parent 795cb2b commit cc703a0
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 33 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ require (
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/bombsimon/wsl/v4 v4.2.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/btcsuitereleases/btcutil v0.0.0-20150612230727-f2b1058a8255 // indirect
github.com/butuzov/mirror v1.1.0 // indirect
github.com/catenacyber/perfsprint v0.7.1 // indirect
Expand Down
7 changes: 6 additions & 1 deletion pkg/build/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,12 @@ func (p *parser) parseKey(key any, typ protocol.SignatureType, private bool) add
(typ == protocol.SignatureTypeED25519 ||
typ == protocol.SignatureTypeLegacyED25519 ||
typ == protocol.SignatureTypeRCD1) {
return address.FromPrivateKeyBytes(key, typ)
k, err := address.FromPrivateKeyBytes(key, typ)
if err != nil {
p.errorf(errors.BadRequest, "unsupported key type %T, %v", key, err)
return &address.Unknown{}
}
return k
}

return &address.PublicKey{
Expand Down
32 changes: 31 additions & 1 deletion pkg/types/address/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ package address

import (
"encoding/hex"
"fmt"

"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/base58"
"github.com/multiformats/go-multibase"
"github.com/multiformats/go-multihash"
Expand Down Expand Up @@ -112,8 +116,28 @@ func (p *PrivateKey) String() string {

case protocol.SignatureTypeRCD1:
return FormatFs(p.Key[:32])

case protocol.SignatureTypeETH:
return hex.EncodeToString(p.Key)

case protocol.SignatureTypeBTCLegacy, protocol.SignatureTypeBTC:
privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), p.Key)

wif, err := btcutil.NewWIF(privKey, &chaincfg.MainNetParams, true)
if err != nil {
return hex.EncodeToString(p.Key)
}
return wif.String()

case protocol.SignatureTypeEcdsaSha256:
return FormatAS2(p.Key)

case protocol.SignatureTypeRsaSha256:
return FormatAS3(p.Key)
}
return p.PublicKey.String()

//as a failsafe, just return the raw hex encoded bytes
return fmt.Sprintf("%X", p.Key)
}

type Lite struct {
Expand Down Expand Up @@ -143,6 +167,12 @@ func formatAddr(typ protocol.SignatureType, hash []byte) string {
case protocol.SignatureTypeETH:
return FormatETH(hash)

case protocol.SignatureTypeEcdsaSha256:
return FormatAC2(hash)

case protocol.SignatureTypeRsaSha256:
return FormatAC3(hash)

case protocol.SignatureTypeReceipt,
protocol.SignatureTypePartition,
protocol.SignatureTypeSet,
Expand Down
117 changes: 111 additions & 6 deletions pkg/types/address/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
package address

import (
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"encoding/hex"
"encoding/pem"
"fmt"
"testing"

Expand Down Expand Up @@ -51,12 +54,24 @@ func TestPublicKeyHash(t *testing.T) {
Type protocol.SignatureType
Format func([]byte) string
}{
"AC": {
"AC1": {
String: "AC12jWw3iqvdCqg11QTLFK9qdgABjknGUnLuX2sLiJMokWcAnqXFk",
Bytes: "e43be90e349210456662d8b8bdc9cc9e5e46ccb07f2129e7b57a8195e5e916d5",
Type: protocol.SignatureTypeED25519,
Format: FormatAC1,
},
"AC2": {
String: "AC2uQ9mAkcToGErGPunmXShG65PWCM9GdwD23LtVAx42WVjtHNsp",
Bytes: "76fa8bb661e3bd0f891d551bc764d35e15286b75903f60ae9fecb6dd75c79f73",
Type: protocol.SignatureTypeEcdsaSha256,
Format: FormatAC2,
},
"AC3": {
String: "AC36QP3SoTKgwfjgfMsqzJk9tGoDFeqMSc67jz1EpH61rGzEUJ7J",
Bytes: "0c44b67095f8fc86576269a542ce9f4fbeac4565d13e8fcb628faaec1368b779",
Type: protocol.SignatureTypeRsaSha256,
Format: FormatAC3,
},
"FA": {
String: "FA3hbVKd8MxyVhTqn7RwoWb2PXTiAbfhEbDSFCmTcmPYuQ8PdRGe",
Bytes: "e43be90e349210456662d8b8bdc9cc9e5e46ccb07f2129e7b57a8195e5e916d5",
Expand Down Expand Up @@ -118,13 +133,27 @@ func TestPrivateKey(t *testing.T) {
Type protocol.SignatureType
Format func([]byte) string
}{
"AS": {
"AS1": {
String: "AS12jWw3iqvdCqg11QTLFK9qdgABjknGUnLuX2sLiJMokWcBq53Ux",
Seed: "e43be90e349210456662d8b8bdc9cc9e5e46ccb07f2129e7b57a8195e5e916d5",
Public: "52813dbcd9e54c8bf504e83b3461355df1f8ed2f2e466c7f30dfd32ce7dbe79e",
Type: protocol.SignatureTypeED25519,
Format: FormatAS1,
},
"AS2": {
String: "AS24M2JMxB4uWnD2hsr16JbMrfJM1MbZsU2AumL9i3Yho9M26wKQpK3gyVATBH59rpK8AjkxMR3hRTmR6VPYWV9ZZDpj7YYs1wDg3QH56wS979TJYoRCbNTSVpwejVttDNQUd9qgMc5T8u5y1fvyXGpEBDPw1BBq6CscnYWwuxDSM4",
Seed: "307702010104205f6190b80e0fdcb89067f827d824cf004540d5dcb6a406efd67a41e97c7c401fa00a06082a8648ce3d030107a14403420004ffcf79dfc28b5e3039657adba9c00219520d54177d9b8c6ec9e0176702305070e2c41b674fc4e5e8951a188b8d6904bbee09d8b4cdd56e5259125b38f39d820f",
Public: "3059301306072a8648ce3d020106082a8648ce3d03010703420004ffcf79dfc28b5e3039657adba9c00219520d54177d9b8c6ec9e0176702305070e2c41b674fc4e5e8951a188b8d6904bbee09d8b4cdd56e5259125b38f39d820f",
Type: protocol.SignatureTypeEcdsaSha256,
Format: FormatAS2,
},
"AS3": {
String: "AS3M5vNQ37taKs7v8wo9e6vop9NGJNwWvQd11uHnSbaJMbdiHJLyCD1p9iHJhRqbg3qtLSvfb8GTWgmh9yCjA2mpe3vpkxpqLEjpNVAAv4e6sYWP8Bwrp4DaQUqyccFiy5oT5CHhXopNtL26QFcS38rUHHY3mzpyPm4jmG1BRwdJWUGr6Q24tMcStaD9W1W9vK7wWwN2TvkwH4Dzcu6xfJcjFnszNQzwvLuSmDRfwC4tWgbN1uL6ajPJCnx6U1k8uaCYkJUyqjv37Q1GydfQ6d9NDuBpZ8YuFNKvRGT8t81zV4B4zqLCK7dLwtmkVX2mVkxe2YKi2M97AJMXTYu7GrhG9hUXLXxKtweXUQbBhELQPqUvGinch4TWuNh7n8RiSrjxuq3eeMSdpAdPLKaseYNfJEwexrk3E57BwLxzWWTBDppYVsZ7e3K1j58nXVdEXc8EeTu5mB5eaCoKaqtGvnVvCLW7a3dYjuBXJ9jqo3Bidb57L2juda6ywrpHCKUbD6BXNSnGeaf3ni8FGVx7omb3q8EDtH68HHE6tfDEgsw3MUAHVj5A37qQ993Ues96WKZqnZDRdbDcLcZiawfpstRQpmNminCtc94PJY3iZxL2SZU8ssjYBkY2tosnwgvucNpen5uaXuFEZcgEtNjF4KoppjW6Ybyfj4GkKaQiKkwbY7CcrwD6bPG8zjPkp1tCAVJ994hceAKDejQB96Lx2apeZ4jpaNeq2zY8QYikGqajigu3Eom3XvgD1zkAUpCVX1pBKRfczwbBg1D6TfbFJ2P48EM8sTxquPJRKueDq1K7WfqrbLPtrUrysFGHTLJcyXBPKSd7",
Seed: "3082025d02010002818100a0037fa2435ff361170a0004f3ff2f8a6005b46e887d54610515a9a59e17b623616e12dcb86c51f1bbd9edcc84b9bb5abc3a5e3d9fda601c5f341b8b1c20a6d6a91d8cf26d1cf58b8d0de8e45db5bf22a7f6b59c248c0ae5305711c60bde3df8ea65752752aa6ed27f00d41350deea394b546c2bd1afc1b56f39c2eeb65ccb8302030100010281802ff01c62ce70868785d1772404bd64cebde9b79e8dc18e6fea880ce51331e35d422929f97a3ee965d4737bac93eed8d45c23d86bf9e2007d3f806ae8082b3810094dffec4202717d48cea3b381aee3132d4ecb5ab0ecb228dfe7961504ceba5b7132ebfdc26d8d77d99e26a31669b852bcfb9b37655b9ad42f201c67983f3cd1024100e366e5de47aaa5c714448c0c0a928bb8cd1b92bbde6108951ff56def6a5f08ec24e4bf293be718a57f00e7ceab9ab11a75e317400c7cbcd535bb5a9e37eee54f024100b42310d18516aecbdfb6de0795ae7179f733ca45bca50ff4ec5cde37a70dfda8e01f74162718a9a1725927e3fd5ef152eb43cc5e1c84d221e339fcabe97dd18d0241008b5bccf57ad00e86415a7cc50859a4bcdd1dcfbfc85988ebf2c8f2d56d47ce6d017319df883168be4b65dfa99d2ad0ec59609128143f016e5c5e73fb5065dc2b024014c2a9d08bd7166416af5b9d6229cd9831de3d24965e2b9d9d94026445937e3575470ab8f6de87c63c887be971acfc8102ee38626c44fe76bb5a567d7596738d024100aac157accbc999755d49820944b2bb65bcf70ad1afe455942a3c81a9b617d50f9eb8f3a1b0553c321fa4024c3fd9c4c7e270bcf0f83a535e245977d507ca8051",
Public: "30818902818100a0037fa2435ff361170a0004f3ff2f8a6005b46e887d54610515a9a59e17b623616e12dcb86c51f1bbd9edcc84b9bb5abc3a5e3d9fda601c5f341b8b1c20a6d6a91d8cf26d1cf58b8d0de8e45db5bf22a7f6b59c248c0ae5305711c60bde3df8ea65752752aa6ed27f00d41350deea394b546c2bd1afc1b56f39c2eeb65ccb830203010001",
Type: protocol.SignatureTypeRsaSha256,
Format: FormatAS3,
},
"Fs": {
String: "Fs342EuYBZJ7TbmZLpN2q1nHVVxsQdtJ8wu3uZxiyVojCvfUGwUg",
Seed: "e43be90e349210456662d8b8bdc9cc9e5e46ccb07f2129e7b57a8195e5e916d5",
Expand All @@ -150,15 +179,91 @@ func TestPrivateKey(t *testing.T) {
addr, err := Parse(c.String)
require.NoError(t, err, "Address must parse")
require.Equal(t, c.Type, addr.GetType(), "Address must have the correct type")
hash, ok := addr.GetPrivateKey()
priv, ok := addr.GetPrivateKey()
require.True(t, ok, "Address must provide a private key")
require.Equal(t, append(seed, public...), hash, "Address must parse correctly")
if c.Type != protocol.SignatureTypeRsaSha256 && c.Type != protocol.SignatureTypeEcdsaSha256 {
require.Equal(t, append(seed, public...), priv, "Address must parse correctly")
} else {
require.Equal(t, seed, priv, "Address must parse correctly")
}
})

t.Run("String", func(t *testing.T) {
addr := &PrivateKey{PublicKey: PublicKey{Type: c.Type, Key: public}, Key: append(seed, public...)}
require.Equal(t, c.String, addr.String(), "Address must format correctly")
if c.Type != protocol.SignatureTypeRsaSha256 && c.Type != protocol.SignatureTypeEcdsaSha256 {
addr := &PrivateKey{PublicKey: PublicKey{Type: c.Type, Key: public}, Key: append(seed, public...)}
require.Equal(t, c.String, addr.String(), "Address must format correctly")
} else {
addr := &PrivateKey{PublicKey: PublicKey{Type: c.Type, Key: public}, Key: seed}
require.Equal(t, c.String, addr.String(), "Address must format correctly")
}
})
})
}
}

func TestFormatWif(t *testing.T) {
//BITCOIN Wallet Import Format (WIF), all keys start with 5, K, or L
wif := "L3qjEroY5veLKTaeRdhuXScuYcXYy3CaSqeQVfvDmZKV5kRDuLWv"
raw := "c58db2514ae2079d456b586223242c5f61c73a5a2406dd2946ed76e06422292e"

privateKey, _, err := parseWIF(wif)

require.NoError(t, err)

a, err := Parse(wif)
require.NoError(t, err)

rawa, _ := a.GetPrivateKey()
require.Equal(t, hex.EncodeToString(rawa), raw)
pk, err := FromPrivateKeyBytes(privateKey, protocol.SignatureTypeBTC)
require.NoError(t, err)

require.Equal(t, a.String(), pk.String())

}

const rsaPrivateKey1024 = `-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCgA3+iQ1/zYRcKAATz/y+KYAW0boh9VGEFFamlnhe2I2FuEty4
bFHxu9ntzIS5u1q8Ol49n9pgHF80G4scIKbWqR2M8m0c9YuNDejkXbW/Iqf2tZwk
jArlMFcRxgvePfjqZXUnUqpu0n8A1BNQ3uo5S1RsK9GvwbVvOcLutlzLgwIDAQAB
AoGAL/AcYs5whoeF0XckBL1kzr3pt56NwY5v6ogM5RMx411CKSn5ej7pZdRze6yT
7tjUXCPYa/niAH0/gGroCCs4EAlN/+xCAnF9SM6js4Gu4xMtTstasOyyKN/nlhUE
zrpbcTLr/cJtjXfZniajFmm4Urz7mzdlW5rULyAcZ5g/PNECQQDjZuXeR6qlxxRE
jAwKkou4zRuSu95hCJUf9W3val8I7CTkvyk75xilfwDnzquasRp14xdADHy81TW7
Wp437uVPAkEAtCMQ0YUWrsvftt4Hla5xefczykW8pQ/07FzeN6cN/ajgH3QWJxip
oXJZJ+P9XvFS60PMXhyE0iHjOfyr6X3RjQJBAItbzPV60A6GQVp8xQhZpLzdHc+/
yFmI6/LI8tVtR85tAXMZ34gxaL5LZd+pnSrQ7FlgkSgUPwFuXF5z+1Bl3CsCQBTC
qdCL1xZkFq9bnWIpzZgx3j0kll4rnZ2UAmRFk341dUcKuPbeh8Y8iHvpcaz8gQLu
OGJsRP52u1pWfXWWc40CQQCqwVesy8mZdV1JgglEsrtlvPcK0a/kVZQqPIGpthfV
D56486GwVTwyH6QCTD/ZxMficLzw+DpTXiRZd9UHyoBR
-----END RSA PRIVATE KEY-----`

func TestFormatAC3(t *testing.T) {
t.Skip("Manual")
block, _ := pem.Decode([]byte(rsaPrivateKey1024))

pk, err := FromPrivateKeyBytes(block.Bytes, protocol.SignatureTypeRsaSha256)
require.NoError(t, err)
//AC36QP3SoTKgwfjgfMsqzJk9tGoDFeqMSc67jz1EpH61rGzEUJ7J
t.Logf("seed: %x", block.Bytes)
t.Logf(pk.String())
t.Logf(pk.PublicKey.String())
kh, _ := pk.PublicKey.GetPublicKeyHash()
t.Logf("key hash: %x", kh)
t.Logf("%x", pk.PublicKey.Key)
}

func TestFormatAC2(t *testing.T) {
t.Skip("Manual")
// Generate ECDSA private key
ecdsaPrivKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)

pk := FromEcdsaPrivateKey(ecdsaPrivKey)
t.Logf("seed: %x", pk.Key)
t.Logf(pk.String())
t.Logf(pk.PublicKey.String())
kh, _ := pk.PublicKey.GetPublicKeyHash()
t.Logf("%x", pk.PublicKey.Key)
t.Logf("key hash: %x", kh)
}
26 changes: 24 additions & 2 deletions pkg/types/address/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,38 @@ import (
)

// FormatAC1 formats the hash of an Accumulate public key as an Accumulate AC1
// address.
// address. (ed25519)
func FormatAC1(hash []byte) string {
return format2(hash, "AC1")
}

// FormatAS1 formats an Accumulate private key as an Accumulate AS1 address.
// FormatAS1 formats an Accumulate private key as an Accumulate AS1 address. (ed25519)
func FormatAS1(seed []byte) string {
return format2(seed, "AS1")
}

// FormatAC2 formats the hash of an Accumulate public key as an Accumulate AC2 (ecdsa)
// address.
func FormatAC2(hash []byte) string {
return format2(hash, "AC2")
}

// FormatAS2 formats an Accumulate private key as an Accumulate AS2 ecdsa address.
func FormatAS2(seed []byte) string {
return format2(seed, "AS2")
}

// FormatAC3 formats the hash of an Accumulate public key as an Accumulate AC3 (rsa)
// address.
func FormatAC3(hash []byte) string {
return format2(hash, "AC3")
}

// FormatAS3 formats an Accumulate private key as an Accumulate AS3 rsa address.
func FormatAS3(seed []byte) string {
return format2(seed, "AS3")
}

// FormatFA formats the hash of a Factom public key as a Factom FA address.
func FormatFA(hash []byte) string {
return format1(hash, 0x5f, 0xb1)
Expand Down
27 changes: 16 additions & 11 deletions pkg/types/address/from.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,21 @@ func FromEcdsaPrivateKey(key *ecdsa.PrivateKey) *PrivateKey {
if err != nil {
panic(err)
}
priv.PublicKey.Type = protocol.SignatureTypeEcdsaSha256
priv.PublicKey.Key, err = x509.MarshalPKIXPublicKey(&key.PublicKey)
if err != nil {
panic(err)
}
return priv
}

func FromPrivateKeyBytes(priv []byte, typ protocol.SignatureType) *PrivateKey {
func FromPrivateKeyBytes(priv []byte, typ protocol.SignatureType) (*PrivateKey, error) {
var pub []byte
switch typ {
case protocol.SignatureTypeUnknown:
panic("key type must be specified")
return nil, fmt.Errorf("key type must be specified")
default:
panic(fmt.Errorf("unknown key type %v", typ))
return nil, fmt.Errorf("unknown key type %v", typ)

case protocol.SignatureTypeED25519,
protocol.SignatureTypeLegacyED25519,
Expand All @@ -107,12 +112,12 @@ func FromPrivateKeyBytes(priv []byte, typ protocol.SignatureType) *PrivateKey {
default:
skt, err := x509.ParsePKCS8PrivateKey(priv)
if err != nil {
panic(fmt.Errorf("invalid ed25519 key length: want 32 or 64, got %d", len(priv)))
return nil, fmt.Errorf("invalid ed25519 key length: want 32 or 64, got %d", len(priv))
}
var ok bool
priv, ok = skt.(ed25519.PrivateKey)
if !ok {
panic(fmt.Errorf("private key is not an edcsa key"))
return nil, fmt.Errorf("private key is not an edcsa key")
}
}
pub = priv[32:]
Expand All @@ -131,12 +136,12 @@ func FromPrivateKeyBytes(priv []byte, typ protocol.SignatureType) *PrivateKey {
if err != nil {
skt, err := x509.ParsePKCS8PrivateKey(priv)
if err != nil {
panic(err)
return nil, err
}
var ok bool
sk, ok = skt.(*rsa.PrivateKey)
if !ok {
panic(fmt.Errorf("private key is not an rsa key"))
return nil, fmt.Errorf("private key is not an rsa key")
}
}
pub = x509.MarshalPKCS1PublicKey(&sk.PublicKey)
Expand All @@ -146,19 +151,19 @@ func FromPrivateKeyBytes(priv []byte, typ protocol.SignatureType) *PrivateKey {
if err != nil {
skt, err := x509.ParsePKCS8PrivateKey(priv)
if err != nil {
panic(err)
return nil, err
}
var ok bool
sk, ok = skt.(*ecdsa.PrivateKey)
if !ok {
panic(fmt.Errorf("private key is not an ecdsa key"))
return nil, fmt.Errorf("private key is not an ecdsa key")
}
}
pub, err = x509.MarshalPKIXPublicKey(&sk.PublicKey)
if err != nil {
panic(err)
return nil, err
}
}

return &PrivateKey{Key: priv, PublicKey: PublicKey{Type: typ, Key: pub}}
return &PrivateKey{Key: priv, PublicKey: PublicKey{Type: typ, Key: pub}}, nil
}
Loading

0 comments on commit cc703a0

Please sign in to comment.