<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package kbcmf

import (
	"bytes"
	"crypto/hmac"
	"golang.org/x/crypto/nacl/secretbox"
	"io"
	"io/ioutil"
)

type decryptState int

const (
	stateHeader      decryptState = iota
	stateBody        decryptState = iota
	stateEndOfStream decryptState = iota
)

type decryptStream struct {
	ring       Keyring
	fmps       *framedMsgpackStream
	err        error
	state      decryptState
	keys       *receiverKeysPlaintext
	sessionKey SymmetricKey
	buf        []byte
}

func (ds *decryptStream) Read(b []byte) (n int, err error) {
	for n == 0 && err == nil {
		n, err = ds.read(b)
	}
	if err == io.EOF && ds.state != stateEndOfStream {
		err = io.ErrUnexpectedEOF
	}
	return n, err
}

func (ds *decryptStream) read(b []byte) (n int, err error) {

	// Handle the case of a previous error. Just return the error
	// again.
	if ds.err != nil {
		return 0, ds.err
	}

	// Handle the case first of a previous read that couldn't put all
	// of its data into the outgoing buffer.
	if len(ds.buf) > 0 {
		n = copy(b, ds.buf)
		ds.buf = ds.buf[n:]
		return n, nil
	}

	// We have three states we can be in, but we can definitely
	// fall through during one read, so be careful.

	if ds.state == stateHeader {
		if ds.err = ds.readHeader(); ds.err != nil {
			return 0, ds.err
		}
		ds.state = stateBody
	}

	if ds.state == stateBody {
		var last bool
		n, last, ds.err = ds.readBlock(b)
		if ds.err != nil {
			return 0, ds.err
		}

		if last {
			ds.state = stateEndOfStream
		}
	}

	if ds.state == stateEndOfStream {
		ds.err = ds.assertEndOfStream()
		if ds.err != nil {
			return 0, ds.err
		}
	}

	return n, nil
}

func (ds *decryptStream) readHeader() error {
	var hdr EncryptionHeader
	seqno, err := ds.fmps.Read(&hdr)
	if err != nil {
		return err
	}
	hdr.seqno = seqno
	return ds.processEncryptionHeader(&hdr)
}

func (ds *decryptStream) readBlock(b []byte) (n int, lastBlock bool, err error) {
	var eb EncryptionBlock
	var seqno PacketSeqno
	seqno, err = ds.fmps.Read(&eb)
	if err != nil {
		return 0, false, err
	}
	eb.seqno = seqno
	var plaintext []byte
	plaintext, err = ds.processEncryptionBlock(&eb)
	if err != nil {
		return 0, false, err
	}
	if plaintext == nil {
		return 0, true, err
	}

	// Copy as much as we can into the given outbuffer
	n = copy(b, plaintext)
	// Leave the remainder for a subsequent read
	ds.buf = plaintext[n:]

	return n, false, err
}

func (ds *decryptStream) assertEndOfStream() error {
	var i interface{}
	_, err := ds.fmps.Read(&i)
	if err == nil {
		err = ErrTrailingGarbage
	}
	return err
}

func (ds *decryptStream) tryVisibileReceivers(hdr *EncryptionHeader, nonce *Nonce, ephemeralKey BoxPublicKey) (BoxSecretKey, []byte, int, error) {
	var kids [][]byte
	for _, r := range hdr.Receivers {
		if r.KID != nil {
			kids = append(kids, r.KID)
		}
	}

	i, sk := ds.ring.LookupBoxSecretKey(kids)
	if i < 0 || sk == nil {
		return nil, nil, -1, nil
	}

	// Decrypt the sender's public key
	nonce.writeCounter32(uint32(2 * i))
	senderPublicRawKey, err := sk.Unbox(ephemeralKey, nonce, hdr.Receivers[i].Sender)
	if err != nil {
		return nil, nil, -1, err
	}
	return sk, senderPublicRawKey, i, err
}

func (ds *decryptStream) tryHiddenReceivers(hdr *EncryptionHeader, nonce *Nonce, ephemeralKey BoxPublicKey) (BoxSecretKey, []byte, int, error) {
	secretKeys := ds.ring.GetAllSecretKeys()
	var bpsk BoxPrecomputedSharedKey

	for _, secretKey := range secretKeys {
		bpsk = secretKey.Precompute(ephemeralKey)

		for i, r := range hdr.Receivers {
			// Decrypt the sender's public key
			nonce.writeCounter32(uint32(2 * i))
			senderPublicRawKey, err := bpsk.Unbox(nonce, r.Sender)
			if err == nil {
				return secretKey, senderPublicRawKey, i, nil
			}
		}
	}

	return nil, nil, -1, nil
}

func (ds *decryptStream) processEncryptionHeader(hdr *EncryptionHeader) error {
	if err := hdr.validate(); err != nil {
		return err
	}
	ephemeralKey := ds.ring.ImportEphemeralKey(hdr.Sender)
	if ephemeralKey == nil {
		return ErrBadEphemeralKey
	}

	var nonce Nonce
	copy(nonce[:], hdr.Nonce)

	secretKey, senderPublicRawKey, i, err := ds.tryVisibileReceivers(hdr, &nonce, ephemeralKey)
	if err != nil {
		return err
	}
	if secretKey == nil {
		secretKey, senderPublicRawKey, i, err = ds.tryHiddenReceivers(hdr, &nonce, ephemeralKey)
	}
	if err != nil {
		return err
	}
	if secretKey == nil || i < 0 {
		return ErrNoDecryptionKey<commit_msg>misspelling<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package kbcmf

import (
	"bytes"
	"crypto/hmac"
	"golang.org/x/crypto/nacl/secretbox"
	"io"
	"io/ioutil"
)

type decryptState int

const (
	stateHeader      decryptState = iota
	stateBody        decryptState = iota
	stateEndOfStream decryptState = iota
)

type decryptStream struct {
	ring       Keyring
	fmps       *framedMsgpackStream
	err        error
	state      decryptState
	keys       *receiverKeysPlaintext
	sessionKey SymmetricKey
	buf        []byte
}

func (ds *decryptStream) Read(b []byte) (n int, err error) {
	for n == 0 && err == nil {
		n, err = ds.read(b)
	}
	if err == io.EOF && ds.state != stateEndOfStream {
		err = io.ErrUnexpectedEOF
	}
	return n, err
}

func (ds *decryptStream) read(b []byte) (n int, err error) {

	// Handle the case of a previous error. Just return the error
	// again.
	if ds.err != nil {
		return 0, ds.err
	}

	// Handle the case first of a previous read that couldn't put all
	// of its data into the outgoing buffer.
	if len(ds.buf) > 0 {
		n = copy(b, ds.buf)
		ds.buf = ds.buf[n:]
		return n, nil
	}

	// We have three states we can be in, but we can definitely
	// fall through during one read, so be careful.

	if ds.state == stateHeader {
		if ds.err = ds.readHeader(); ds.err != nil {
			return 0, ds.err
		}
		ds.state = stateBody
	}

	if ds.state == stateBody {
		var last bool
		n, last, ds.err = ds.readBlock(b)
		if ds.err != nil {
			return 0, ds.err
		}

		if last {
			ds.state = stateEndOfStream
		}
	}

	if ds.state == stateEndOfStream {
		ds.err = ds.assertEndOfStream()
		if ds.err != nil {
			return 0, ds.err
		}
	}

	return n, nil
}

func (ds *decryptStream) readHeader() error {
	var hdr EncryptionHeader
	seqno, err := ds.fmps.Read(&hdr)
	if err != nil {
		return err
	}
	hdr.seqno = seqno
	return ds.processEncryptionHeader(&hdr)
}

func (ds *decryptStream) readBlock(b []byte) (n int, lastBlock bool, err error) {
	var eb EncryptionBlock
	var seqno PacketSeqno
	seqno, err = ds.fmps.Read(&eb)
	if err != nil {
		return 0, false, err
	}
	eb.seqno = seqno
	var plaintext []byte
	plaintext, err = ds.processEncryptionBlock(&eb)
	if err != nil {
		return 0, false, err
	}
	if plaintext == nil {
		return 0, true, err
	}

	// Copy as much as we can into the given outbuffer
	n = copy(b, plaintext)
	// Leave the remainder for a subsequent read
	ds.buf = plaintext[n:]

	return n, false, err
}

func (ds *decryptStream) assertEndOfStream() error {
	var i interface{}
	_, err := ds.fmps.Read(&i)
	if err == nil {
		err = ErrTrailingGarbage
	}
	return err
}

func (ds *decryptStream) tryVisibleReceivers(hdr *EncryptionHeader, nonce *Nonce, ephemeralKey BoxPublicKey) (BoxSecretKey, []byte, int, error) {
	var kids [][]byte
	for _, r := range hdr.Receivers {
		if r.KID != nil {
			kids = append(kids, r.KID)
		}
	}

	i, sk := ds.ring.LookupBoxSecretKey(kids)
	if i < 0 || sk == nil {
		return nil, nil, -1, nil
	}

	// Decrypt the sender's public key
	nonce.writeCounter32(uint32(2 * i))
	senderPublicRawKey, err := sk.Unbox(ephemeralKey, nonce, hdr.Receivers[i].Sender)
	if err != nil {
		return nil, nil, -1, err
	}
	return sk, senderPublicRawKey, i, err
}

func (ds *decryptStream) tryHiddenReceivers(hdr *EncryptionHeader, nonce *Nonce, ephemeralKey BoxPublicKey) (BoxSecretKey, []byte, int, error) {
	secretKeys := ds.ring.GetAllSecretKeys()
	var bpsk BoxPrecomputedSharedKey

	for _, secretKey := range secretKeys {
		bpsk = secretKey.Precompute(ephemeralKey)

		for i, r := range hdr.Receivers {
			// Decrypt the sender's public key
			nonce.writeCounter32(uint32(2 * i))
			senderPublicRawKey, err := bpsk.Unbox(nonce, r.Sender)
			if err == nil {
				return secretKey, senderPublicRawKey, i, nil
			}
		}
	}

	return nil, nil, -1, nil
}

func (ds *decryptStream) processEncryptionHeader(hdr *EncryptionHeader) error {
	if err := hdr.validate(); err != nil {
		return err
	}
	ephemeralKey := ds.ring.ImportEphemeralKey(hdr.Sender)
	if ephemeralKey == nil {
		return ErrBadEphemeralKey
	}

	var nonce Nonce
	copy(nonce[:], hdr.Nonce)

	secretKey, senderPublicRawKey, i, err := ds.tryVisibleReceivers(hdr, &nonce, ephemeralKey)
	if err != nil {
		return err
	}
	if secretKey == nil {
		secretKey, senderPublicRawKey, i, err = ds.tryHiddenReceivers(hdr, &nonce, ephemeralKey)
	}
	if err != nil {
		return err
	}
	if secretKey == nil || i < 0 {
		return ErrNoDecryptionKey
{'fraction_non_alphanumeric': 0.1191006233303651, 'fraction_numerical': 0.006233303650934996, 'mean_word_length': 3.313490158425348, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2086760', 'n_tokens_mistral': 3553, 'n_tokens_neox': 3312, 'n_words': 993}