Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
go-libp2p
Commits
4f82ae5e
Commit
4f82ae5e
authored
9 years ago
by
Jeromy
Browse files
Options
Download
Email Patches
Plain Diff
move some deps out as gx packages
parent
bd4f4b5b
Changes
84
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
loggables/loggables.go
+0
-69
loggables/loggables.go
p2p/crypto/bench_test.go
+0
-54
p2p/crypto/bench_test.go
p2p/crypto/key.go
+0
-316
p2p/crypto/key.go
p2p/crypto/key_test.go
+0
-122
p2p/crypto/key_test.go
p2p/crypto/pb/Makefile
+0
-10
p2p/crypto/pb/Makefile
p2p/crypto/pb/crypto.pb.go
+0
-104
p2p/crypto/pb/crypto.pb.go
p2p/crypto/pb/crypto.proto
+0
-15
p2p/crypto/pb/crypto.proto
p2p/crypto/rsa.go
+0
-125
p2p/crypto/rsa.go
p2p/crypto/secio/al.go
+0
-115
p2p/crypto/secio/al.go
p2p/crypto/secio/interface.go
+0
-126
p2p/crypto/secio/interface.go
p2p/crypto/secio/io_test.go
+0
-1
p2p/crypto/secio/io_test.go
p2p/crypto/secio/pb/Makefile
+0
-10
p2p/crypto/secio/pb/Makefile
p2p/crypto/secio/pb/spipe.pb.go
+0
-97
p2p/crypto/secio/pb/spipe.pb.go
p2p/crypto/secio/pb/spipe.proto
+0
-14
p2p/crypto/secio/pb/spipe.proto
p2p/crypto/secio/protocol.go
+0
-341
p2p/crypto/secio/protocol.go
p2p/crypto/secio/rw.go
+0
-297
p2p/crypto/secio/rw.go
p2p/discovery/mdns.go
+1
-1
p2p/discovery/mdns.go
p2p/host/basic/basic_host.go
+1
-1
p2p/host/basic/basic_host.go
p2p/host/basic/natmgr.go
+1
-1
p2p/host/basic/natmgr.go
p2p/host/host.go
+1
-1
p2p/host/host.go
with
4 additions
and
1820 deletions
+4
-1820
loggables/loggables.go
deleted
100644 → 0
View file @
bd4f4b5b
// Package loggables includes a bunch of transaltor functions for commonplace/stdlib
// objects. This is boilerplate code that shouldn't change much, and not sprinkled
// all over the place (i.e. gather it here).
//
// Note: it may make sense to put all stdlib Loggable functions in the eventlog
// package. Putting it here for now in case we don't want to polute it.
package
loggables
import
(
"net"
peer
"github.com/ipfs/go-libp2p/p2p/peer"
logging
"gx/ipfs/Qmazh5oNUVsDZTs2g59rq8aYQqwpss8tcUWQzor5sCCEuH/go-log"
ma
"gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr"
)
// NetConn returns an eventlog.Metadata with the conn addresses
func
NetConn
(
c
net
.
Conn
)
logging
.
Loggable
{
return
logging
.
Metadata
{
"localAddr"
:
c
.
LocalAddr
(),
"remoteAddr"
:
c
.
RemoteAddr
(),
}
}
// Error returns an eventlog.Metadata with an error
func
Error
(
e
error
)
logging
.
Loggable
{
return
logging
.
Metadata
{
"error"
:
e
.
Error
(),
}
}
// Dial metadata is metadata for dial events
func
Dial
(
sys
string
,
lid
,
rid
peer
.
ID
,
laddr
,
raddr
ma
.
Multiaddr
)
DeferredMap
{
m
:=
DeferredMap
{}
m
[
"subsystem"
]
=
sys
if
lid
!=
""
{
m
[
"localPeer"
]
=
func
()
interface
{}
{
return
lid
.
Pretty
()
}
}
if
laddr
!=
nil
{
m
[
"localAddr"
]
=
func
()
interface
{}
{
return
laddr
.
String
()
}
}
if
rid
!=
""
{
m
[
"remotePeer"
]
=
func
()
interface
{}
{
return
rid
.
Pretty
()
}
}
if
raddr
!=
nil
{
m
[
"remoteAddr"
]
=
func
()
interface
{}
{
return
raddr
.
String
()
}
}
return
m
}
// DeferredMap is a Loggable which may contained deffered values.
type
DeferredMap
map
[
string
]
interface
{}
// Loggable describes objects that can be marshalled into Metadata for logging
func
(
m
DeferredMap
)
Loggable
()
map
[
string
]
interface
{}
{
m2
:=
map
[
string
]
interface
{}{}
for
k
,
v
:=
range
m
{
if
vf
,
ok
:=
v
.
(
func
()
interface
{});
ok
{
// if it's a DeferredVal, call it.
m2
[
k
]
=
vf
()
}
else
{
// else use the value as is.
m2
[
k
]
=
v
}
}
return
m2
}
This diff is collapsed.
Click to expand it.
p2p/crypto/bench_test.go
deleted
100644 → 0
View file @
bd4f4b5b
package
crypto
import
"testing"
func
BenchmarkSign1B
(
b
*
testing
.
B
)
{
RunBenchmarkSign
(
b
,
1
)
}
func
BenchmarkSign10B
(
b
*
testing
.
B
)
{
RunBenchmarkSign
(
b
,
10
)
}
func
BenchmarkSign100B
(
b
*
testing
.
B
)
{
RunBenchmarkSign
(
b
,
100
)
}
func
BenchmarkSign1000B
(
b
*
testing
.
B
)
{
RunBenchmarkSign
(
b
,
1000
)
}
func
BenchmarkSign10000B
(
b
*
testing
.
B
)
{
RunBenchmarkSign
(
b
,
10000
)
}
func
BenchmarkSign100000B
(
b
*
testing
.
B
)
{
RunBenchmarkSign
(
b
,
100000
)
}
func
BenchmarkVerify1B
(
b
*
testing
.
B
)
{
RunBenchmarkVerify
(
b
,
1
)
}
func
BenchmarkVerify10B
(
b
*
testing
.
B
)
{
RunBenchmarkVerify
(
b
,
10
)
}
func
BenchmarkVerify100B
(
b
*
testing
.
B
)
{
RunBenchmarkVerify
(
b
,
100
)
}
func
BenchmarkVerify1000B
(
b
*
testing
.
B
)
{
RunBenchmarkVerify
(
b
,
1000
)
}
func
BenchmarkVerify10000B
(
b
*
testing
.
B
)
{
RunBenchmarkVerify
(
b
,
10000
)
}
func
BenchmarkVerify100000B
(
b
*
testing
.
B
)
{
RunBenchmarkVerify
(
b
,
100000
)
}
func
RunBenchmarkSign
(
b
*
testing
.
B
,
numBytes
int
)
{
secret
,
_
,
err
:=
GenerateKeyPair
(
RSA
,
1024
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
someData
:=
make
([]
byte
,
numBytes
)
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
_
,
err
:=
secret
.
Sign
(
someData
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
}
}
func
RunBenchmarkVerify
(
b
*
testing
.
B
,
numBytes
int
)
{
secret
,
public
,
err
:=
GenerateKeyPair
(
RSA
,
1024
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
someData
:=
make
([]
byte
,
numBytes
)
signature
,
err
:=
secret
.
Sign
(
someData
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
valid
,
err
:=
public
.
Verify
(
someData
,
signature
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
if
!
valid
{
b
.
Fatal
(
"signature should be valid"
)
}
}
}
This diff is collapsed.
Click to expand it.
p2p/crypto/key.go
deleted
100644 → 0
View file @
bd4f4b5b
// package crypto implements various cryptographic utilities used by ipfs.
// This includes a Public and Private key interface and an RSA key implementation
// that satisfies it.
package
crypto
import
(
"bytes"
"encoding/base64"
"errors"
"fmt"
"io"
"crypto/elliptic"
"crypto/hmac"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"hash"
pb
"github.com/ipfs/go-libp2p/p2p/crypto/pb"
proto
"gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
u
"gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
logging
"gx/ipfs/Qmazh5oNUVsDZTs2g59rq8aYQqwpss8tcUWQzor5sCCEuH/go-log"
)
var
log
=
logging
.
Logger
(
"crypto"
)
var
ErrBadKeyType
=
errors
.
New
(
"invalid or unsupported key type"
)
const
(
RSA
=
iota
)
// Key represents a crypto key that can be compared to another key
type
Key
interface
{
// Bytes returns a serialized, storeable representation of this key
Bytes
()
([]
byte
,
error
)
// Hash returns the hash of this key
Hash
()
([]
byte
,
error
)
// Equals checks whether two PubKeys are the same
Equals
(
Key
)
bool
}
// PrivKey represents a private key that can be used to generate a public key,
// sign data, and decrypt data that was encrypted with a public key
type
PrivKey
interface
{
Key
// Cryptographically sign the given bytes
Sign
([]
byte
)
([]
byte
,
error
)
// Return a public key paired with this private key
GetPublic
()
PubKey
// Generate a secret string of bytes
GenSecret
()
[]
byte
Decrypt
(
b
[]
byte
)
([]
byte
,
error
)
}
type
PubKey
interface
{
Key
// Verify that 'sig' is the signed hash of 'data'
Verify
(
data
[]
byte
,
sig
[]
byte
)
(
bool
,
error
)
// Encrypt data in a way that can be decrypted by a paired private key
Encrypt
(
data
[]
byte
)
([]
byte
,
error
)
}
// Given a public key, generates the shared key.
type
GenSharedKey
func
([]
byte
)
([]
byte
,
error
)
func
GenerateKeyPair
(
typ
,
bits
int
)
(
PrivKey
,
PubKey
,
error
)
{
return
GenerateKeyPairWithReader
(
typ
,
bits
,
rand
.
Reader
)
}
// Generates a keypair of the given type and bitsize
func
GenerateKeyPairWithReader
(
typ
,
bits
int
,
src
io
.
Reader
)
(
PrivKey
,
PubKey
,
error
)
{
switch
typ
{
case
RSA
:
priv
,
err
:=
rsa
.
GenerateKey
(
src
,
bits
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
pk
:=
&
priv
.
PublicKey
return
&
RsaPrivateKey
{
sk
:
priv
},
&
RsaPublicKey
{
pk
},
nil
default
:
return
nil
,
nil
,
ErrBadKeyType
}
}
// Generates an ephemeral public key and returns a function that will compute
// the shared secret key. Used in the identify module.
//
// Focuses only on ECDH now, but can be made more general in the future.
func
GenerateEKeyPair
(
curveName
string
)
([]
byte
,
GenSharedKey
,
error
)
{
var
curve
elliptic
.
Curve
switch
curveName
{
case
"P-256"
:
curve
=
elliptic
.
P256
()
case
"P-384"
:
curve
=
elliptic
.
P384
()
case
"P-521"
:
curve
=
elliptic
.
P521
()
}
priv
,
x
,
y
,
err
:=
elliptic
.
GenerateKey
(
curve
,
rand
.
Reader
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
pubKey
:=
elliptic
.
Marshal
(
curve
,
x
,
y
)
// log.Debug("GenerateEKeyPair %d", len(pubKey))
done
:=
func
(
theirPub
[]
byte
)
([]
byte
,
error
)
{
// Verify and unpack node's public key.
x
,
y
:=
elliptic
.
Unmarshal
(
curve
,
theirPub
)
if
x
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Malformed public key: %d %v"
,
len
(
theirPub
),
theirPub
)
}
if
!
curve
.
IsOnCurve
(
x
,
y
)
{
return
nil
,
errors
.
New
(
"Invalid public key."
)
}
// Generate shared secret.
secret
,
_
:=
curve
.
ScalarMult
(
x
,
y
,
priv
)
return
secret
.
Bytes
(),
nil
}
return
pubKey
,
done
,
nil
}
type
StretchedKeys
struct
{
IV
[]
byte
MacKey
[]
byte
CipherKey
[]
byte
}
// Generates a set of keys for each party by stretching the shared key.
// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
func
KeyStretcher
(
cipherType
string
,
hashType
string
,
secret
[]
byte
)
(
StretchedKeys
,
StretchedKeys
)
{
var
cipherKeySize
int
var
ivSize
int
switch
cipherType
{
case
"AES-128"
:
ivSize
=
16
cipherKeySize
=
16
case
"AES-256"
:
ivSize
=
16
cipherKeySize
=
32
case
"Blowfish"
:
ivSize
=
8
// Note: 24 arbitrarily selected, needs more thought
cipherKeySize
=
32
}
hmacKeySize
:=
20
seed
:=
[]
byte
(
"key expansion"
)
result
:=
make
([]
byte
,
2
*
(
ivSize
+
cipherKeySize
+
hmacKeySize
))
var
h
func
()
hash
.
Hash
switch
hashType
{
case
"SHA1"
:
h
=
sha1
.
New
case
"SHA256"
:
h
=
sha256
.
New
case
"SHA512"
:
h
=
sha512
.
New
default
:
panic
(
"Unrecognized hash function, programmer error?"
)
}
m
:=
hmac
.
New
(
h
,
secret
)
m
.
Write
(
seed
)
a
:=
m
.
Sum
(
nil
)
j
:=
0
for
j
<
len
(
result
)
{
m
.
Reset
()
m
.
Write
(
a
)
m
.
Write
(
seed
)
b
:=
m
.
Sum
(
nil
)
todo
:=
len
(
b
)
if
j
+
todo
>
len
(
result
)
{
todo
=
len
(
result
)
-
j
}
copy
(
result
[
j
:
j
+
todo
],
b
)
j
+=
todo
m
.
Reset
()
m
.
Write
(
a
)
a
=
m
.
Sum
(
nil
)
}
half
:=
len
(
result
)
/
2
r1
:=
result
[
:
half
]
r2
:=
result
[
half
:
]
var
k1
StretchedKeys
var
k2
StretchedKeys
k1
.
IV
=
r1
[
0
:
ivSize
]
k1
.
CipherKey
=
r1
[
ivSize
:
ivSize
+
cipherKeySize
]
k1
.
MacKey
=
r1
[
ivSize
+
cipherKeySize
:
]
k2
.
IV
=
r2
[
0
:
ivSize
]
k2
.
CipherKey
=
r2
[
ivSize
:
ivSize
+
cipherKeySize
]
k2
.
MacKey
=
r2
[
ivSize
+
cipherKeySize
:
]
return
k1
,
k2
}
// UnmarshalPublicKey converts a protobuf serialized public key into its
// representative object
func
UnmarshalPublicKey
(
data
[]
byte
)
(
PubKey
,
error
)
{
pmes
:=
new
(
pb
.
PublicKey
)
err
:=
proto
.
Unmarshal
(
data
,
pmes
)
if
err
!=
nil
{
return
nil
,
err
}
switch
pmes
.
GetType
()
{
case
pb
.
KeyType_RSA
:
return
UnmarshalRsaPublicKey
(
pmes
.
GetData
())
default
:
return
nil
,
ErrBadKeyType
}
}
// MarshalPublicKey converts a public key object into a protobuf serialized
// public key
func
MarshalPublicKey
(
k
PubKey
)
([]
byte
,
error
)
{
b
,
err
:=
MarshalRsaPublicKey
(
k
.
(
*
RsaPublicKey
))
if
err
!=
nil
{
return
nil
,
err
}
pmes
:=
new
(
pb
.
PublicKey
)
typ
:=
pb
.
KeyType_RSA
// for now only type.
pmes
.
Type
=
&
typ
pmes
.
Data
=
b
return
proto
.
Marshal
(
pmes
)
}
// UnmarshalPrivateKey converts a protobuf serialized private key into its
// representative object
func
UnmarshalPrivateKey
(
data
[]
byte
)
(
PrivKey
,
error
)
{
pmes
:=
new
(
pb
.
PrivateKey
)
err
:=
proto
.
Unmarshal
(
data
,
pmes
)
if
err
!=
nil
{
return
nil
,
err
}
switch
pmes
.
GetType
()
{
case
pb
.
KeyType_RSA
:
return
UnmarshalRsaPrivateKey
(
pmes
.
GetData
())
default
:
return
nil
,
ErrBadKeyType
}
}
// MarshalPrivateKey converts a key object into its protobuf serialized form.
func
MarshalPrivateKey
(
k
PrivKey
)
([]
byte
,
error
)
{
b
:=
MarshalRsaPrivateKey
(
k
.
(
*
RsaPrivateKey
))
pmes
:=
new
(
pb
.
PrivateKey
)
typ
:=
pb
.
KeyType_RSA
// for now only type.
pmes
.
Type
=
&
typ
pmes
.
Data
=
b
return
proto
.
Marshal
(
pmes
)
}
// ConfigDecodeKey decodes from b64 (for config file), and unmarshals.
func
ConfigDecodeKey
(
b
string
)
([]
byte
,
error
)
{
return
base64
.
StdEncoding
.
DecodeString
(
b
)
}
// ConfigEncodeKey encodes to b64 (for config file), and marshals.
func
ConfigEncodeKey
(
b
[]
byte
)
string
{
return
base64
.
StdEncoding
.
EncodeToString
(
b
)
}
// KeyEqual checks whether two
func
KeyEqual
(
k1
,
k2
Key
)
bool
{
if
k1
==
k2
{
return
true
}
b1
,
err1
:=
k1
.
Bytes
()
b2
,
err2
:=
k2
.
Bytes
()
return
bytes
.
Equal
(
b1
,
b2
)
&&
err1
==
err2
}
// KeyHash hashes a key.
func
KeyHash
(
k
Key
)
([]
byte
,
error
)
{
kb
,
err
:=
k
.
Bytes
()
if
err
!=
nil
{
return
nil
,
err
}
return
u
.
Hash
(
kb
),
nil
}
This diff is collapsed.
Click to expand it.
p2p/crypto/key_test.go
deleted
100644 → 0
View file @
bd4f4b5b
package
crypto_test
import
(
.
"github.com/ipfs/go-libp2p/p2p/crypto"
"bytes"
tu
"github.com/ipfs/go-libp2p/testutil"
"testing"
)
func
TestRsaKeys
(
t
*
testing
.
T
)
{
sk
,
pk
,
err
:=
tu
.
RandTestKeyPair
(
512
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
testKeySignature
(
t
,
sk
)
testKeyEncoding
(
t
,
sk
)
testKeyEquals
(
t
,
sk
)
testKeyEquals
(
t
,
pk
)
}
func
testKeySignature
(
t
*
testing
.
T
,
sk
PrivKey
)
{
pk
:=
sk
.
GetPublic
()
text
:=
sk
.
GenSecret
()
sig
,
err
:=
sk
.
Sign
(
text
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
valid
,
err
:=
pk
.
Verify
(
text
,
sig
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
valid
{
t
.
Fatal
(
"Invalid signature."
)
}
}
func
testKeyEncoding
(
t
*
testing
.
T
,
sk
PrivKey
)
{
skbm
,
err
:=
MarshalPrivateKey
(
sk
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
sk2
,
err
:=
UnmarshalPrivateKey
(
skbm
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
skbm2
,
err
:=
MarshalPrivateKey
(
sk2
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
skbm
,
skbm2
)
{
t
.
Error
(
"skb -> marshal -> unmarshal -> skb failed.
\n
"
,
skbm
,
"
\n
"
,
skbm2
)
}
pk
:=
sk
.
GetPublic
()
pkbm
,
err
:=
MarshalPublicKey
(
pk
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
_
,
err
=
UnmarshalPublicKey
(
pkbm
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
pkbm2
,
err
:=
MarshalPublicKey
(
pk
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
pkbm
,
pkbm2
)
{
t
.
Error
(
"skb -> marshal -> unmarshal -> skb failed.
\n
"
,
pkbm
,
"
\n
"
,
pkbm2
)
}
}
func
testKeyEquals
(
t
*
testing
.
T
,
k
Key
)
{
kb
,
err
:=
k
.
Bytes
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
KeyEqual
(
k
,
k
)
{
t
.
Fatal
(
"Key not equal to itself."
)
}
if
!
KeyEqual
(
k
,
testkey
(
kb
))
{
t
.
Fatal
(
"Key not equal to key with same bytes."
)
}
sk
,
pk
,
err
:=
tu
.
RandTestKeyPair
(
512
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
KeyEqual
(
k
,
sk
)
{
t
.
Fatal
(
"Keys should not equal."
)
}
if
KeyEqual
(
k
,
pk
)
{
t
.
Fatal
(
"Keys should not equal."
)
}
}
type
testkey
[]
byte
func
(
pk
testkey
)
Bytes
()
([]
byte
,
error
)
{
return
pk
,
nil
}
func
(
pk
testkey
)
Equals
(
k
Key
)
bool
{
return
KeyEqual
(
pk
,
k
)
}
func
(
pk
testkey
)
Hash
()
([]
byte
,
error
)
{
return
KeyHash
(
pk
)
}
This diff is collapsed.
Click to expand it.
p2p/crypto/pb/Makefile
deleted
100644 → 0
View file @
bd4f4b5b
PB
=
$(
wildcard
*
.proto
)
GO
=
$(PB:.proto=.pb.go)
all
:
$(GO)
%.pb.go
:
%.proto
protoc
--gogo_out
=
.
$<
clean
:
rm
*
.pb.go
This diff is collapsed.
Click to expand it.
p2p/crypto/pb/crypto.pb.go
deleted
100644 → 0
View file @
bd4f4b5b
// Code generated by protoc-gen-gogo.
// source: crypto.proto
// DO NOT EDIT!
/*
Package crypto_pb is a generated protocol buffer package.
It is generated from these files:
crypto.proto
It has these top-level messages:
PublicKey
PrivateKey
*/
package
crypto_pb
import
proto
"gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
import
math
"math"
// Reference imports to suppress errors if they are not otherwise used.
var
_
=
proto
.
Marshal
var
_
=
math
.
Inf
type
KeyType
int32
const
(
KeyType_RSA
KeyType
=
0
)
var
KeyType_name
=
map
[
int32
]
string
{
0
:
"RSA"
,
}
var
KeyType_value
=
map
[
string
]
int32
{
"RSA"
:
0
,
}
func
(
x
KeyType
)
Enum
()
*
KeyType
{
p
:=
new
(
KeyType
)
*
p
=
x
return
p
}
func
(
x
KeyType
)
String
()
string
{
return
proto
.
EnumName
(
KeyType_name
,
int32
(
x
))
}
func
(
x
*
KeyType
)
UnmarshalJSON
(
data
[]
byte
)
error
{
value
,
err
:=
proto
.
UnmarshalJSONEnum
(
KeyType_value
,
data
,
"KeyType"
)
if
err
!=
nil
{
return
err
}
*
x
=
KeyType
(
value
)
return
nil
}
type
PublicKey
struct
{
Type
*
KeyType
`protobuf:"varint,1,req,enum=crypto.pb.KeyType" json:"Type,omitempty"`
Data
[]
byte
`protobuf:"bytes,2,req" json:"Data,omitempty"`
XXX_unrecognized
[]
byte
`json:"-"`
}
func
(
m
*
PublicKey
)
Reset
()
{
*
m
=
PublicKey
{}
}
func
(
m
*
PublicKey
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
PublicKey
)
ProtoMessage
()
{}
func
(
m
*
PublicKey
)
GetType
()
KeyType
{
if
m
!=
nil
&&
m
.
Type
!=
nil
{
return
*
m
.
Type
}
return
KeyType_RSA
}
func
(
m
*
PublicKey
)
GetData
()
[]
byte
{
if
m
!=
nil
{
return
m
.
Data
}
return
nil
}
type
PrivateKey
struct
{
Type
*
KeyType
`protobuf:"varint,1,req,enum=crypto.pb.KeyType" json:"Type,omitempty"`
Data
[]
byte
`protobuf:"bytes,2,req" json:"Data,omitempty"`
XXX_unrecognized
[]
byte
`json:"-"`
}
func
(
m
*
PrivateKey
)
Reset
()
{
*
m
=
PrivateKey
{}
}
func
(
m
*
PrivateKey
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
PrivateKey
)
ProtoMessage
()
{}
func
(
m
*
PrivateKey
)
GetType
()
KeyType
{
if
m
!=
nil
&&
m
.
Type
!=
nil
{
return
*
m
.
Type
}
return
KeyType_RSA
}
func
(
m
*
PrivateKey
)
GetData
()
[]
byte
{
if
m
!=
nil
{
return
m
.
Data
}
return
nil
}
func
init
()
{
proto
.
RegisterEnum
(
"crypto.pb.KeyType"
,
KeyType_name
,
KeyType_value
)
}
This diff is collapsed.
Click to expand it.
p2p/crypto/pb/crypto.proto
deleted
100644 → 0
View file @
bd4f4b5b
package
crypto
.
pb
;
enum
KeyType
{
RSA
=
0
;
}
message
PublicKey
{
required
KeyType
Type
=
1
;
required
bytes
Data
=
2
;
}
message
PrivateKey
{
required
KeyType
Type
=
1
;
required
bytes
Data
=
2
;
}
This diff is collapsed.
Click to expand it.
p2p/crypto/rsa.go
deleted
100644 → 0
View file @
bd4f4b5b
package
crypto
import
(
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"errors"
pb
"github.com/ipfs/go-libp2p/p2p/crypto/pb"
proto
"gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
)
type
RsaPrivateKey
struct
{
sk
*
rsa
.
PrivateKey
pk
*
rsa
.
PublicKey
}
type
RsaPublicKey
struct
{
k
*
rsa
.
PublicKey
}
func
(
pk
*
RsaPublicKey
)
Verify
(
data
,
sig
[]
byte
)
(
bool
,
error
)
{
hashed
:=
sha256
.
Sum256
(
data
)
err
:=
rsa
.
VerifyPKCS1v15
(
pk
.
k
,
crypto
.
SHA256
,
hashed
[
:
],
sig
)
if
err
!=
nil
{
return
false
,
err
}
return
true
,
nil
}
func
(
pk
*
RsaPublicKey
)
Bytes
()
([]
byte
,
error
)
{
b
,
err
:=
x509
.
MarshalPKIXPublicKey
(
pk
.
k
)
if
err
!=
nil
{
return
nil
,
err
}
pbmes
:=
new
(
pb
.
PublicKey
)
typ
:=
pb
.
KeyType_RSA
pbmes
.
Type
=
&
typ
pbmes
.
Data
=
b
return
proto
.
Marshal
(
pbmes
)
}
func
(
pk
*
RsaPublicKey
)
Encrypt
(
b
[]
byte
)
([]
byte
,
error
)
{
return
rsa
.
EncryptPKCS1v15
(
rand
.
Reader
,
pk
.
k
,
b
)
}
// Equals checks whether this key is equal to another
func
(
pk
*
RsaPublicKey
)
Equals
(
k
Key
)
bool
{
return
KeyEqual
(
pk
,
k
)
}
func
(
pk
*
RsaPublicKey
)
Hash
()
([]
byte
,
error
)
{
return
KeyHash
(
pk
)
}
func
(
sk
*
RsaPrivateKey
)
GenSecret
()
[]
byte
{
buf
:=
make
([]
byte
,
16
)
rand
.
Read
(
buf
)
return
buf
}
func
(
sk
*
RsaPrivateKey
)
Sign
(
message
[]
byte
)
([]
byte
,
error
)
{
hashed
:=
sha256
.
Sum256
(
message
)
return
rsa
.
SignPKCS1v15
(
rand
.
Reader
,
sk
.
sk
,
crypto
.
SHA256
,
hashed
[
:
])
}
func
(
sk
*
RsaPrivateKey
)
GetPublic
()
PubKey
{
if
sk
.
pk
==
nil
{
sk
.
pk
=
&
sk
.
sk
.
PublicKey
}
return
&
RsaPublicKey
{
sk
.
pk
}
}
func
(
sk
*
RsaPrivateKey
)
Decrypt
(
b
[]
byte
)
([]
byte
,
error
)
{
return
rsa
.
DecryptPKCS1v15
(
rand
.
Reader
,
sk
.
sk
,
b
)
}
func
(
sk
*
RsaPrivateKey
)
Bytes
()
([]
byte
,
error
)
{
b
:=
x509
.
MarshalPKCS1PrivateKey
(
sk
.
sk
)
pbmes
:=
new
(
pb
.
PrivateKey
)
typ
:=
pb
.
KeyType_RSA
pbmes
.
Type
=
&
typ
pbmes
.
Data
=
b
return
proto
.
Marshal
(
pbmes
)
}
// Equals checks whether this key is equal to another
func
(
sk
*
RsaPrivateKey
)
Equals
(
k
Key
)
bool
{
return
KeyEqual
(
sk
,
k
)
}
func
(
sk
*
RsaPrivateKey
)
Hash
()
([]
byte
,
error
)
{
return
KeyHash
(
sk
)
}
func
UnmarshalRsaPrivateKey
(
b
[]
byte
)
(
*
RsaPrivateKey
,
error
)
{
sk
,
err
:=
x509
.
ParsePKCS1PrivateKey
(
b
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
RsaPrivateKey
{
sk
:
sk
},
nil
}
func
MarshalRsaPrivateKey
(
k
*
RsaPrivateKey
)
[]
byte
{
return
x509
.
MarshalPKCS1PrivateKey
(
k
.
sk
)
}
func
UnmarshalRsaPublicKey
(
b
[]
byte
)
(
*
RsaPublicKey
,
error
)
{
pub
,
err
:=
x509
.
ParsePKIXPublicKey
(
b
)
if
err
!=
nil
{
return
nil
,
err
}
pk
,
ok
:=
pub
.
(
*
rsa
.
PublicKey
)
if
!
ok
{
return
nil
,
errors
.
New
(
"Not actually an rsa public key."
)
}
return
&
RsaPublicKey
{
pk
},
nil
}
func
MarshalRsaPublicKey
(
k
*
RsaPublicKey
)
([]
byte
,
error
)
{
return
x509
.
MarshalPKIXPublicKey
(
k
.
k
)
}
This diff is collapsed.
Click to expand it.
p2p/crypto/secio/al.go
deleted
100644 → 0
View file @
bd4f4b5b
package
secio
import
(
"errors"
"fmt"
"strings"
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"hash"
ci
"github.com/ipfs/go-libp2p/p2p/crypto"
bfish
"gx/ipfs/Qme1boxspcQWR8FBzMxeppqug2fYgYc15diNWmqgDVnvn2/go-crypto/blowfish"
)
// List of supported ECDH curves
var
SupportedExchanges
=
"P-256,P-384,P-521"
// List of supported Ciphers
var
SupportedCiphers
=
"AES-256,AES-128,Blowfish"
// List of supported Hashes
var
SupportedHashes
=
"SHA256,SHA512"
type
HMAC
struct
{
hash
.
Hash
size
int
}
// encParams represent encryption parameters
type
encParams
struct
{
// keys
permanentPubKey
ci
.
PubKey
ephemeralPubKey
[]
byte
keys
ci
.
StretchedKeys
// selections
curveT
string
cipherT
string
hashT
string
// cipher + mac
cipher
cipher
.
Stream
mac
HMAC
}
func
(
e
*
encParams
)
makeMacAndCipher
()
error
{
m
,
err
:=
newMac
(
e
.
hashT
,
e
.
keys
.
MacKey
)
if
err
!=
nil
{
return
err
}
bc
,
err
:=
newBlockCipher
(
e
.
cipherT
,
e
.
keys
.
CipherKey
)
if
err
!=
nil
{
return
err
}
e
.
cipher
=
cipher
.
NewCTR
(
bc
,
e
.
keys
.
IV
)
e
.
mac
=
m
return
nil
}
func
newMac
(
hashType
string
,
key
[]
byte
)
(
HMAC
,
error
)
{
switch
hashType
{
case
"SHA1"
:
return
HMAC
{
hmac
.
New
(
sha1
.
New
,
key
),
sha1
.
Size
},
nil
case
"SHA512"
:
return
HMAC
{
hmac
.
New
(
sha512
.
New
,
key
),
sha512
.
Size
},
nil
case
"SHA256"
:
return
HMAC
{
hmac
.
New
(
sha256
.
New
,
key
),
sha256
.
Size
},
nil
default
:
return
HMAC
{},
fmt
.
Errorf
(
"Unrecognized hash type: %s"
,
hashType
)
}
}
func
newBlockCipher
(
cipherT
string
,
key
[]
byte
)
(
cipher
.
Block
,
error
)
{
switch
cipherT
{
case
"AES-128"
,
"AES-256"
:
return
aes
.
NewCipher
(
key
)
case
"Blowfish"
:
return
bfish
.
NewCipher
(
key
)
default
:
return
nil
,
fmt
.
Errorf
(
"Unrecognized cipher type: %s"
,
cipherT
)
}
}
// Determines which algorithm to use. Note: f(a, b) = f(b, a)
func
selectBest
(
order
int
,
p1
,
p2
string
)
(
string
,
error
)
{
var
f
,
s
[]
string
switch
{
case
order
<
0
:
f
=
strings
.
Split
(
p2
,
","
)
s
=
strings
.
Split
(
p1
,
","
)
case
order
>
0
:
f
=
strings
.
Split
(
p1
,
","
)
s
=
strings
.
Split
(
p2
,
","
)
default
:
// Exact same preferences.
p
:=
strings
.
Split
(
p1
,
","
)
return
p
[
0
],
nil
}
for
_
,
fc
:=
range
f
{
for
_
,
sc
:=
range
s
{
if
fc
==
sc
{
return
fc
,
nil
}
}
}
return
""
,
errors
.
New
(
"No algorithms in common!"
)
}
This diff is collapsed.
Click to expand it.
p2p/crypto/secio/interface.go
deleted
100644 → 0
View file @
bd4f4b5b
// package secio handles establishing secure communication between two peers.
package
secio
import
(
"io"
ci
"github.com/ipfs/go-libp2p/p2p/crypto"
peer
"github.com/ipfs/go-libp2p/p2p/peer"
msgio
"gx/ipfs/QmRQhVisS8dmPbjBUthVkenn81pBxrx1GxE281csJhm2vL/go-msgio"
context
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
)
// SessionGenerator constructs secure communication sessions for a peer.
type
SessionGenerator
struct
{
LocalID
peer
.
ID
PrivateKey
ci
.
PrivKey
}
// NewSession takes an insecure io.ReadWriter, sets up a TLS-like
// handshake with the other side, and returns a secure session.
// The handshake isn't run until the connection is read or written to.
// See the source for the protocol details and security implementation.
// The provided Context is only needed for the duration of this function.
func
(
sg
*
SessionGenerator
)
NewSession
(
ctx
context
.
Context
,
insecure
io
.
ReadWriteCloser
)
(
Session
,
error
)
{
return
newSecureSession
(
ctx
,
sg
.
LocalID
,
sg
.
PrivateKey
,
insecure
)
}
type
Session
interface
{
// ReadWriter returns the encrypted communication channel
ReadWriter
()
msgio
.
ReadWriteCloser
// LocalPeer retrieves the local peer.
LocalPeer
()
peer
.
ID
// LocalPrivateKey retrieves the local private key
LocalPrivateKey
()
ci
.
PrivKey
// RemotePeer retrieves the remote peer.
RemotePeer
()
peer
.
ID
// RemotePublicKey retrieves the remote's public key
// which was received during the handshake.
RemotePublicKey
()
ci
.
PubKey
// Close closes the secure session
Close
()
error
}
// SecureReadWriter returns the encrypted communication channel
func
(
s
*
secureSession
)
ReadWriter
()
msgio
.
ReadWriteCloser
{
if
err
:=
s
.
Handshake
();
err
!=
nil
{
return
&
closedRW
{
err
}
}
return
s
.
secure
}
// LocalPeer retrieves the local peer.
func
(
s
*
secureSession
)
LocalPeer
()
peer
.
ID
{
return
s
.
localPeer
}
// LocalPrivateKey retrieves the local peer's PrivateKey
func
(
s
*
secureSession
)
LocalPrivateKey
()
ci
.
PrivKey
{
return
s
.
localKey
}
// RemotePeer retrieves the remote peer.
func
(
s
*
secureSession
)
RemotePeer
()
peer
.
ID
{
if
err
:=
s
.
Handshake
();
err
!=
nil
{
return
""
}
return
s
.
remotePeer
}
// RemotePeer retrieves the remote peer.
func
(
s
*
secureSession
)
RemotePublicKey
()
ci
.
PubKey
{
if
err
:=
s
.
Handshake
();
err
!=
nil
{
return
nil
}
return
s
.
remote
.
permanentPubKey
}
// Close closes the secure session
func
(
s
*
secureSession
)
Close
()
error
{
s
.
cancel
()
s
.
handshakeMu
.
Lock
()
defer
s
.
handshakeMu
.
Unlock
()
if
s
.
secure
==
nil
{
return
s
.
insecure
.
Close
()
// hadn't secured yet.
}
return
s
.
secure
.
Close
()
}
// closedRW implements a stub msgio interface that's already
// closed and errored.
type
closedRW
struct
{
err
error
}
func
(
c
*
closedRW
)
Read
(
buf
[]
byte
)
(
int
,
error
)
{
return
0
,
c
.
err
}
func
(
c
*
closedRW
)
Write
(
buf
[]
byte
)
(
int
,
error
)
{
return
0
,
c
.
err
}
func
(
c
*
closedRW
)
NextMsgLen
()
(
int
,
error
)
{
return
0
,
c
.
err
}
func
(
c
*
closedRW
)
ReadMsg
()
([]
byte
,
error
)
{
return
nil
,
c
.
err
}
func
(
c
*
closedRW
)
WriteMsg
(
buf
[]
byte
)
error
{
return
c
.
err
}
func
(
c
*
closedRW
)
Close
()
error
{
return
c
.
err
}
func
(
c
*
closedRW
)
ReleaseMsg
(
m
[]
byte
)
{
}
This diff is collapsed.
Click to expand it.
p2p/crypto/secio/io_test.go
deleted
100644 → 0
View file @
bd4f4b5b
package
secio
This diff is collapsed.
Click to expand it.
p2p/crypto/secio/pb/Makefile
deleted
100644 → 0
View file @
bd4f4b5b
PB
=
$(
wildcard
*
.proto
)
GO
=
$(PB:.proto=.pb.go)
all
:
$(GO)
%.pb.go
:
%.proto
protoc
--gogo_out
=
.
--proto_path
=
../../../../../../:/usr/local/opt/protobuf/include:.
$<
clean
:
rm
*
.pb.go
This diff is collapsed.
Click to expand it.
p2p/crypto/secio/pb/spipe.pb.go
deleted
100644 → 0
View file @
bd4f4b5b
// Code generated by protoc-gen-gogo.
// source: spipe.proto
// DO NOT EDIT!
/*
Package spipe_pb is a generated protocol buffer package.
It is generated from these files:
spipe.proto
It has these top-level messages:
Propose
Exchange
*/
package
spipe_pb
import
proto
"gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
import
math
"math"
// Reference imports to suppress errors if they are not otherwise used.
var
_
=
proto
.
Marshal
var
_
=
math
.
Inf
type
Propose
struct
{
Rand
[]
byte
`protobuf:"bytes,1,opt,name=rand" json:"rand,omitempty"`
Pubkey
[]
byte
`protobuf:"bytes,2,opt,name=pubkey" json:"pubkey,omitempty"`
Exchanges
*
string
`protobuf:"bytes,3,opt,name=exchanges" json:"exchanges,omitempty"`
Ciphers
*
string
`protobuf:"bytes,4,opt,name=ciphers" json:"ciphers,omitempty"`
Hashes
*
string
`protobuf:"bytes,5,opt,name=hashes" json:"hashes,omitempty"`
XXX_unrecognized
[]
byte
`json:"-"`
}
func
(
m
*
Propose
)
Reset
()
{
*
m
=
Propose
{}
}
func
(
m
*
Propose
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
Propose
)
ProtoMessage
()
{}
func
(
m
*
Propose
)
GetRand
()
[]
byte
{
if
m
!=
nil
{
return
m
.
Rand
}
return
nil
}
func
(
m
*
Propose
)
GetPubkey
()
[]
byte
{
if
m
!=
nil
{
return
m
.
Pubkey
}
return
nil
}
func
(
m
*
Propose
)
GetExchanges
()
string
{
if
m
!=
nil
&&
m
.
Exchanges
!=
nil
{
return
*
m
.
Exchanges
}
return
""
}
func
(
m
*
Propose
)
GetCiphers
()
string
{
if
m
!=
nil
&&
m
.
Ciphers
!=
nil
{
return
*
m
.
Ciphers
}
return
""
}
func
(
m
*
Propose
)
GetHashes
()
string
{
if
m
!=
nil
&&
m
.
Hashes
!=
nil
{
return
*
m
.
Hashes
}
return
""
}
type
Exchange
struct
{
Epubkey
[]
byte
`protobuf:"bytes,1,opt,name=epubkey" json:"epubkey,omitempty"`
Signature
[]
byte
`protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
XXX_unrecognized
[]
byte
`json:"-"`
}
func
(
m
*
Exchange
)
Reset
()
{
*
m
=
Exchange
{}
}
func
(
m
*
Exchange
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
Exchange
)
ProtoMessage
()
{}
func
(
m
*
Exchange
)
GetEpubkey
()
[]
byte
{
if
m
!=
nil
{
return
m
.
Epubkey
}
return
nil
}
func
(
m
*
Exchange
)
GetSignature
()
[]
byte
{
if
m
!=
nil
{
return
m
.
Signature
}
return
nil
}
func
init
()
{
}
This diff is collapsed.
Click to expand it.
p2p/crypto/secio/pb/spipe.proto
deleted
100644 → 0
View file @
bd4f4b5b
package
spipe
.
pb
;
message
Propose
{
optional
bytes
rand
=
1
;
optional
bytes
pubkey
=
2
;
optional
string
exchanges
=
3
;
optional
string
ciphers
=
4
;
optional
string
hashes
=
5
;
}
message
Exchange
{
optional
bytes
epubkey
=
1
;
optional
bytes
signature
=
2
;
}
This diff is collapsed.
Click to expand it.
p2p/crypto/secio/protocol.go
deleted
100644 → 0
View file @
bd4f4b5b
package
secio
import
(
"bytes"
"crypto/rand"
"errors"
"fmt"
"io"
"sync"
"time"
ci
"github.com/ipfs/go-libp2p/p2p/crypto"
pb
"github.com/ipfs/go-libp2p/p2p/crypto/secio/pb"
peer
"github.com/ipfs/go-libp2p/p2p/peer"
msgio
"gx/ipfs/QmRQhVisS8dmPbjBUthVkenn81pBxrx1GxE281csJhm2vL/go-msgio"
u
"gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
context
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
logging
"gx/ipfs/Qmazh5oNUVsDZTs2g59rq8aYQqwpss8tcUWQzor5sCCEuH/go-log"
)
var
log
=
logging
.
Logger
(
"secio"
)
// ErrUnsupportedKeyType is returned when a private key cast/type switch fails.
var
ErrUnsupportedKeyType
=
errors
.
New
(
"unsupported key type"
)
// ErrClosed signals the closing of a connection.
var
ErrClosed
=
errors
.
New
(
"connection closed"
)
// ErrEcho is returned when we're attempting to handshake with the same keys and nonces.
var
ErrEcho
=
errors
.
New
(
"same keys and nonces. one side talking to self."
)
// HandshakeTimeout governs how long the handshake will be allowed to take place for.
// Making this number large means there could be many bogus connections waiting to
// timeout in flight. Typical handshakes take ~3RTTs, so it should be completed within
// seconds across a typical planet in the solar system.
var
HandshakeTimeout
=
time
.
Second
*
30
// nonceSize is the size of our nonces (in bytes)
const
nonceSize
=
16
// secureSession encapsulates all the parameters needed for encrypting
// and decrypting traffic from an insecure channel.
type
secureSession
struct
{
ctx
context
.
Context
cancel
context
.
CancelFunc
secure
msgio
.
ReadWriteCloser
insecure
io
.
ReadWriteCloser
insecureM
msgio
.
ReadWriter
localKey
ci
.
PrivKey
localPeer
peer
.
ID
remotePeer
peer
.
ID
local
encParams
remote
encParams
sharedSecret
[]
byte
handshakeMu
sync
.
Mutex
// guards handshakeDone + handshakeErr
handshakeDone
bool
handshakeErr
error
}
func
(
s
*
secureSession
)
Loggable
()
map
[
string
]
interface
{}
{
m
:=
make
(
map
[
string
]
interface
{})
m
[
"localPeer"
]
=
s
.
localPeer
.
Pretty
()
m
[
"remotePeer"
]
=
s
.
remotePeer
.
Pretty
()
m
[
"established"
]
=
(
s
.
secure
!=
nil
)
return
m
}
func
newSecureSession
(
ctx
context
.
Context
,
local
peer
.
ID
,
key
ci
.
PrivKey
,
insecure
io
.
ReadWriteCloser
)
(
*
secureSession
,
error
)
{
s
:=
&
secureSession
{
localPeer
:
local
,
localKey
:
key
}
s
.
ctx
,
s
.
cancel
=
context
.
WithCancel
(
ctx
)
switch
{
case
s
.
localPeer
==
""
:
return
nil
,
errors
.
New
(
"no local id provided"
)
case
s
.
localKey
==
nil
:
return
nil
,
errors
.
New
(
"no local private key provided"
)
case
!
s
.
localPeer
.
MatchesPrivateKey
(
s
.
localKey
)
:
return
nil
,
fmt
.
Errorf
(
"peer.ID does not match PrivateKey"
)
case
insecure
==
nil
:
return
nil
,
fmt
.
Errorf
(
"insecure ReadWriter is nil"
)
}
s
.
ctx
=
ctx
s
.
insecure
=
insecure
s
.
insecureM
=
msgio
.
NewReadWriter
(
insecure
)
return
s
,
nil
}
func
(
s
*
secureSession
)
Handshake
()
error
{
s
.
handshakeMu
.
Lock
()
defer
s
.
handshakeMu
.
Unlock
()
if
s
.
handshakeErr
!=
nil
{
return
s
.
handshakeErr
}
if
!
s
.
handshakeDone
{
s
.
handshakeErr
=
s
.
runHandshake
()
s
.
handshakeDone
=
true
}
return
s
.
handshakeErr
}
// runHandshake performs initial communication over insecure channel to share
// keys, IDs, and initiate communication, assigning all necessary params.
// requires the duplex channel to be a msgio.ReadWriter (for framed messaging)
func
(
s
*
secureSession
)
runHandshake
()
error
{
ctx
,
cancel
:=
context
.
WithTimeout
(
s
.
ctx
,
HandshakeTimeout
)
// remove
defer
cancel
()
// =============================================================================
// step 1. Propose -- propose cipher suite + send pubkeys + nonce
// Generate and send Hello packet.
// Hello = (rand, PublicKey, Supported)
nonceOut
:=
make
([]
byte
,
nonceSize
)
_
,
err
:=
rand
.
Read
(
nonceOut
)
if
err
!=
nil
{
return
err
}
defer
log
.
EventBegin
(
ctx
,
"secureHandshake"
,
s
)
.
Done
()
s
.
local
.
permanentPubKey
=
s
.
localKey
.
GetPublic
()
myPubKeyBytes
,
err
:=
s
.
local
.
permanentPubKey
.
Bytes
()
if
err
!=
nil
{
return
err
}
proposeOut
:=
new
(
pb
.
Propose
)
proposeOut
.
Rand
=
nonceOut
proposeOut
.
Pubkey
=
myPubKeyBytes
proposeOut
.
Exchanges
=
&
SupportedExchanges
proposeOut
.
Ciphers
=
&
SupportedCiphers
proposeOut
.
Hashes
=
&
SupportedHashes
// log.Debugf("1.0 Propose: nonce:%s exchanges:%s ciphers:%s hashes:%s",
// nonceOut, SupportedExchanges, SupportedCiphers, SupportedHashes)
// Send Propose packet (respects ctx)
proposeOutBytes
,
err
:=
writeMsgCtx
(
ctx
,
s
.
insecureM
,
proposeOut
)
if
err
!=
nil
{
return
err
}
// Receive + Parse their Propose packet and generate an Exchange packet.
proposeIn
:=
new
(
pb
.
Propose
)
proposeInBytes
,
err
:=
readMsgCtx
(
ctx
,
s
.
insecureM
,
proposeIn
)
if
err
!=
nil
{
return
err
}
// log.Debugf("1.0.1 Propose recv: nonce:%s exchanges:%s ciphers:%s hashes:%s",
// proposeIn.GetRand(), proposeIn.GetExchanges(), proposeIn.GetCiphers(), proposeIn.GetHashes())
// =============================================================================
// step 1.1 Identify -- get identity from their key
// get remote identity
s
.
remote
.
permanentPubKey
,
err
=
ci
.
UnmarshalPublicKey
(
proposeIn
.
GetPubkey
())
if
err
!=
nil
{
return
err
}
// get peer id
s
.
remotePeer
,
err
=
peer
.
IDFromPublicKey
(
s
.
remote
.
permanentPubKey
)
if
err
!=
nil
{
return
err
}
log
.
Debugf
(
"1.1 Identify: %s Remote Peer Identified as %s"
,
s
.
localPeer
,
s
.
remotePeer
)
// =============================================================================
// step 1.2 Selection -- select/agree on best encryption parameters
// to determine order, use cmp(H(remote_pubkey||local_rand), H(local_pubkey||remote_rand)).
oh1
:=
u
.
Hash
(
append
(
proposeIn
.
GetPubkey
(),
nonceOut
...
))
oh2
:=
u
.
Hash
(
append
(
myPubKeyBytes
,
proposeIn
.
GetRand
()
...
))
order
:=
bytes
.
Compare
(
oh1
,
oh2
)
if
order
==
0
{
return
ErrEcho
// talking to self (same socket. must be reuseport + dialing self)
}
s
.
local
.
curveT
,
err
=
selectBest
(
order
,
SupportedExchanges
,
proposeIn
.
GetExchanges
())
if
err
!=
nil
{
return
err
}
s
.
local
.
cipherT
,
err
=
selectBest
(
order
,
SupportedCiphers
,
proposeIn
.
GetCiphers
())
if
err
!=
nil
{
return
err
}
s
.
local
.
hashT
,
err
=
selectBest
(
order
,
SupportedHashes
,
proposeIn
.
GetHashes
())
if
err
!=
nil
{
return
err
}
// we use the same params for both directions (must choose same curve)
// WARNING: if they dont SelectBest the same way, this won't work...
s
.
remote
.
curveT
=
s
.
local
.
curveT
s
.
remote
.
cipherT
=
s
.
local
.
cipherT
s
.
remote
.
hashT
=
s
.
local
.
hashT
// log.Debugf("1.2 selection: exchange:%s cipher:%s hash:%s",
// s.local.curveT, s.local.cipherT, s.local.hashT)
// =============================================================================
// step 2. Exchange -- exchange (signed) ephemeral keys. verify signatures.
// Generate EphemeralPubKey
var
genSharedKey
ci
.
GenSharedKey
s
.
local
.
ephemeralPubKey
,
genSharedKey
,
err
=
ci
.
GenerateEKeyPair
(
s
.
local
.
curveT
)
// Gather corpus to sign.
selectionOut
:=
new
(
bytes
.
Buffer
)
selectionOut
.
Write
(
proposeOutBytes
)
selectionOut
.
Write
(
proposeInBytes
)
selectionOut
.
Write
(
s
.
local
.
ephemeralPubKey
)
selectionOutBytes
:=
selectionOut
.
Bytes
()
// log.Debugf("2.0 exchange: %v", selectionOutBytes)
exchangeOut
:=
new
(
pb
.
Exchange
)
exchangeOut
.
Epubkey
=
s
.
local
.
ephemeralPubKey
exchangeOut
.
Signature
,
err
=
s
.
localKey
.
Sign
(
selectionOutBytes
)
if
err
!=
nil
{
return
err
}
// Send Propose packet (respects ctx)
if
_
,
err
:=
writeMsgCtx
(
ctx
,
s
.
insecureM
,
exchangeOut
);
err
!=
nil
{
return
err
}
// Receive + Parse their Exchange packet.
exchangeIn
:=
new
(
pb
.
Exchange
)
if
_
,
err
:=
readMsgCtx
(
ctx
,
s
.
insecureM
,
exchangeIn
);
err
!=
nil
{
return
err
}
// =============================================================================
// step 2.1. Verify -- verify their exchange packet is good.
// get their ephemeral pub key
s
.
remote
.
ephemeralPubKey
=
exchangeIn
.
GetEpubkey
()
selectionIn
:=
new
(
bytes
.
Buffer
)
selectionIn
.
Write
(
proposeInBytes
)
selectionIn
.
Write
(
proposeOutBytes
)
selectionIn
.
Write
(
s
.
remote
.
ephemeralPubKey
)
selectionInBytes
:=
selectionIn
.
Bytes
()
// log.Debugf("2.0.1 exchange recv: %v", selectionInBytes)
// u.POut("Remote Peer Identified as %s\n", s.remote)
sigOK
,
err
:=
s
.
remote
.
permanentPubKey
.
Verify
(
selectionInBytes
,
exchangeIn
.
GetSignature
())
if
err
!=
nil
{
// log.Error("2.1 Verify: failed: %s", err)
return
err
}
if
!
sigOK
{
err
:=
errors
.
New
(
"Bad signature!"
)
// log.Error("2.1 Verify: failed: %s", err)
return
err
}
// log.Debugf("2.1 Verify: signature verified.")
// =============================================================================
// step 2.2. Keys -- generate keys for mac + encryption
// OK! seems like we're good to go.
s
.
sharedSecret
,
err
=
genSharedKey
(
exchangeIn
.
GetEpubkey
())
if
err
!=
nil
{
return
err
}
// generate two sets of keys (stretching)
k1
,
k2
:=
ci
.
KeyStretcher
(
s
.
local
.
cipherT
,
s
.
local
.
hashT
,
s
.
sharedSecret
)
// use random nonces to decide order.
switch
{
case
order
>
0
:
// just break
case
order
<
0
:
k1
,
k2
=
k2
,
k1
// swap
default
:
// we should've bailed before this. but if not, bail here.
return
ErrEcho
}
s
.
local
.
keys
=
k1
s
.
remote
.
keys
=
k2
// log.Debug("2.2 keys:\n\tshared: %v\n\tk1: %v\n\tk2: %v",
// s.sharedSecret, s.local.keys, s.remote.keys)
// =============================================================================
// step 2.3. MAC + Cipher -- prepare MAC + cipher
if
err
:=
s
.
local
.
makeMacAndCipher
();
err
!=
nil
{
return
err
}
if
err
:=
s
.
remote
.
makeMacAndCipher
();
err
!=
nil
{
return
err
}
// log.Debug("2.3 mac + cipher.")
// =============================================================================
// step 3. Finish -- send expected message to verify encryption works (send local nonce)
// setup ETM ReadWriter
w
:=
NewETMWriter
(
s
.
insecure
,
s
.
local
.
cipher
,
s
.
local
.
mac
)
r
:=
NewETMReader
(
s
.
insecure
,
s
.
remote
.
cipher
,
s
.
remote
.
mac
)
s
.
secure
=
msgio
.
Combine
(
w
,
r
)
.
(
msgio
.
ReadWriteCloser
)
// log.Debug("3.0 finish. sending: %v", proposeIn.GetRand())
// send their Nonce.
if
_
,
err
:=
s
.
secure
.
Write
(
proposeIn
.
GetRand
());
err
!=
nil
{
return
fmt
.
Errorf
(
"Failed to write Finish nonce: %s"
,
err
)
}
// read our Nonce
nonceOut2
:=
make
([]
byte
,
len
(
nonceOut
))
if
_
,
err
:=
io
.
ReadFull
(
s
.
secure
,
nonceOut2
);
err
!=
nil
{
return
fmt
.
Errorf
(
"Failed to read Finish nonce: %s"
,
err
)
}
// log.Debug("3.0 finish.\n\texpect: %v\n\tactual: %v", nonceOut, nonceOut2)
if
!
bytes
.
Equal
(
nonceOut
,
nonceOut2
)
{
return
fmt
.
Errorf
(
"Failed to read our encrypted nonce: %s != %s"
,
nonceOut2
,
nonceOut
)
}
// Whew! ok, that's all folks.
return
nil
}
This diff is collapsed.
Click to expand it.
p2p/crypto/secio/rw.go
deleted
100644 → 0
View file @
bd4f4b5b
package
secio
import
(
"crypto/cipher"
"errors"
"fmt"
"io"
"sync"
"crypto/hmac"
msgio
"gx/ipfs/QmRQhVisS8dmPbjBUthVkenn81pBxrx1GxE281csJhm2vL/go-msgio"
mpool
"gx/ipfs/QmRQhVisS8dmPbjBUthVkenn81pBxrx1GxE281csJhm2vL/go-msgio/mpool"
proto
"gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
context
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
)
// ErrMACInvalid signals that a MAC verification failed
var
ErrMACInvalid
=
errors
.
New
(
"MAC verification failed"
)
// bufPool is a ByteSlicePool for messages. we need buffers because (sadly)
// we cannot encrypt in place-- the user needs their buffer back.
var
bufPool
=
mpool
.
ByteSlicePool
type
etmWriter
struct
{
// params
pool
mpool
.
Pool
// for the buffers with encrypted data
msg
msgio
.
WriteCloser
// msgio for knowing where boundaries lie
str
cipher
.
Stream
// the stream cipher to encrypt with
mac
HMAC
// the mac to authenticate data with
sync
.
Mutex
}
// NewETMWriter Encrypt-Then-MAC
func
NewETMWriter
(
w
io
.
Writer
,
s
cipher
.
Stream
,
mac
HMAC
)
msgio
.
WriteCloser
{
return
&
etmWriter
{
msg
:
msgio
.
NewWriter
(
w
),
str
:
s
,
mac
:
mac
,
pool
:
bufPool
}
}
// Write writes passed in buffer as a single message.
func
(
w
*
etmWriter
)
Write
(
b
[]
byte
)
(
int
,
error
)
{
if
err
:=
w
.
WriteMsg
(
b
);
err
!=
nil
{
return
0
,
err
}
return
len
(
b
),
nil
}
// WriteMsg writes the msg in the passed in buffer.
func
(
w
*
etmWriter
)
WriteMsg
(
b
[]
byte
)
error
{
w
.
Lock
()
defer
w
.
Unlock
()
// encrypt.
data
:=
w
.
pool
.
Get
(
uint32
(
len
(
b
)))
.
([]
byte
)
data
=
data
[
:
len
(
b
)]
// the pool's buffer may be larger
w
.
str
.
XORKeyStream
(
data
,
b
)
// log.Debugf("ENC plaintext (%d): %s %v", len(b), b, b)
// log.Debugf("ENC ciphertext (%d): %s %v", len(data), data, data)
// then, mac.
if
_
,
err
:=
w
.
mac
.
Write
(
data
);
err
!=
nil
{
return
err
}
// Sum appends.
data
=
w
.
mac
.
Sum
(
data
)
w
.
mac
.
Reset
()
// it's sad to append here. our buffers are -- hopefully -- coming from
// a shared buffer pool, so the append may not actually cause allocation
// one can only hope. i guess we'll see.
return
w
.
msg
.
WriteMsg
(
data
)
}
func
(
w
*
etmWriter
)
Close
()
error
{
return
w
.
msg
.
Close
()
}
type
etmReader
struct
{
msgio
.
Reader
io
.
Closer
// internal buffer returned from the msgio
buf
[]
byte
// low and high watermark for the buffered data
lowat
int
hiwat
int
// params
msg
msgio
.
ReadCloser
// msgio for knowing where boundaries lie
str
cipher
.
Stream
// the stream cipher to encrypt with
mac
HMAC
// the mac to authenticate data with
sync
.
Mutex
}
// NewETMReader Encrypt-Then-MAC
func
NewETMReader
(
r
io
.
Reader
,
s
cipher
.
Stream
,
mac
HMAC
)
msgio
.
ReadCloser
{
return
&
etmReader
{
msg
:
msgio
.
NewReader
(
r
),
str
:
s
,
mac
:
mac
}
}
func
(
r
*
etmReader
)
NextMsgLen
()
(
int
,
error
)
{
return
r
.
msg
.
NextMsgLen
()
}
func
(
r
*
etmReader
)
drain
(
buf
[]
byte
)
int
{
// Return zero if there is no data remaining in the internal buffer.
if
r
.
lowat
==
r
.
hiwat
{
return
0
}
// Copy data to the output buffer.
n
:=
copy
(
buf
,
r
.
buf
[
r
.
lowat
:
r
.
hiwat
])
// Update the low watermark.
r
.
lowat
+=
n
// Release the buffer and reset the watermarks if it has been fully read.
if
r
.
lowat
==
r
.
hiwat
{
r
.
msg
.
ReleaseMsg
(
r
.
buf
)
r
.
buf
=
nil
r
.
lowat
=
0
r
.
hiwat
=
0
}
return
n
}
func
(
r
*
etmReader
)
fill
()
error
{
// Read a message from the underlying msgio.
msg
,
err
:=
r
.
msg
.
ReadMsg
()
if
err
!=
nil
{
return
err
}
// Check the MAC.
n
,
err
:=
r
.
macCheckThenDecrypt
(
msg
)
if
err
!=
nil
{
r
.
msg
.
ReleaseMsg
(
msg
)
return
err
}
// Retain the buffer so it can be drained from and later released.
r
.
buf
=
msg
r
.
lowat
=
0
r
.
hiwat
=
n
return
nil
}
func
(
r
*
etmReader
)
Read
(
buf
[]
byte
)
(
int
,
error
)
{
r
.
Lock
()
defer
r
.
Unlock
()
// Return buffered data without reading more, if possible.
copied
:=
r
.
drain
(
buf
)
if
copied
>
0
{
return
copied
,
nil
}
// Check the length of the next message.
fullLen
,
err
:=
r
.
msg
.
NextMsgLen
()
if
err
!=
nil
{
return
0
,
err
}
// If the destination buffer is too short, fill an internal buffer and then
// drain as much of that into the output buffer as will fit.
if
cap
(
buf
)
<
fullLen
{
err
:=
r
.
fill
()
if
err
!=
nil
{
return
0
,
err
}
copied
:=
r
.
drain
(
buf
)
return
copied
,
nil
}
// Otherwise, read directly into the destination buffer.
n
,
err
:=
io
.
ReadFull
(
r
.
msg
,
buf
[
:
fullLen
])
if
err
!=
nil
{
return
0
,
err
}
m
,
err
:=
r
.
macCheckThenDecrypt
(
buf
[
:
n
])
if
err
!=
nil
{
return
0
,
err
}
return
m
,
nil
}
func
(
r
*
etmReader
)
ReadMsg
()
([]
byte
,
error
)
{
r
.
Lock
()
defer
r
.
Unlock
()
msg
,
err
:=
r
.
msg
.
ReadMsg
()
if
err
!=
nil
{
return
nil
,
err
}
n
,
err
:=
r
.
macCheckThenDecrypt
(
msg
)
if
err
!=
nil
{
return
nil
,
err
}
return
msg
[
:
n
],
nil
}
func
(
r
*
etmReader
)
macCheckThenDecrypt
(
m
[]
byte
)
(
int
,
error
)
{
l
:=
len
(
m
)
if
l
<
r
.
mac
.
size
{
return
0
,
fmt
.
Errorf
(
"buffer (%d) shorter than MAC size (%d)"
,
l
,
r
.
mac
.
size
)
}
mark
:=
l
-
r
.
mac
.
size
data
:=
m
[
:
mark
]
macd
:=
m
[
mark
:
]
r
.
mac
.
Write
(
data
)
expected
:=
r
.
mac
.
Sum
(
nil
)
r
.
mac
.
Reset
()
// check mac. if failed, return error.
if
!
hmac
.
Equal
(
macd
,
expected
)
{
log
.
Debug
(
"MAC Invalid:"
,
expected
,
"!="
,
macd
)
return
0
,
ErrMACInvalid
}
// ok seems good. decrypt. (can decrypt in place, yay!)
// log.Debugf("DEC ciphertext (%d): %s %v", len(data), data, data)
r
.
str
.
XORKeyStream
(
data
,
data
)
// log.Debugf("DEC plaintext (%d): %s %v", len(data), data, data)
return
mark
,
nil
}
func
(
w
*
etmReader
)
Close
()
error
{
return
w
.
msg
.
Close
()
}
// ReleaseMsg signals a buffer can be reused.
func
(
r
*
etmReader
)
ReleaseMsg
(
b
[]
byte
)
{
r
.
msg
.
ReleaseMsg
(
b
)
}
// writeMsgCtx is used by the
func
writeMsgCtx
(
ctx
context
.
Context
,
w
msgio
.
Writer
,
msg
proto
.
Message
)
([]
byte
,
error
)
{
enc
,
err
:=
proto
.
Marshal
(
msg
)
if
err
!=
nil
{
return
nil
,
err
}
// write in a goroutine so we can exit when our context is cancelled.
done
:=
make
(
chan
error
)
go
func
(
m
[]
byte
)
{
err
:=
w
.
WriteMsg
(
m
)
select
{
case
done
<-
err
:
case
<-
ctx
.
Done
()
:
}
}(
enc
)
select
{
case
<-
ctx
.
Done
()
:
return
nil
,
ctx
.
Err
()
case
e
:=
<-
done
:
return
enc
,
e
}
}
func
readMsgCtx
(
ctx
context
.
Context
,
r
msgio
.
Reader
,
p
proto
.
Message
)
([]
byte
,
error
)
{
var
msg
[]
byte
// read in a goroutine so we can exit when our context is cancelled.
done
:=
make
(
chan
error
)
go
func
()
{
var
err
error
msg
,
err
=
r
.
ReadMsg
()
select
{
case
done
<-
err
:
case
<-
ctx
.
Done
()
:
}
}()
select
{
case
<-
ctx
.
Done
()
:
return
nil
,
ctx
.
Err
()
case
e
:=
<-
done
:
if
e
!=
nil
{
return
nil
,
e
}
}
return
msg
,
proto
.
Unmarshal
(
msg
,
p
)
}
This diff is collapsed.
Click to expand it.
p2p/discovery/mdns.go
View file @
4f82ae5e
...
...
@@ -10,8 +10,8 @@ import (
"time"
"github.com/ipfs/go-libp2p/p2p/host"
"github.com/ipfs/go-libp2p/p2p/peer"
"gx/ipfs/QmSscYPCcE1H3UQr2tnsJ2a9dK9LsHTBGgP71VW6fz67e5/mdns"
"gx/ipfs/QmY1xNhBfF9xA1pmD8yejyQAyd77K68qNN6JPM1CN2eiRu/go-libp2p-peer"
manet
"gx/ipfs/QmYVqhVfbK4BKvbW88Lhm26b3ud14sTBvcm1H7uWUx1Fkp/go-multiaddr-net"
logging
"gx/ipfs/Qmazh5oNUVsDZTs2g59rq8aYQqwpss8tcUWQzor5sCCEuH/go-log"
ma
"gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr"
...
...
This diff is collapsed.
Click to expand it.
p2p/host/basic/basic_host.go
View file @
4f82ae5e
...
...
@@ -6,11 +6,11 @@ import (
metrics
"github.com/ipfs/go-libp2p/p2p/metrics"
mstream
"github.com/ipfs/go-libp2p/p2p/metrics/stream"
inet
"github.com/ipfs/go-libp2p/p2p/net"
peer
"github.com/ipfs/go-libp2p/p2p/peer"
protocol
"github.com/ipfs/go-libp2p/p2p/protocol"
identify
"github.com/ipfs/go-libp2p/p2p/protocol/identify"
relay
"github.com/ipfs/go-libp2p/p2p/protocol/relay"
goprocess
"gx/ipfs/QmQopLATEYMNg7dVqZRNDfeE2S1yKy8zrRh5xnYiuqeZBn/goprocess"
peer
"gx/ipfs/QmY1xNhBfF9xA1pmD8yejyQAyd77K68qNN6JPM1CN2eiRu/go-libp2p-peer"
context
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
logging
"gx/ipfs/Qmazh5oNUVsDZTs2g59rq8aYQqwpss8tcUWQzor5sCCEuH/go-log"
ma
"gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr"
...
...
This diff is collapsed.
Click to expand it.
p2p/host/basic/natmgr.go
View file @
4f82ae5e
...
...
@@ -3,10 +3,10 @@ package basichost
import
(
"sync"
lgbl
"github.com/ipfs/go-libp2p/loggables"
inat
"github.com/ipfs/go-libp2p/p2p/nat"
inet
"github.com/ipfs/go-libp2p/p2p/net"
goprocess
"gx/ipfs/QmQopLATEYMNg7dVqZRNDfeE2S1yKy8zrRh5xnYiuqeZBn/goprocess"
lgbl
"gx/ipfs/QmSyBhZt2upyQ3NJmTpab1pX6hesA59vcYTGmgoDorZZbw/go-libp2p-loggables"
context
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
ma
"gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr"
)
...
...
This diff is collapsed.
Click to expand it.
p2p/host/host.go
View file @
4f82ae5e
...
...
@@ -3,9 +3,9 @@ package host
import
(
metrics
"github.com/ipfs/go-libp2p/p2p/metrics"
inet
"github.com/ipfs/go-libp2p/p2p/net"
peer
"github.com/ipfs/go-libp2p/p2p/peer"
protocol
"github.com/ipfs/go-libp2p/p2p/protocol"
msmux
"gx/ipfs/QmUeEcYJrzAEKdQXjzTxCgNZgc9sRuwharsvzzm5Gd2oGB/go-multistream"
peer
"gx/ipfs/QmY1xNhBfF9xA1pmD8yejyQAyd77K68qNN6JPM1CN2eiRu/go-libp2p-peer"
context
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
logging
"gx/ipfs/Qmazh5oNUVsDZTs2g59rq8aYQqwpss8tcUWQzor5sCCEuH/go-log"
ma
"gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr"
...
...
This diff is collapsed.
Click to expand it.
Prev
1
2
3
4
5
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help