func (c *client) startUpload(id uint64, inPath string) (cancel func()) { killChan := make(chan bool, 1) go func() { var detachment *pond.Message_Detachment var tmp *os.File var err error if tmp, err = ioutil.TempFile("" /* default tmp dir */, "pond-upload-"); err != nil { err = errors.New("failed to create temp file: " + err.Error()) } else { os.Remove(tmp.Name()) defer tmp.Close() detachment, err = saveEncrypted(c.rand, c.backgroundChan, tmp, id, inPath, killChan) if err == nil { err = c.uploadDetachment(c.backgroundChan, tmp, id, killChan) } } if err == nil { detachment.Url = proto.String(c.buildDetachmentURL(id)) c.log.Printf("Finished upload of %s", *detachment.Url) c.backgroundChan <- DetachmentComplete{id, detachment} } else { c.backgroundChan <- DetachmentError{id, err} } tmp.Close() }() return func() { killChan <- true } }
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 }