Beispiel #1
0
func (kx *KeyExchange) exchange2() ([]byte, error) {
	reply, err := kx.meetingPlace.Exchange(kx.Log, kx.meeting2[:], kx.message2[:], kx.ShutdownChan)
	if err != nil {
		return nil, err
	}

	var nonce [24]byte
	if len(reply) < len(nonce) {
		return nil, errors.New("panda: meeting point reply too small")
	}

	if kx.sharedKey[0] == 0 && kx.sharedKey[1] == 0 {
		panic("here")
	}
	copy(nonce[:], reply)
	message, ok := secretbox.Open(nil, reply[24:], &nonce, &kx.sharedKey)
	if !ok {
		return nil, errors.New("panda: peer's message cannot be authenticated")
	}

	if len(message) < 4 {
		return nil, errors.New("panda: peer's message is invalid")
	}
	l := binary.LittleEndian.Uint32(message)
	message = message[4:]
	if l > uint32(len(message)) {
		return nil, errors.New("panda: peer's message is truncated")
	}
	message = message[:int(l)]
	return message, nil
}
Beispiel #2
0
// OpenWithKey is the same as Open, but a different key can be passed in.
func (s *Service) OpenWithKey(e *SealedBytes, secretKey *[SecretKeyLength]byte) (byt []byte, err error) {
	// once function is complete, check if we are returning err or not.
	// if we are, return emit a failure metric, if not a success metric.
	defer func() {
		if err == nil {
			s.metricsClient.Inc("success", 1, 1)
		} else {
			s.metricsClient.Inc("failure", 1, 1)
		}
	}()

	// check that we either initialized with a key or one was passed in
	if secretKey == nil {
		return nil, fmt.Errorf("secret key is nil")
	}

	// convert nonce to an array
	nonce, err := nonceSliceToArray(e.Nonce)
	if err != nil {
		return nil, err
	}

	// decrypt
	var decrypted []byte
	decrypted, ok := secretbox.Open(decrypted, e.Ciphertext, nonce, secretKey)
	if !ok {
		return nil, fmt.Errorf("unable to decrypt message")
	}

	return decrypted, nil
}
Beispiel #3
0
func (nd *NaClDecryptor) decrypt(buf []byte) ([]byte, bool) {
	seqNoAndDF := binary.BigEndian.Uint64(buf[:8])
	df := (seqNoAndDF & (1 << 63)) != 0
	seqNo := seqNoAndDF & ((1 << 63) - 1)
	var di *NaClDecryptorInstance
	if df {
		di = nd.instanceDF
	} else {
		di = nd.instance
	}
	binary.BigEndian.PutUint64(di.nonce[16:24], seqNoAndDF)
	result, success := secretbox.Open(nil, buf[8:], &di.nonce, nd.sessionKey)
	if !success {
		return nil, false
	}
	// Drop duplicates. We do this *after* decryption since we must
	// not advance our state unless decryption succeeded. Doing so
	// would open an easy attack vector where an adversary could
	// inject a packet with a sequence number of (1 << 63) - 1,
	// causing all subsequent genuine packets to get dropped.
	offset, usedOffsets := di.advanceState(seqNo)
	if usedOffsets == nil || usedOffsets.Contains(offset) {
		// We have detected a possible replay attack, but it is
		// possible we may have just received a very old packet, or
		// duplication may have occurred in the network. So let's just
		// drop the packet silently.
		return nil, true
	}
	usedOffsets.Add(offset)
	return result, success
}
Beispiel #4
0
func (receiver *EncryptedTCPReceiver) Decode(msg []byte) ([]byte, error) {
	decodedMsg, success := secretbox.Open(nil, msg, &receiver.state.nonce, receiver.state.sessionKey)
	if !success {
		return nil, fmt.Errorf("Unable to decrypt TCP msg")
	}
	receiver.state.advance()
	return decodedMsg, nil
}
Beispiel #5
0
// decrypt extracts the nonce from the ciphertext, and attempts to
// decrypt with NaCl's secretbox.
func decrypt(key *[keySize]byte, in []byte) ([]byte, bool) {
	if len(in) < nonceSize {
		return nil, false
	}
	var nonce [nonceSize]byte
	copy(nonce[:], in)
	return secretbox.Open(nil, in[nonceSize:], &nonce, key)
}
Beispiel #6
0
// trySavedKeys tries to decrypt ciphertext using keys saved for missing messages.
func (r *Ratchet) trySavedKeys(ciphertext []byte) ([]byte, error) {
	if len(ciphertext) < sealedHeaderSize {
		return nil, errors.New("ratchet: header too small to be valid")
	}

	sealedHeader := ciphertext[:sealedHeaderSize]
	var nonce [24]byte
	copy(nonce[:], sealedHeader)
	sealedHeader = sealedHeader[len(nonce):]

	for headerKey, messageKeys := range r.saved {
		header, ok := secretbox.Open(nil, sealedHeader, &nonce, &headerKey)
		if !ok {
			continue
		}
		if len(header) != headerSize {
			continue
		}
		msgNum := binary.LittleEndian.Uint32(header[:4])
		msgKey, ok := messageKeys[msgNum]
		if !ok {
			// This is a fairly common case: the message key might
			// not have been saved because it's the next message
			// key.
			return nil, nil
		}

		sealedMessage := ciphertext[sealedHeaderSize:]
		copy(nonce[:], header[nonceInHeaderOffset:])
		msg, ok := secretbox.Open(nil, sealedMessage, &nonce, &msgKey.key)
		if !ok {
			return nil, errors.New("ratchet: corrupt message")
		}
		delete(messageKeys, msgNum)
		if len(messageKeys) == 0 {
			delete(r.saved, headerKey)
		}
		return msg, nil
	}

	return nil, nil
}
Beispiel #7
0
func (c *Conn) Read(out []byte) (n int, err error) {
	if len(c.readPending) > 0 {
		n = copy(out, c.readPending)
		c.readPending = c.readPending[n:]
		return
	}

	if c.readBuffer == nil {
		c.readBuffer = make([]byte, blockSize+2)
	}

	if _, err := io.ReadFull(c.conn, c.readBuffer[:2]); err != nil {
		return 0, err
	}
	n = int(c.readBuffer[0]) | int(c.readBuffer[1])<<8
	if n > len(c.readBuffer) {
		return 0, errors.New("transport: peer's message too large for Read")
	}
	if _, err := io.ReadFull(c.conn, c.readBuffer[:n]); err != nil {
		return 0, err
	}

	var ok bool
	if len(out) >= n-secretbox.Overhead {
		// We can decrypt directly into the output buffer.
		out, ok = secretbox.Open(out[:0], c.readBuffer[:n], &c.readSequence, &c.readKey)
		n = len(out)
	} else {
		// We need to decrypt into a side buffer and copy a prefix of
		// the result into the caller's buffer.
		c.decryptBuffer, ok = secretbox.Open(c.decryptBuffer[:0], c.readBuffer[:n], &c.readSequence, &c.readKey)
		n = copy(out, c.decryptBuffer)
		c.readPending = c.decryptBuffer[n:]
	}
	incSequence(&c.readSequence)
	if !ok {
		c.readPending = c.readPending[:0]
		return 0, errors.New("transport: bad MAC")
	}

	return
}
Beispiel #8
0
func (c *Conn) decrypt(data []byte) ([]byte, error) {
	if !c.readKeyValid {
		return data, nil
	}

	decrypted, ok := secretbox.Open(nil, data, &c.readSequence, &c.readKey)
	incSequence(&c.readSequence)
	if !ok {
		return nil, errors.New("transport: bad MAC")
	}
	return decrypted, nil
}
Beispiel #9
0
func decrypt(key, ciphertext []byte) ([]byte, error) {
	if len(ciphertext) < nonceLen+secretbox.Overhead {
		return nil, fmt.Errorf("message too short")
	}
	var nonce [nonceLen]byte
	copy(nonce[:], ciphertext)
	ciphertext = ciphertext[nonceLen:]
	text, ok := secretbox.Open(nil, ciphertext, &nonce, makeKey(key))
	if !ok {
		return nil, fmt.Errorf("decryption failure")
	}
	return text, nil
}
Beispiel #10
0
// Decrypt decrypts a message using XSalsa20-Poly1305 and outputs it to dst.
// Returns false if decryption failed (authentication tag mismatch).
func (sb *secretBoxMode) Decrypt(dst []byte, src []byte, nonce []byte) bool {
	if len(src) <= sb.Overhead() {
		panic("cryptstate: bad src")
	}

	if len(nonce) != 24 {
		panic("cryptstate: bad nonce length")
	}

	noncePtr := (*[24]byte)(unsafe.Pointer(&nonce[0]))
	_, ok := secretbox.Open(dst[0:0], src, noncePtr, &sb.key)
	return ok
}
Beispiel #11
0
func DecryptPrefixNonce(ciphertxt []byte, secret *[32]byte) ([]byte, bool) {
	if len(ciphertxt) < secretbox.Overhead+24 {
		return nil, false
	}
	// There is no way to nicely convert from a slice to an
	// array. So have to used the following loop.
	var nonce [24]byte
	for idx, e := range ciphertxt[0:24] {
		nonce[idx] = e
	}
	ciphertxt = ciphertxt[24:]
	return secretbox.Open(nil, ciphertxt, &nonce, secret)
}
Beispiel #12
0
// TODO : consider caching the last deciphered chunk
func (this *CipherReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
	log.Printf("ReadAt len(p):%v, off:%v\n", len(p), off)
	// read Nonce if not yet read
	if this.Nonce == nil {
		this.Nonce = &[24]byte{}
		_, err := this.Reader.ReadAt(this.Nonce[:], 0)
		if err != nil {
			return 0, err
		}
	}
	// ...
	for len(p) > 0 {
		chunkIndex := off / (this.ChunkSize - secretbox.Overhead)
		chunkStart := chunkIndex * this.ChunkSize
		offChunk := off - chunkIndex*(this.ChunkSize-secretbox.Overhead)
		log.Printf(" - chunkIndex: %v, chunkStart: %v, offChunk: %v\n", chunkIndex, chunkStart, offChunk)

		// compute nonce, basically a base 256 addition operation
		var nonce [24]byte
		copy(nonce[:], this.Nonce[:])
		{
			ci := chunkIndex // copy
			i := 0
			carry := int16(0)
			for ci > 0 || carry > 0 {
				sum := int16(ci % 256)
				sum += int16(nonce[i])
				sum += int16(carry)
				nonce[i] = byte(sum % 256)
				carry = int16(sum >> 8)
				ci >>= 8
				i++
			}
			log.Printf(" - nonce: %v", nonce)
		}
		numRead, err := this.Reader.ReadAt(this.Chunk, 24+chunkStart)
		if err != nil && err != io.EOF {
			return n, err
		}
		openedChunk, ok := secretbox.Open(nil, this.Chunk[:numRead], &nonce, this.Key)
		//fmt.Println(colors.Cyan("nonce:", nonce, " key:", this.Key, " numRead:", numRead))
		if !ok {
			return n, errors.New(fmt.Sprintf("Failed to decipher chunk %v", chunkIndex))
		}
		copied := copy(p, openedChunk[offChunk:])
		p = p[copied:]
		n += copied
		off += int64(copied)
	}
	return n, nil
}
Beispiel #13
0
func (s *Convergent) Get(key []byte) ([]byte, error) {
	boxedkey := s.computeBoxedKey(key)
	box, err := s.untrusted.Get(boxedkey)
	if err != nil {
		return nil, err
	}

	nonce := s.makeNonce(key)
	plain, ok := secretbox.Open(nil, box, nonce, s.secret)
	if !ok {
		return nil, Corrupt{Key: key}
	}
	return plain, nil
}
Beispiel #14
0
// decrypt extracts the nonce from the ciphertext, and attempts to
// decrypt with NaCl's secretbox.
func decrypt(key *[keySize]byte, message []byte) ([]byte, error) {
	if len(message) < (nonceSize + secretbox.Overhead) {
		return nil, ErrDecrypt
	}

	var nonce [nonceSize]byte
	copy(nonce[:], message[:nonceSize])
	out, ok := secretbox.Open(nil, message[nonceSize:], &nonce, key)
	if !ok {
		return nil, ErrDecrypt
	}

	return out, nil
}
Beispiel #15
0
func unbox(key *[32]byte, body []byte) ([]byte, error) {
	var nonce [24]byte
	if len(body) < len(nonce)+secretbox.Overhead+2 {
		return nil, errors.New("panda: reply from server is too short to be valid")
	}
	copy(nonce[:], body)
	unsealed, ok := secretbox.Open(nil, body[len(nonce):], &nonce, key)
	if !ok {
		return nil, errors.New("panda: failed to authenticate reply from server")
	}
	l := int(unsealed[0]) | int(unsealed[1])<<8
	unsealed = unsealed[2:]
	if l > len(unsealed) {
		return nil, errors.New("panda: corrupt but authentic message found")
	}
	return unsealed[:l], nil
}
Beispiel #16
0
// importTombFile decrypts a file with the given path, using a hex-encoded key
// and loads the client state from the result.
func (c *client) importTombFile(stateFile *disk.StateFile, keyHex, path string) error {
	keyBytes, err := hex.DecodeString(keyHex)
	if err != nil {
		return err
	}

	var key [32]byte
	var nonce [24]byte
	if len(keyBytes) != len(key) {
		return fmt.Errorf("Incorrect key length: %d (want %d)", len(keyBytes), len(key))
	}
	copy(key[:], keyBytes)

	tombBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}

	plaintext, ok := secretbox.Open(nil, tombBytes, &nonce, &key)
	if !ok {
		return errors.New("Incorrect key")
	}

	c.stateLock, err = stateFile.Lock(true /* create */)
	if c.stateLock == nil && err == nil {
		return errors.New("Output statefile is locked.")
	}
	if err != nil {
		return err
	}

	writerChan := make(chan disk.NewState)
	writerDone := make(chan struct{})
	go stateFile.StartWriter(writerChan, writerDone)

	writerChan <- disk.NewState{State: plaintext}
	close(writerChan)
	<-writerDone

	return nil
}
Beispiel #17
0
func (m *secretboxMode) Decrypt(encrypted []byte) ([]byte, bool) {
	var opened []byte
	var nonce [24]byte

	if len(encrypted) < 24 {
		log.Printf("secretbox: Not good: len (%d) < 24\n", len(encrypted))
		return nil, false
	}

	for i := 0; i < 24; i++ {
		nonce[i] = encrypted[len(encrypted)-24+i]
	}

	data := encrypted[:len(encrypted)-24]
	opened, ok := secretbox.Open(opened[:0], data, &nonce, &m.key)
	if !ok {
		log.Printf("secretbox: Not good: Open() returned false\n")
	}

	return opened, ok
}
Beispiel #18
0
func (c *client) loadState(b []byte, key *[32]byte) error {
	if len(b) < sCryptSaltLen+24*smearedCopies {
		return errors.New("state file is too small to be valid")
	}

	b = b[sCryptSaltLen:]

	var nonce [24]byte
	for i := 0; i < smearedCopies; i++ {
		for j := 0; j < 24; j++ {
			nonce[j] ^= b[24*i+j]
		}
	}

	b = b[24*smearedCopies:]
	plaintext, ok := secretbox.Open(nil, b, &nonce, key)
	if !ok {
		return badPasswordError
	}
	if len(plaintext) < 4 {
		return errors.New("state file corrupt")
	}
	length := binary.LittleEndian.Uint32(plaintext[:4])
	plaintext = plaintext[4:]
	if length > 1<<31 || length > uint32(len(plaintext)) {
		return errors.New("state file corrupt")
	}
	plaintext = plaintext[:int(length)]

	var state protos.State
	if err := proto.Unmarshal(plaintext, &state); err != nil {
		return err
	}

	if err := c.unmarshal(&state); err != nil {
		return err
	}
	return nil
}
Beispiel #19
0
func loadOldState(b []byte, key *[32]byte) (*State, error) {
	const (
		SCryptSaltLen = 32
		smearedCopies = 32768 / 24
	)

	if len(b) < SCryptSaltLen+24*smearedCopies {
		return nil, errors.New("state file is too small to be valid")
	}

	var nonce [24]byte
	for i := 0; i < smearedCopies; i++ {
		for j := 0; j < 24; j++ {
			nonce[j] ^= b[24*i+j]
		}
	}

	b = b[24*smearedCopies:]
	plaintext, ok := secretbox.Open(nil, b, &nonce, key)
	if !ok {
		return nil, BadPasswordError
	}
	if len(plaintext) < 4 {
		return nil, errors.New("state file corrupt")
	}
	length := binary.LittleEndian.Uint32(plaintext[:4])
	plaintext = plaintext[4:]
	if length > 1<<31 || length > uint32(len(plaintext)) {
		return nil, errors.New("state file corrupt")
	}
	plaintext = plaintext[:int(length)]

	var state State
	if err := proto.Unmarshal(plaintext, &state); err != nil {
		return nil, err
	}

	return &state, nil
}
Beispiel #20
0
func (s *httpService) getBackendSticky(req *http.Request) (*httputil.ClientConn, *http.Cookie) {
	cookie, err := req.Cookie(stickyCookie)
	if err != nil {
		return s.getNewBackendSticky()
	}

	data, err := base64.StdEncoding.DecodeString(cookie.Value)
	if err != nil {
		return s.getNewBackendSticky()
	}
	var nonce [24]byte
	if len(data) < len(nonce) {
		return s.getNewBackendSticky()
	}
	copy(nonce[:], data)
	res, ok := secretbox.Open(nil, data[len(nonce):], &nonce, s.cookieKey)
	if !ok {
		return s.getNewBackendSticky()
	}

	addr := string(res)
	ok = false
	for _, a := range s.ss.Addrs() {
		if a == addr {
			ok = true
			break
		}
	}
	if !ok {
		return s.getNewBackendSticky()
	}

	backend, err := net.Dial("tcp", string(addr))
	if err != nil {
		return s.getNewBackendSticky()
	}
	return httputil.NewClientConn(backend, nil), nil
}
Beispiel #21
0
func main() {
	runtime.GOMAXPROCS(2)
	flag.Parse()

	if len(*secret) == 0 {
		fmt.Fprintf(os.Stderr, "The shared secret must be given as --secret\n")
		os.Exit(2)
	}
	if len(*keyFile) == 0 {
		fmt.Fprintf(os.Stderr, "The path to a find containing the public key material to exchange must be given as --key-file\n")
		os.Exit(2)
	}

	pubKeyBytes, err := ioutil.ReadFile(*keyFile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to read key file: %s\n", err)
		os.Exit(2)
	}

	const maxBody = 4096
	if limit := maxBody - 24 - secretbox.Overhead; len(pubKeyBytes) > limit {
		fmt.Fprintf(os.Stderr, "--key-file is too large (%d bytes of a maximum of %d)\n", len(pubKeyBytes), limit)
		os.Exit(2)
	}

	// Run scrypt on a goroutine so that we can overlap it with the network
	// delay.
	keyChan := make(chan []byte)
	go deriveKey(keyChan, *secret)

	var dialer proxy.Dialer
	dialer = proxy.Direct
	if len(*torProxy) > 0 {
		fmt.Fprintf(os.Stderr, "Using SOCKS5 proxy at %s\n", *torProxy)
		dialer, err = proxy.SOCKS5("tcp", *torProxy, nil, dialer)
		if err != nil {
			panic(err)
		}
	}

	fmt.Fprintf(os.Stderr, "Starting TCP connection to %s\n", *server)
	rawConn, err := dialer.Dial("tcp", *server)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to connect to server: %s\n", err)
		os.Exit(2)
	}

	var conn net.Conn
	if *useTLS {
		hostname, _, err := net.SplitHostPort(*server)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to split %s into host and post: %s\n", *server, err)
			os.Exit(2)
		}
		tlsConn := tls.Client(rawConn, &tls.Config{
			ServerName: hostname,
		})
		fmt.Fprintf(os.Stderr, "Starting TLS handshake\n")
		if err := tlsConn.Handshake(); err != nil {
			rawConn.Close()
			fmt.Fprintf(os.Stderr, "TLS handshake failed: %s\n", err)
			os.Exit(2)
		}
		conn = tlsConn
	} else {
		conn = rawConn
	}
	defer conn.Close()

	var keySlice []byte
	select {
	case keySlice = <-keyChan:
	default:
		fmt.Fprintf(os.Stderr, "Waiting for key derivation to complete. This may take some time.\n")
		keySlice = <-keyChan
	}
	var key [32]byte
	copy(key[:], keySlice)

	mac := hmac.New(sha256.New, key[:])
	mac.Write(pubKeyBytes)
	nonceSlice := mac.Sum(nil)
	var nonce [24]byte
	copy(nonce[:], nonceSlice)

	box := make([]byte, len(nonce)+secretbox.Overhead+len(pubKeyBytes))
	copy(box, nonce[:])
	secretbox.Seal(box[len(nonce):len(nonce)], pubKeyBytes, &nonce, &key)

	h := sha256.New()
	h.Write(key[:])
	tag := h.Sum(nil)

	body := bytes.NewReader(box)
	request, err := http.NewRequest("POST", "http://"+*server+"/exchange/"+hex.EncodeToString(tag), body)
	if err != nil {
		panic(err)
	}
	request.ContentLength = int64(len(box))
	request.Header.Add("Content-Type", "application/octet-stream")

	request.Write(conn)
	fmt.Fprintf(os.Stderr, "Request sent. Waiting for HTTP reply\n")
	replyReader := bufio.NewReader(conn)

	response, err := http.ReadResponse(replyReader, request)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error reading reply from server: %s\n", err)
		os.Exit(2)
	}

	switch response.StatusCode {
	case 409:
		fmt.Fprintf(os.Stderr, "The transaction failed because this key has been used recently by two other parties.\n")
		os.Exit(2)
	case 204:
		fmt.Fprintf(os.Stderr, "Material submitted, but the other party has yet to start the process. Try again later with the same arguments.\n")
		os.Exit(1)
	case 200:
		r := &io.LimitedReader{R: response.Body, N: maxBody + 1}
		body, err := ioutil.ReadAll(r)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error reading from server: %s\n", err)
			os.Exit(2)
		}
		if len(body) > maxBody {
			fmt.Fprintf(os.Stderr, "Reply from server is too large\n")
			os.Exit(2)
		}
		if len(body) < len(nonce)+secretbox.Overhead {
			fmt.Fprintf(os.Stderr, "Reply from server is too short to be valid: %x\n", body)
			os.Exit(2)
		}
		copy(nonce[:], body)
		unsealed, ok := secretbox.Open(nil, body[len(nonce):], &nonce, &key)
		if !ok {
			fmt.Fprintf(os.Stderr, "Failed to authenticate reply from server\n")
			os.Exit(2)
		}
		os.Stdout.Write(unsealed)
	default:
		fmt.Fprintf(os.Stderr, "HTTP error from server: %s\n", response.Status)
		io.Copy(os.Stderr, response.Body)
		os.Exit(2)
	}
}
Beispiel #22
0
func saveDecrypted(c chan interface{}, outPath string, id uint64, in *os.File, detachment *pond.Message_Detachment, killChan chan bool) error {
	out, err := os.OpenFile(outPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		return errors.New("failed to open output: " + err.Error())
	}
	defer out.Close()

	var key [32]byte
	var nonce [24]byte

	blockSize := *detachment.ChunkSize + secretbox.Overhead
	if blockSize > 1<<20 {
		return errors.New("chunk size too large")
	}

	copy(key[:], detachment.Key)

	var bytesIn, bytesOut uint64
	buf := make([]byte, blockSize)
	var decrypted []byte
	var lastUpdate time.Time

BlockLoop:
	for {
		n, err := io.ReadFull(in, buf)
		switch err {
		case nil:
			break
		case io.ErrUnexpectedEOF, io.EOF:
			break BlockLoop
		default:
			return errors.New("failed to read from source: " + err.Error())
		}

		bytesIn += uint64(n)
		var ok bool
		decrypted, ok = secretbox.Open(decrypted[:0], buf, &nonce, &key)
		if !ok {
			os.Remove(outPath)
			return errors.New("input corrupt")
		}

		if bytesOut != *detachment.Size {
			if n := bytesOut + uint64(len(decrypted)); n > *detachment.Size {
				decrypted = decrypted[:*detachment.Size-bytesOut]
			}
			bytesOut += uint64(len(decrypted))

			if _, err := out.Write(decrypted); err != nil {
				return errors.New("failed to write to destination: " + err.Error())
			}
		}

		if bytesIn > *detachment.PaddedSize {
			// This means that we downloaded more bytes than we
			// expected.
			break
		}

		incNonce(&nonce)

		now := time.Now()
		if lastUpdate.IsZero() || now.Sub(lastUpdate) > 500*time.Millisecond {
			lastUpdate = now
			select {
			case c <- DetachmentProgress{
				id:    id,
				done:  bytesIn,
				total: *detachment.PaddedSize,
			}:
				break
			default:
			}
		}

		select {
		case <-killChan:
			os.Remove(outPath)
			return backgroundCanceledError
		default:
			break
		}
	}

	if bytesIn != *detachment.PaddedSize {
		return errors.New("input truncated")
	}

	return nil
}
Beispiel #23
0
// If valid == true, pb[176:] is replaced by the plaintext contents of
// the Initiate C'->S' box.
func (s *server) checkInitiate(pb []byte) (serverShortTermKey []byte, domain string, valid bool) {
	valid = false
	if len(pb) < 544 || !bytes.Equal(pb[:8], initiateMagic) {
		return
	}

	// Try to open the cookie.
	var nonce [24]byte
	copy(nonce[:], minuteNoncePrefix)
	copy(nonce[len(minuteNoncePrefix):], pb[72:72+16])

	var cookie [64]byte
	if _, ok := secretbox.Open(cookie[:0], pb[88:168], &nonce, &s.minuteKey); !ok {
		if _, ok = secretbox.Open(cookie[:0], pb[88:168], &nonce, &s.prevMinuteKey); !ok {
			return
		}
	}

	// Check that the cookie and client match
	if !bytes.Equal(cookie[:32], pb[40:40+32]) {
		return
	}

	// Extract server short-term secret key
	var serverKey [32]byte
	serverShortTermKey = serverKey[:]
	copy(serverShortTermKey, cookie[32:])

	// Open the Initiate box using both short-term secret keys.
	copy(nonce[:], initiateNoncePrefix)
	copy(nonce[len(initiateNoncePrefix):], pb[168:168+8])

	var clientShortTermKey [32]byte
	copy(clientShortTermKey[:], pb[40:40+32])

	initiate := make([]byte, len(pb[176:])-box.Overhead)
	if _, ok := box.Open(initiate[:0], pb[176:], &nonce, &clientShortTermKey, &serverKey); !ok {
		return
	}

	if domain = domainToString(initiate[96 : 96+256]); domain == "" {
		return
	}

	// Extract client long-term public key and check the vouch
	// subpacket.
	var clientLongTermKey [32]byte
	copy(clientLongTermKey[:], initiate[:32])

	copy(nonce[:], vouchNoncePrefix)
	copy(nonce[len(vouchNoncePrefix):], initiate[32:32+16])

	var vouch [32]byte
	if _, ok := box.Open(vouch[:0], initiate[48:48+48], &nonce, &clientLongTermKey, &s.longTermSecretKey); !ok {
		return
	}

	if !bytes.Equal(vouch[:], pb[40:40+32]) {
		return
	}

	// The Initiate packet is valid, replace the encrypted box with
	// the plaintext and return.
	copy(pb[176:], initiate)
	for i := len(pb) - box.Overhead; i < len(pb); i++ {
		pb[i] = 0
	}
	valid = true

	return
}
Beispiel #24
0
func (r *Ratchet) Decrypt(ciphertext []byte) ([]byte, error) {
	msg, err := r.trySavedKeys(ciphertext)
	if err != nil || msg != nil {
		return msg, err
	}

	sealedHeader := ciphertext[:sealedHeaderSize]
	sealedMessage := ciphertext[sealedHeaderSize:]
	var nonce [24]byte
	copy(nonce[:], sealedHeader)
	sealedHeader = sealedHeader[len(nonce):]

	header, ok := secretbox.Open(nil, sealedHeader, &nonce, &r.recvHeaderKey)
	ok = ok && !isZeroKey(&r.recvHeaderKey)
	if ok {
		if len(header) != headerSize {
			return nil, errors.New("ratchet: incorrect header size")
		}
		messageNum := binary.LittleEndian.Uint32(header[:4])
		provisionalChainKey, messageKey, savedKeys, err := r.saveKeys(&r.recvHeaderKey, &r.recvChainKey, messageNum, r.recvCount)
		if err != nil {
			return nil, err
		}

		copy(nonce[:], header[nonceInHeaderOffset:])
		msg, ok := secretbox.Open(nil, sealedMessage, &nonce, &messageKey)
		if !ok {
			return nil, errors.New("ratchet: corrupt message")
		}

		copy(r.recvChainKey[:], provisionalChainKey[:])
		r.mergeSavedKeys(savedKeys)
		r.recvCount = messageNum + 1
		return msg, nil
	}

	header, ok = secretbox.Open(nil, sealedHeader, &nonce, &r.nextRecvHeaderKey)
	if !ok {
		return nil, errors.New("ratchet: cannot decrypt")
	}
	if len(header) != headerSize {
		return nil, errors.New("ratchet: incorrect header size")
	}

	if r.ratchet {
		return nil, errors.New("ratchet: received message encrypted to next header key without ratchet flag set")
	}

	messageNum := binary.LittleEndian.Uint32(header[:4])
	prevMessageCount := binary.LittleEndian.Uint32(header[4:8])

	_, _, oldSavedKeys, err := r.saveKeys(&r.recvHeaderKey, &r.recvChainKey, prevMessageCount, r.recvCount)
	if err != nil {
		return nil, err
	}

	var dhPublic, sharedKey, rootKey, chainKey, keyMaterial [32]byte
	copy(dhPublic[:], header[8:])

	curve25519.ScalarMult(&sharedKey, &r.sendRatchetPrivate, &dhPublic)

	sha := sha256.New()
	sha.Write(rootKeyUpdateLabel)
	sha.Write(r.rootKey[:])
	sha.Write(sharedKey[:])

	var rootKeyHMAC hash.Hash

	if r.v2 {
		sha.Sum(keyMaterial[:0])
		rootKeyHMAC = hmac.New(sha256.New, keyMaterial[:])
		deriveKey(&rootKey, rootKeyLabel, rootKeyHMAC)
	} else {
		sha.Sum(rootKey[:0])
		rootKeyHMAC = hmac.New(sha256.New, rootKey[:])
	}
	deriveKey(&chainKey, chainKeyLabel, rootKeyHMAC)

	provisionalChainKey, messageKey, savedKeys, err := r.saveKeys(&r.nextRecvHeaderKey, &chainKey, messageNum, 0)
	if err != nil {
		return nil, err
	}

	copy(nonce[:], header[nonceInHeaderOffset:])
	msg, ok = secretbox.Open(nil, sealedMessage, &nonce, &messageKey)
	if !ok {
		return nil, errors.New("ratchet: corrupt message")
	}

	copy(r.rootKey[:], rootKey[:])
	copy(r.recvChainKey[:], provisionalChainKey[:])
	copy(r.recvHeaderKey[:], r.nextRecvHeaderKey[:])
	deriveKey(&r.nextRecvHeaderKey, sendHeaderKeyLabel, rootKeyHMAC)
	for i := range r.sendRatchetPrivate {
		r.sendRatchetPrivate[i] = 0
	}
	copy(r.recvRatchetPublic[:], dhPublic[:])

	r.recvCount = messageNum + 1
	r.mergeSavedKeys(oldSavedKeys)
	r.mergeSavedKeys(savedKeys)
	r.ratchet = true

	return msg, nil
}
Beispiel #25
0
func (sf *StateFile) Read(pw string) (*State, error) {
	b, err := ioutil.ReadFile(sf.Path)
	if err != nil {
		return nil, err
	}

	if len(b) < len(headerMagic)+4 {
		return nil, errors.New("state file is too small to be valid")
	}

	if !bytes.Equal(b[:len(headerMagic)], headerMagic[:]) {
		sf.header.NoErasureStorage = proto.Bool(true)
		if len(pw) > 0 {
			sf.header.Scrypt = new(Header_SCrypt)
			sf.header.KdfSalt = b[:32]
			if err := sf.deriveKey(pw); err != nil {
				return nil, err
			}
		}
		b = b[32:]
		state, err := sf.readOldStyle(b)
		if err != nil {
			return nil, err
		}
		return state, nil
	}

	b = b[len(headerMagic):]
	headerLen := binary.LittleEndian.Uint32(b)
	b = b[4:]
	if headerLen > 1<<16 {
		return nil, errors.New("state file corrupt")
	}
	if len(b) < int(headerLen) {
		return nil, errors.New("state file truncated")
	}
	headerBytes := b[:int(headerLen)]
	b = b[int(headerLen):]

	if err := proto.Unmarshal(headerBytes, &sf.header); err != nil {
		return nil, err
	}
	if len(pw) > 0 {
		if err := sf.deriveKey(pw); err != nil {
			return nil, err
		}
	}

	if !sf.header.GetNoErasureStorage() {
		for _, erasureMethod := range erasureRegistry {
			sf.Erasure = erasureMethod(&sf.header)
			if sf.Erasure != nil {
				break
			}
		}
		if sf.Erasure == nil {
			return nil, errors.New("unknown erasure storage method")
		}

		mask, err := sf.Erasure.Read(&sf.key)
		if err != nil {
			return nil, err
		}
		copy(sf.mask[:], mask[:])
	}

	smearedCopies := int(sf.header.GetNonceSmearCopies())

	if len(b) < 24*smearedCopies {
		return nil, errors.New("state file truncated")
	}

	var nonce [24]byte
	for i := 0; i < smearedCopies; i++ {
		for j := 0; j < 24; j++ {
			nonce[j] ^= b[24*i+j]
		}
	}

	b = b[24*smearedCopies:]

	var effectiveKey [kdfKeyLen]byte
	for i := range effectiveKey {
		effectiveKey[i] = sf.mask[i] ^ sf.key[i]
	}
	plaintext, ok := secretbox.Open(nil, b, &nonce, &effectiveKey)
	if !ok {
		return nil, BadPasswordError
	}
	if len(plaintext) < 4 {
		return nil, errors.New("state file corrupt")
	}
	length := binary.LittleEndian.Uint32(plaintext[:4])
	plaintext = plaintext[4:]
	if length > 1<<31 || length > uint32(len(plaintext)) {
		return nil, errors.New("state file corrupt")
	}
	plaintext = plaintext[:int(length)]

	var state State
	if err := proto.Unmarshal(plaintext, &state); err != nil {
		return nil, err
	}

	return &state, nil
}
Beispiel #26
0
// Open authenticates and decrypts a box produced by Seal and appends the
// message to out, which must not overlap box. The output will be Overhead
// bytes smaller than box.
func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) {
	var sharedKey [32]byte
	Precompute(&sharedKey, peersPublicKey, privateKey)
	return secretbox.Open(out, box, nonce, &sharedKey)
}
Beispiel #27
0
func (nd *NaClDecryptor) decrypt(buf []byte) ([]byte, error) {
	offset := binary.BigEndian.Uint16(buf[:2])
	df := (offset & (1 << 15)) != 0
	offsetNoFlags := offset & ((1 << 15) - 1)
	var decState *NaClDecryptorInstance
	if df {
		decState = nd.instanceDF
	} else {
		decState = nd.instance
	}
	var nonce *[24]byte
	var usedOffsets *bit.Set
	var ok bool
	if decState.nonce == nil {
		if offsetNoFlags > (1 << 13) {
			// offset is already beyond the first quarter and it's the
			// first thing we've seen?! I don't think so.
			return nil, fmt.Errorf("Unexpected offset when decrypting UDP packet")
		}
		decState.nonce, ok = <-decState.nonceChan
		if !ok {
			return nil, fmt.Errorf("Nonce chan closed")
		}
		nonce = decState.nonce
		usedOffsets = decState.usedOffsets
		decState.highestOffsetSeen = offsetNoFlags
	} else {
		highestOffsetSeen := decState.highestOffsetSeen
		if offsetNoFlags < (1<<13) && highestOffsetSeen > ((1<<14)+(1<<13)) &&
			(highestOffsetSeen-offsetNoFlags) > ((1<<14)+(1<<13)) {
			// offset is in the first quarter, highestOffsetSeen is in
			// the top quarter and under a quarter behind us. We
			// interpret this as we need to move to the next nonce
			decState.previousUsedOffsets = decState.usedOffsets
			decState.usedOffsets = bit.New()
			decState.previousNonce = decState.nonce
			decState.nonce, ok = <-decState.nonceChan
			if !ok {
				return nil, fmt.Errorf("Nonce chan closed")
			}
			decState.highestOffsetSeen = offsetNoFlags
			nonce = decState.nonce
			usedOffsets = decState.usedOffsets
		} else if offsetNoFlags > highestOffsetSeen &&
			(offsetNoFlags-highestOffsetSeen) < (1<<13) {
			// offset is under a quarter above highestOffsetSeen. This
			// is ok - maybe some packet loss
			decState.highestOffsetSeen = offsetNoFlags
			nonce = decState.nonce
			usedOffsets = decState.usedOffsets
		} else if offsetNoFlags <= highestOffsetSeen &&
			(highestOffsetSeen-offsetNoFlags) < (1<<13) {
			// offset is within a quarter of the highest we've
			// seen. This is ok - just assuming some out-of-order
			// delivery.
			nonce = decState.nonce
			usedOffsets = decState.usedOffsets
		} else if highestOffsetSeen < (1<<13) && offsetNoFlags > ((1<<14)+(1<<13)) &&
			(offsetNoFlags-highestOffsetSeen) > ((1<<14)+(1<<13)) {
			// offset is in the last quarter, highestOffsetSeen is in
			// the first quarter, and offset is under a quarter behind
			// us. This is ok - as above, just some out of order. But
			// here it means we're dealing with the previous nonce
			nonce = decState.previousNonce
			usedOffsets = decState.previousUsedOffsets
		} else {
			return nil, fmt.Errorf("Unexpected offset when decrypting UDP packet")
		}
	}
	offsetNoFlagsInt := int(offsetNoFlags)
	if usedOffsets.Contains(offsetNoFlagsInt) {
		return nil, fmt.Errorf("Suspected replay attack detected when decrypting UDP packet")
	}
	SetNonceLow15Bits(nonce, offsetNoFlags)
	result, success := secretbox.Open(nil, buf[2:], nonce, nd.conn.SessionKey)
	if success {
		usedOffsets.Add(offsetNoFlagsInt)
		return result, nil
	} else {
		return nil, fmt.Errorf("Unable to decrypt msg via UDP: %v", buf)
	}
}
Beispiel #28
0
// OpenAfterPrecomputation performs the same actions as Open, but takes a
// shared key as generated by Precompute.
func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) {
	return secretbox.Open(out, box, nonce, sharedKey)
}
Beispiel #29
0
func do(keyFile string) error {
	contents, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		return err
	}

	var detachment pond.Message_Detachment
	if err := proto.Unmarshal(contents, &detachment); err != nil {
		return err
	}

	size := detachment.GetSize()
	paddedSize := detachment.GetPaddedSize()
	chunkSize := uint64(detachment.GetChunkSize())
	blockSize := chunkSize + secretbox.Overhead

	if blockSize > 1<<20 {
		return errors.New("chunk size too large")
	}

	if paddedSize%blockSize != 0 {
		return errors.New("padded size is not a multiple of the chunk size")
	}

	fmt.Fprintf(os.Stderr, `Pond decryption:
  Original filename: %s
  Size: %d
  Padded size: %d
  Chunk size: %d
`, sanitiseForTerminal(detachment.GetFilename()), size, paddedSize, chunkSize)

	var key [32]byte
	var nonce [24]byte
	copy(key[:], detachment.Key)

	var read, written uint64
	buf := make([]byte, blockSize)
	var decrypted []byte

	for read < paddedSize {
		if _, err := io.ReadFull(os.Stdin, buf); err != nil {
			return err
		}

		read += uint64(len(buf))
		var ok bool
		decrypted, ok := secretbox.Open(decrypted[:0], buf, &nonce, &key)
		if !ok {
			return errors.New("decryption error")
		}

		incNonce(&nonce)

		todo := size - written
		if n := uint64(len(decrypted)); todo > n {
			todo = n
		}

		if _, err := os.Stdout.Write(decrypted[:todo]); err != nil {
			return err
		}

		written += todo
	}

	return nil
}