Beispiel #1
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
}