Skip to content
This repository has been archived by the owner on Dec 7, 2019. It is now read-only.

Commit

Permalink
change how we calculate inline peer IDs.
Browse files Browse the repository at this point in the history
Instead of trying to get fancy with multicodecs and such, just inline the public
key's protobuf.

Eventually, we can try to switch to true IPLD but this is, IMO, a step in the
right direction.
  • Loading branch information
Stebalien committed Feb 8, 2018
1 parent a3c79eb commit 583ec80
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 122 deletions.
6 changes: 0 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@
"name": "go-multihash",
"version": "1.0.7"
},
{
"author": "whyrusleeping",
"hash": "QmNhVCV7kgAqW6oh6n8m9myxT2ksGPhVZnHkzkBvR5qg2d",
"name": "go-multicodec-packed",
"version": "0.1.0"
},
{
"author": "mr-tron",
"hash": "QmWFAMPqsEyUX7gDUsRVmMWz59FxSpJ1b2v6bJ1yYzo7jY",
Expand Down
100 changes: 14 additions & 86 deletions peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
package peer

import (
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"strings"

logging "github.com/ipfs/go-log" // ID represents the identity of a peer.
ic "github.com/libp2p/go-libp2p-crypto"
b58 "github.com/mr-tron/base58/base58"
mc "github.com/multiformats/go-multicodec-packed"
mh "github.com/multiformats/go-multihash"
)

Expand Down Expand Up @@ -66,77 +63,23 @@ func (id ID) MatchesPublicKey(pk ic.PubKey) bool {
return oid == id
}

var MultihashDecodeErr = errors.New("unable to decode multihash")
var MultihashCodecErr = errors.New("unexpected multihash codec")
var MultihashLengthErr = errors.New("unexpected multihash length")
var CodePrefixErr = errors.New("unexpected code prefix")

func (id ID) ExtractEd25519PublicKey() (ic.PubKey, error) {
// ed25519 pubkey identity format
// <identity mc><length (2 + 32 = 34)><ed25519-pub mc><ed25519 pubkey>
// <0x00 ><0x22 ><0xed01 ><ed25519 pubkey>

var nilPubKey ic.PubKey

// Decode multihash
// ExtractPublicKey attempts to extract the public key from an ID
//
// This method returns nil, nil if the peer ID looks valid but it can't extract
// the public key.
func (id ID) ExtractPublicKey() (ic.PubKey, error) {
decoded, err := mh.Decode([]byte(id))
if err != nil {
return nilPubKey, MultihashDecodeErr
return nil, err
}

// Check ID multihash codec
if decoded.Code != mh.ID {
return nilPubKey, MultihashCodecErr
}

// Check multihash length
if decoded.Length != 2+32 {
return nilPubKey, MultihashLengthErr
}

// Split prefix
code, pubKeyBytes := mc.SplitPrefix(decoded.Digest)

// Check ed25519 code
if code != mc.Ed25519Pub {
return nilPubKey, CodePrefixErr
}

// Unmarshall public key
pubKey, err := ic.UnmarshalEd25519PublicKey(pubKeyBytes)
if err != nil {
// Should never occur because of the check decoded.Length != 2+32
return nilPubKey, fmt.Errorf("Unexpected error unmarshalling Ed25519 public key")
}

return pubKey, nil
}

// ExtractPublicKey attempts to extract the public key from an ID
func (id ID) ExtractPublicKey() ic.PubKey {
var pk ic.PubKey

// Try extract ed25519 pubkey
pk, err := id.ExtractEd25519PublicKey()
if err != nil {
log.Info(err, id)
return nil, nil
}

if pk != nil {
return pk
}

// Try extract other type of pubkey
/*pk, err = id.Extract...PublicKey()
pk, err := ic.UnmarshalPublicKey(decoded.Digest)
if err != nil {
log.Error(err, id)
return nil, err
}
if pk != nil {
return pk
}*/

return pk
return pk, nil
}

// IDFromString cast a string to ID type, and validate
Expand Down Expand Up @@ -191,26 +134,11 @@ func IDFromPublicKey(pk ic.PubKey) (ID, error) {
if err != nil {
return "", err
}
hash, _ := mh.Sum(b, mh.SHA2_256, -1)
return ID(hash), nil
}

// IDFromEd25519PublicKey returns the Peer ID corresponding to Id25519 pk
func IDFromEd25519PublicKey(pk ic.PubKey) (ID, error) {
b, err := pk.Bytes()
if err != nil {
return "", err
var alg uint64 = mh.SHA2_256
if len(b) <= 40 {
alg = mh.ID
}

// Build the ed25519 public key multi-codec
Ed25519PubMultiCodec := make([]byte, 2)
binary.PutUvarint(Ed25519PubMultiCodec, uint64(mc.Ed25519Pub))

hash, err := mh.Sum(append(Ed25519PubMultiCodec, b[len(b)-32:]...), mh.ID, 34)
if err != nil {
return "", err
}

hash, _ := mh.Sum(b, alg, -1)
return ID(hash), nil
}

Expand Down
56 changes: 26 additions & 30 deletions peer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,51 +160,47 @@ func TestPublicKeyExtraction(t *testing.T) {
t.Fatal(err)
}

id, err := IDFromEd25519PublicKey(originalPub)
id, err := IDFromPublicKey(originalPub)
if err != nil {
t.Fatal(err)
}

extractedPub := id.ExtractPublicKey()
if !originalPub.Equals(extractedPub) {
extractedPub, err := id.ExtractPublicKey()
if err != nil {
t.Fatal(err)
}
if extractedPub == nil {
t.Fatal("failed to extract public key")
}
if !originalPub.Equals(extractedPub) {
t.Fatal("extracted public key doesn't match")
}

// Test invalid multihash (invariant of the type of public key)
if ID("").ExtractPublicKey() != nil {
t.Fatal("Expecting a nil public key")
pk, err := ID("").ExtractPublicKey()
if err == nil {
t.Fatal("expected an error")
}
if pk != nil {
t.Fatal("expected a nil public key")
}
}

func TestEd25519PublicKeyExtraction(t *testing.T) {
randomKey := make([]byte, 32)
_, err := rand.Read(randomKey)
// Shouldn't work for, e.g. RSA keys (too large)

_, rsaPub, err := ic.GenerateKeyPair(ic.RSA, 2048)
if err != nil {
t.Fatal(err)
}

// Error case 1: Invalid multihash
_, err = ID("").ExtractEd25519PublicKey()
if err != MultihashDecodeErr {
t.Fatal("Error case 1: Expected an error")
}

// Error case 2: Non-ID multihash
_, err = ID(append([]byte{0x01 /* != 0x00 (id) */, 0x22, 0xed, 0x01}, randomKey...)).ExtractEd25519PublicKey()
if err != MultihashCodecErr {
t.Fatal("Error case 2: Expecting an error")
rsaId, err := IDFromPublicKey(rsaPub)
if err != nil {
t.Fatal(err)
}

// Error case 3: Non-34 multihash length
_, err = ID(append([]byte{0x00, 0x23 /* 35 = 34 + 1 != 35 */, 0xed, 0x01, 0x00 /* extra byte */}, randomKey...)).ExtractEd25519PublicKey()
if err != MultihashLengthErr {
t.Fatal("Error case 3: Expecting an error")
extractedRsaPub, err := rsaId.ExtractPublicKey()
if err != nil {
t.Fatal(err)
}

// Error case 4: Non-ed25519 code
_, err = ID(append([]byte{0x00, 0x22, 0xef /* != 0xed */, 0x01}, randomKey...)).ExtractEd25519PublicKey()
if err != CodePrefixErr {
t.Fatal("Error case 4: Expecting an error")
if extractedRsaPub != nil {
t.Fatal("expected to fail to extract public key from rsa ID")
}
}

Expand Down

0 comments on commit 583ec80

Please sign in to comment.