// Package insecure provides an insecure, unencrypted implementation of the SecureConn and SecureTransport interfaces. // // Recommended only for testing and other non-production usage.
package insecure import ( ci ) // ID is the multistream-select protocol ID that should be used when identifying // this security transport. const ID = "/plaintext/2.0.0" // Transport is a no-op stream security transport. It provides no // security and simply mocks the security methods. Identity methods // return the local peer's ID and private key, and whatever the remote // peer presents as their ID and public key. // No authentication of the remote identity is performed. type Transport struct { id peer.ID key ci.PrivKey protocolID protocol.ID } var _ sec.SecureTransport = &Transport{} // NewWithIdentity constructs a new insecure transport. The public key is sent to // remote peers. No security is provided. func ( protocol.ID, peer.ID, ci.PrivKey) *Transport { return &Transport{ protocolID: , id: , key: , } } // LocalPeer returns the transport's local peer ID. func ( *Transport) () peer.ID { return .id } // SecureInbound *pretends to secure* an inbound connection to the given peer. // It sends the local peer's ID and public key, and receives the same from the remote peer. // No validation is performed as to the authenticity or ownership of the provided public key, // and the key exchange provides no security. // // SecureInbound may fail if the remote peer sends an ID and public key that are inconsistent // with each other, or if a network error occurs during the ID exchange. func ( *Transport) ( context.Context, net.Conn, peer.ID) (sec.SecureConn, error) { := &Conn{ Conn: , local: .id, localPubKey: .key.GetPublic(), } if := .runHandshakeSync(); != nil { return nil, } if != "" && != .remote { return nil, fmt.Errorf("remote peer sent unexpected peer ID. expected=%s received=%s", , .remote) } return , nil } // SecureOutbound *pretends to secure* an outbound connection to the given peer. // It sends the local peer's ID and public key, and receives the same from the remote peer. // No validation is performed as to the authenticity or ownership of the provided public key, // and the key exchange provides no security. // // SecureOutbound may fail if the remote peer sends an ID and public key that are inconsistent // with each other, or if the ID sent by the remote peer does not match the one dialed. It may // also fail if a network error occurs during the ID exchange. func ( *Transport) ( context.Context, net.Conn, peer.ID) (sec.SecureConn, error) { := &Conn{ Conn: , local: .id, localPubKey: .key.GetPublic(), } if := .runHandshakeSync(); != nil { return nil, } if != .remote { return nil, fmt.Errorf("remote peer sent unexpected peer ID. expected=%s received=%s", , .remote) } return , nil } func ( *Transport) () protocol.ID { return .protocolID } // Conn is the connection type returned by the insecure transport. type Conn struct { net.Conn local, remote peer.ID localPubKey, remotePubKey ci.PubKey } func makeExchangeMessage( ci.PubKey) (*pb.Exchange, error) { , := ci.PublicKeyToProto() if != nil { return nil, } , := peer.IDFromPublicKey() if != nil { return nil, } return &pb.Exchange{ Id: []byte(), Pubkey: , }, nil } func ( *Conn) () error { // If we were initialized without keys, behave as in plaintext/1.0.0 (do nothing) if .localPubKey == nil { return nil } // Generate an Exchange message , := makeExchangeMessage(.localPubKey) if != nil { return } // Send our Exchange and read theirs , := readWriteMsg(.Conn, ) if != nil { return } // Pull remote ID and public key from message , := ci.PublicKeyFromProto(.Pubkey) if != nil { return } , := peer.IDFromBytes(.Id) if != nil { return } // Validate that ID matches public key if !.MatchesPublicKey() { , := peer.IDFromPublicKey() return fmt.Errorf("remote peer id does not match public key. id=%s calculated_id=%s", , ) } // Add remote ID and key to conn state .remotePubKey = .remote = return nil } // read and write a message at the same time. func readWriteMsg( io.ReadWriter, *pb.Exchange) (*pb.Exchange, error) { const = 1 << 16 , := proto.Marshal() if != nil { return nil, } := make(chan error) go func() { := msgio.NewVarintWriter() <- .WriteMsg() }() := msgio.NewVarintReaderSize(, ) , := .ReadMsg() // Always wait for the read to finish. := <- if != nil { return nil, } if != nil { .ReleaseMsg() return nil, } := new(pb.Exchange) = proto.Unmarshal(, ) return , } // LocalPeer returns the local peer ID. func ( *Conn) () peer.ID { return .local } // RemotePeer returns the remote peer ID if we initiated the dial. Otherwise, it // returns "" (because this connection isn't actually secure). func ( *Conn) () peer.ID { return .remote } // RemotePublicKey returns whatever public key was given by the remote peer. // Note that no verification of ownership is done, as this connection is not secure. func ( *Conn) () ci.PubKey { return .remotePubKey } // ConnState returns the security connection's state information. func ( *Conn) () network.ConnectionState { return network.ConnectionState{} } var _ sec.SecureTransport = (*Transport)(nil) var _ sec.SecureConn = (*Conn)(nil)