Beispiel #1
0
func (c *cipher) DecryptMessage(localKey, remoteKey cipherset.Key, p []byte) ([]byte, error) {
	if len(p) < 21+4+4 {
		return nil, cipherset.ErrInvalidMessage
	}

	var (
		ctLen            = len(p) - (21 + 4 + 4)
		out              = make([]byte, ctLen)
		cs1aLocalKey, _  = localKey.(*key)
		cs1aRemoteKey, _ = remoteKey.(*key)
		remoteLineKey    = p[:21]
		iv               = p[21 : 21+4]
		ciphertext       = p[21+4 : 21+4+ctLen]
		mac              = p[21+4+ctLen:]
	)

	if cs1aLocalKey == nil || cs1aRemoteKey == nil {
		return nil, cipherset.ErrInvalidState
	}

	{ // verify mac
		macKey := ecdh.ComputeShared(secp160r1.P160(),
			cs1aRemoteKey.pub.x, cs1aRemoteKey.pub.y, cs1aLocalKey.prv.d)
		macKey = append(macKey, iv...)

		h := hmac.New(sha256.New, macKey)
		h.Write(p[:21+4+ctLen])
		if subtle.ConstantTimeCompare(mac, fold(h.Sum(nil), 4)) != 1 {
			return nil, cipherset.ErrInvalidMessage
		}
	}

	{ // descrypt inner
		ephemX, ephemY := eccp.Unmarshal(secp160r1.P160(), remoteLineKey)
		if ephemX == nil || ephemY == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		shared := ecdh.ComputeShared(secp160r1.P160(), ephemX, ephemY, cs1aLocalKey.prv.d)
		if shared == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aharedSum := sha256.Sum256(shared)
		aesKey := fold(aharedSum[:], 16)
		if aesKey == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aesBlock, err := aes.NewCipher(aesKey)
		if err != nil {
			return nil, cipherset.ErrInvalidMessage
		}

		var aesIv [16]byte
		copy(aesIv[:], iv)

		aes := Cipher.NewCTR(aesBlock, aesIv[:])
		if aes == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aes.XORKeyStream(out, ciphertext)
	}

	return out, nil
}
Beispiel #2
0
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
}
Beispiel #3
0
func (s *state) EncryptMessage(in []byte) ([]byte, error) {
	var (
		ctLen = len(in)
		out   = bufpool.New().SetLen(21 + 4 + ctLen + 4)
		raw   = out.RawBytes()
	)

	if !s.CanEncryptMessage() {
		panic("unable to encrypt message")
	}

	// copy public senderLineKey
	copy(raw[:21], s.localLineKey.Public())

	// copy the nonce
	_, err := io.ReadFull(rand.Reader, raw[21:21+4])
	if err != nil {
		return nil, err
	}

	{ // encrypt inner
		shared := ecdh.ComputeShared(
			secp160r1.P160(),
			s.remoteKey.pub.x, s.remoteKey.pub.y,
			s.localLineKey.prv.d)
		if shared == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aharedSum := sha256.Sum256(shared)
		aesKey := fold(aharedSum[:], 16)
		if aesKey == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aesBlock, err := aes.NewCipher(aesKey)
		if err != nil {
			return nil, err
		}

		var aesIv [16]byte
		copy(aesIv[:], raw[21:21+4])

		aes := Cipher.NewCTR(aesBlock, aesIv[:])
		if aes == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aes.XORKeyStream(raw[21+4:21+4+ctLen], in)
	}

	{ // compute HMAC
		macKey := ecdh.ComputeShared(secp160r1.P160(),
			s.remoteKey.pub.x, s.remoteKey.pub.y, s.localKey.prv.d)
		macKey = append(macKey, raw[21:21+4]...)

		h := hmac.New(sha256.New, macKey)
		h.Write(raw[:21+4+ctLen])
		sum := h.Sum(nil)
		copy(raw[21+4+ctLen:], fold(sum, 4))
	}

	out.SetLen(21 + 4 + ctLen + 4)

	return out.Get(nil), nil
}
Beispiel #4
0
func (s *state) EncryptPacket(pkt *lob.Packet) (*lob.Packet, error) {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	var (
		outer   *lob.Packet
		inner   *bufpool.Buffer
		body    *bufpool.Buffer
		bodyRaw []byte
		nonce   [16]byte
		ctLen   int
		err     error
	)

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

	// encode inner packet
	inner, err = lob.Encode(pkt)
	if err != nil {
		return nil, err
	}

	ctLen = inner.Len()

	// make nonce
	_, err = io.ReadFull(rand.Reader, nonce[:4])
	if err != nil {
		return nil, err
	}

	// alloc enough space
	body = bufpool.New().SetLen(16 + 4 + ctLen + 4)
	bodyRaw = body.RawBytes()

	// copy token
	copy(bodyRaw[:16], (*s.remoteToken)[:])

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

	{ // encrypt inner
		aesBlock, err := aes.NewCipher(s.lineEncryptionKey)
		if err != nil {
			return nil, err
		}

		aes := Cipher.NewCTR(aesBlock, nonce[:])
		if aes == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aes.XORKeyStream(bodyRaw[16+4:16+4+ctLen], inner.RawBytes())
	}

	{ // compute HMAC
		macKey := append(s.lineEncryptionKey, bodyRaw[16:16+4]...)

		h := hmac.New(sha256.New, macKey)
		h.Write(bodyRaw[16+4 : 16+4+ctLen])
		sum := h.Sum(nil)
		copy(bodyRaw[16+4+ctLen:], fold(sum, 4))
	}

	outer = lob.New(body.RawBytes())
	inner.Free()
	body.Free()

	return outer, nil
}
Beispiel #5
0
func (c *cipher) DecryptHandshake(localKey cipherset.Key, p []byte) (cipherset.Handshake, error) {
	if len(p) < 21+4+4 {
		return nil, cipherset.ErrInvalidMessage
	}

	var (
		ctLen             = len(p) - (21 + 4 + 4)
		out               = bufpool.New()
		cs1aLocalKey, _   = localKey.(*key)
		remoteKey         *key
		remoteLineKey     *key
		hshake            *handshake
		remoteLineKeyData = p[:21]
		iv                = p[21 : 21+4]
		ciphertext        = p[21+4 : 21+4+ctLen]
		mac               = p[21+4+ctLen:]
	)

	if cs1aLocalKey == nil {
		return nil, cipherset.ErrInvalidState
	}

	{ // decrypt inner
		ephemX, ephemY := eccp.Unmarshal(secp160r1.P160(), remoteLineKeyData)
		if ephemX == nil || ephemY == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		shared := ecdh.ComputeShared(secp160r1.P160(), ephemX, ephemY, cs1aLocalKey.prv.d)
		if shared == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aharedSum := sha256.Sum256(shared)
		aesKey := fold(aharedSum[:], 16)
		if aesKey == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aesBlock, err := aes.NewCipher(aesKey)
		if err != nil {
			return nil, cipherset.ErrInvalidMessage
		}

		var aesIv [16]byte
		copy(aesIv[:], iv)

		aes := Cipher.NewCTR(aesBlock, aesIv[:])
		if aes == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		out.SetLen(ctLen)
		aes.XORKeyStream(out.RawBytes(), ciphertext)
		remoteLineKey = &key{}
		remoteLineKey.pub.x, remoteLineKey.pub.y = ephemX, ephemY
	}

	{ // decode inner
		inner, err := lob.Decode(out)
		if err != nil {
			return nil, cipherset.ErrInvalidMessage
		}

		at, hasAt := inner.Header().GetUint32("at")
		if !hasAt {
			return nil, cipherset.ErrInvalidMessage
		}

		delete(inner.Header().Extra, "at")

		parts, err := cipherset.PartsFromHeader(inner.Header())
		if err != nil {
			return nil, cipherset.ErrInvalidMessage
		}

		if inner.BodyLen() != 21 {
			return nil, cipherset.ErrInvalidMessage
		}

		remoteKey = &key{}
		remoteKey.pub.x, remoteKey.pub.y = eccp.Unmarshal(secp160r1.P160(), inner.Body(nil))
		if !remoteKey.CanEncrypt() {
			return nil, cipherset.ErrInvalidMessage
		}

		hshake = &handshake{}
		hshake.at = at
		hshake.key = remoteKey
		hshake.lineKey = remoteLineKey
		hshake.parts = parts
	}

	{ // verify mac
		var nonce [16]byte
		copy(nonce[:], iv)

		macKey := ecdh.ComputeShared(secp160r1.P160(),
			remoteKey.pub.x, remoteKey.pub.y, cs1aLocalKey.prv.d)
		macKey = append(macKey, nonce[:]...)

		h := hmac.New(sha256.New, macKey)
		h.Write(p[:21+4+ctLen])
		if subtle.ConstantTimeCompare(mac, fold(h.Sum(nil), 4)) != 1 {
			return nil, cipherset.ErrInvalidMessage
		}
	}

	return hshake, nil
}