コード例 #1
0
ファイル: channel.go プロジェクト: utamaro/gogotelehash
func (c *Channel) traceReceivedPacket(pkt *lob.Packet) {
	if tracer.Enabled {
		tracer.Emit("channel.rcv.packet", tracer.Info{
			"channel_id": c.TID,
			"packet_id":  pkt.TID,
			"packet": tracer.Info{
				"header": pkt.Header(),
				"body":   base64.StdEncoding.EncodeToString(pkt.Body(nil)),
			},
		})
	}
}
コード例 #2
0
ファイル: channel_test.go プロジェクト: utamaro/gogotelehash
func TestPingPong(t *testing.T) {
	// t.Parallel()
	logs.ResetLogger()

	withTwoEndpoints(t, func(A, B *Endpoint) {
		var (
			assert = assert.New(t)
			c      *Channel
			ident  *Identity
			pkt    *lob.Packet
			err    error
		)

		go func() {
			c, err := A.Listen("ping", false).AcceptChannel()

			c.SetDeadline(time.Now().Add(10 * time.Second))

			if assert.NoError(err) && assert.NotNil(c) {
				defer c.Close()

				pkt, err = c.ReadPacket()
				if assert.NoError(err) && assert.NotNil(pkt) {
					assert.Equal("ping", string(pkt.Body(nil)))

					err = c.WritePacket(lob.New([]byte("pong")))
					assert.NoError(err)
				}
			}
		}()

		ident, err = A.LocalIdentity()
		assert.NoError(err)

		c, err = B.Open(ident, "ping", false)
		assert.NoError(err)
		if assert.NotNil(c) {
			defer c.Close()

			c.SetDeadline(time.Now().Add(10 * time.Second))

			err = c.WritePacket(lob.New([]byte("ping")))
			assert.NoError(err)

			pkt, err = c.ReadPacket()
			if assert.NoError(err) && assert.NotNil(pkt) {
				assert.Equal("pong", string(pkt.Body(nil)))
			}
		}
	})
}
コード例 #3
0
ファイル: channel.go プロジェクト: utamaro/gogotelehash
func (c *Channel) traceDroppedPacket(pkt *lob.Packet, reason string) {
	if tracer.Enabled {
		info := tracer.Info{
			"channel_id": c.TID,
			"packet_id":  pkt.TID,
			"reason":     reason,
		}

		if pkt != nil {
			info["packet"] = tracer.Info{
				"header": pkt.Header(),
				"body":   base64.StdEncoding.EncodeToString(pkt.Body(nil)),
			}
		}

		tracer.Emit("channel.rcv.packet", info)
	}
}
コード例 #4
0
ファイル: channel.go プロジェクト: utamaro/gogotelehash
func (c *Channel) traceWrite(pkt *lob.Packet, p *Pipe) {
	if tracer.Enabled {
		info := tracer.Info{
			"channel_id": c.TID,
		}

		if p != nil {
			info["path"] = p.RemoteAddr().String()
		}

		if pkt != nil {
			info["packet_id"] = pkt.TID
			info["packet"] = tracer.Info{
				"header": pkt.Header(),
				"body":   base64.StdEncoding.EncodeToString(pkt.Body(nil)),
			}
		}

		tracer.Emit("channel.write", info)
	}
}
コード例 #5
0
ファイル: channel.go プロジェクト: utamaro/gogotelehash
func (c *Channel) traceWriteError(pkt *lob.Packet, p *Pipe, reason error) error {
	if tracer.Enabled {
		info := tracer.Info{
			"channel_id": c.TID,
			"reason":     reason.Error(),
		}

		if p != nil {
			info["path"] = p.RemoteAddr().String()
		}

		if pkt != nil {
			info["packet_id"] = pkt.TID
			info["packet"] = tracer.Info{
				"header": pkt.Header(),
				"body":   base64.StdEncoding.EncodeToString(pkt.Body(nil)),
			}
		}

		tracer.Emit("channel.write.error", info)
	}
	return reason
}
コード例 #6
0
ファイル: cs1a_cipher.go プロジェクト: utamaro/gogotelehash
func (s *state) DecryptPacket(pkt *lob.Packet) (*lob.Packet, error) {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	if !s.CanDecryptPacket() {
		return nil, cipherset.ErrInvalidState
	}
	if pkt == nil {
		return nil, nil
	}

	if !pkt.Header().IsZero() || pkt.BodyLen() < 16+4+4 {
		return nil, cipherset.ErrInvalidPacket
	}

	var (
		nonce    [16]byte
		bodyRaw  []byte
		innerRaw []byte
		innerLen = pkt.BodyLen() - (16 + 4 + 4)
		body     = bufpool.New()
		inner    = bufpool.New().SetLen(innerLen)
	)

	pkt.Body(body.SetLen(pkt.BodyLen()).RawBytes()[:0])
	bodyRaw = body.RawBytes()
	innerRaw = inner.RawBytes()

	// compare token
	if !bytes.Equal(bodyRaw[:16], (*s.localToken)[:]) {
		inner.Free()
		body.Free()
		return nil, cipherset.ErrInvalidPacket
	}

	// copy nonce
	copy(nonce[:], bodyRaw[16:16+4])

	{ // verify hmac
		mac := bodyRaw[16+4+innerLen:]

		macKey := append(s.lineDecryptionKey, nonce[:4]...)

		h := hmac.New(sha256.New, macKey)
		h.Write(bodyRaw[16+4 : 16+4+innerLen])
		if subtle.ConstantTimeCompare(mac, fold(h.Sum(nil), 4)) != 1 {
			inner.Free()
			body.Free()
			return nil, cipherset.ErrInvalidPacket
		}
	}

	{ // decrypt inner
		aesBlock, err := aes.NewCipher(s.lineDecryptionKey)
		if err != nil {
			inner.Free()
			body.Free()
			return nil, err
		}

		aes := Cipher.NewCTR(aesBlock, nonce[:])
		if aes == nil {
			inner.Free()
			body.Free()
			return nil, cipherset.ErrInvalidPacket
		}

		aes.XORKeyStream(innerRaw, bodyRaw[16+4:16+4+innerLen])
	}

	innerPkt, err := lob.Decode(inner)
	if err != nil {
		inner.Free()
		body.Free()
		return nil, err
	}

	inner.Free()
	body.Free()

	return innerPkt, nil
}
コード例 #7
0
ファイル: testing.go プロジェクト: utamaro/gogotelehash
func (s *cipherTestSuite) TestPacketEncryption() {
	var (
		assert = s.Assertions
		c      = s.cipher
	)

	var (
		ka  cipherset.Key
		kb  cipherset.Key
		sa  cipherset.State
		sb  cipherset.State
		ha  cipherset.Handshake
		hb  cipherset.Handshake
		pkt *lob.Packet
		box []byte
		err error
		ok  bool
	)

	ka, err = c.GenerateKey()
	assert.NoError(err)
	kb, err = c.GenerateKey()
	assert.NoError(err)

	sa, err = c.NewState(ka)
	assert.NoError(err)
	sb, err = c.NewState(kb)
	assert.NoError(err)

	err = sa.SetRemoteKey(kb)
	assert.NoError(err)
	box, err = sa.EncryptHandshake(1, nil)
	assert.NoError(err)
	hb, err = c.DecryptHandshake(kb, box)
	assert.NoError(err)
	ok = sb.ApplyHandshake(hb)
	assert.True(ok)
	box, err = sb.EncryptHandshake(1, nil)
	assert.NoError(err)
	ha, err = c.DecryptHandshake(ka, box)
	assert.NoError(err)
	ok = sa.ApplyHandshake(ha)
	assert.True(ok)

	pkt = lob.New([]byte("Hello world!"))
	pkt.Header().SetInt("foo", 0xbeaf)
	pkt, err = sa.EncryptPacket(pkt)
	assert.NoError(err)
	assert.NotNil(pkt)
	assert.Nil(pkt.Header().Bytes)
	assert.True(pkt.Header().IsZero())
	assert.NotEmpty(pkt.Body)

	pkt, err = sb.DecryptPacket(pkt)
	assert.NoError(err)
	assert.NotNil(pkt)
	assert.Nil(pkt.Header().Bytes)
	assert.Equal(&lob.Header{Extra: map[string]interface{}{"foo": 0xbeaf}}, pkt.Header())
	assert.Equal([]byte("Hello world!"), pkt.Body(nil))

	pkt = lob.New([]byte("Bye world!"))
	pkt.Header().SetInt("bar", 0xdead)
	pkt, err = sb.EncryptPacket(pkt)
	assert.NoError(err)
	assert.NotNil(pkt)
	assert.Nil(pkt.Header().Bytes)
	assert.True(pkt.Header().IsZero())
	assert.NotEmpty(pkt.Body)

	pkt, err = sa.DecryptPacket(pkt)
	assert.NoError(err)
	assert.NotNil(pkt)
	assert.Nil(pkt.Header().Bytes)
	assert.Equal(&lob.Header{Extra: map[string]interface{}{"bar": 0xdead}}, pkt.Header())
	assert.Equal([]byte("Bye world!"), pkt.Body(nil))
}
コード例 #8
0
ファイル: cs3a_cipher.go プロジェクト: utamaro/gogotelehash
func (s *state) DecryptPacket(pkt *lob.Packet) (*lob.Packet, error) {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	if !s.CanDecryptPacket() {
		return nil, cipherset.ErrInvalidState
	}
	if pkt == nil {
		return nil, nil
	}

	if !pkt.Header().IsZero() || pkt.BodyLen() < lenToken+lenNonce {
		return nil, cipherset.ErrInvalidPacket
	}

	var (
		nonce    [lenNonce]byte
		bodyRaw  []byte
		innerRaw []byte
		innerPkt *lob.Packet
		body     = bufpool.New()
		inner    = bufpool.New()
		ok       bool
	)

	pkt.Body(body.SetLen(pkt.BodyLen()).RawBytes()[:0])
	bodyRaw = body.RawBytes()
	innerRaw = inner.RawBytes()

	// compare token
	if !bytes.Equal(bodyRaw[:lenToken], (*s.localToken)[:]) {
		inner.Free()
		body.Free()
		return nil, cipherset.ErrInvalidPacket
	}

	// copy nonce
	copy(nonce[:], bodyRaw[lenToken:lenToken+lenNonce])

	// decrypt inner packet
	innerRaw, ok = box.OpenAfterPrecomputation(
		innerRaw[:0], bodyRaw[lenToken+lenNonce:], &nonce, s.lineDecryptionKey)
	if !ok {
		inner.Free()
		body.Free()
		return nil, cipherset.ErrInvalidPacket
	}
	inner.SetLen(len(innerRaw))

	innerPkt, err := lob.Decode(inner)
	if err != nil {
		inner.Free()
		body.Free()
		return nil, err
	}

	inner.Free()
	body.Free()

	return innerPkt, nil
}