Example #1
0
// TestEncryptingFromMiddle tests that Encrypting when the source is NOT
// at the beginning of the stream works properly
func TestEncryptingFromMiddle(t *testing.T) {
	actualBytes := []byte("abcdefghijklmnopqrstuvwxyz")
	actualStart := 10

	orig := memstream.NewCapacity(30)
	orig.Write(actualBytes)

	// Jump part way in and encrypt
	orig.Seek(int64(actualStart), 0)
	encrypted := memstream.NewCapacity(50)
	_, _, err := Encrypt(orig, encrypted, keys)
	if err != nil {
		t.Errorf("Unable to encrypt: %v", err)
		return
	}

	// Decrypt
	encrypted.Seek(0, 0)
	decrypted := memstream.NewCapacity(30)
	_, _, err = Decrypt(encrypted, decrypted, keys)
	if err != nil {
		t.Errorf("Unable to decrypt: %v", err)
		return
	}

	if !bytes.Equal(actualBytes[actualStart:], decrypted.Bytes()) {
		t.Errorf("Decrypted bytes (%v) do not match original (%v)", decrypted.Bytes(), actualBytes)
		fmt.Println(decrypted.Bytes())
		fmt.Println(actualBytes[actualStart:])
		return
	}
}
Example #2
0
// Write rebuilds the protected file on disk, ensuring the contents and header
// are current with the local file
func (h *Header) Write() error {
	// Get data from local file for header
	localFile, err := os.Open(h.AbsLocalPath())
	if err != nil {
		return &ErrProtectedFile{"Unable to open local file", err}
	}
	defer localFile.Close()

	h.contentHash, err = hash.Sha256(localFile)
	if err != nil {
		return &ErrProtectedFile{"Unable to get local file hash", err}
	}

	// Keys
	h.contentKeys, err = aes.NewKeyCombo()
	if err != nil {
		return &ErrProtectedFile{"Failed to generate keys for file", err}
	}

	// Write header to temp file
	headerBytes := memstream.NewCapacity(1024)
	writer := bufio.NewWriter(headerBytes)
	err = writer.WriteByte(1) // Version
	if err != nil {
		return &ErrProtectedFile{"Unable to write version", err}
	}

	_, err = writer.Write(h.contentKeys.CryptoKey)
	if err != nil {
		return &ErrProtectedFile{"Unable to write crypto key", err}
	}
	_, err = writer.Write(h.contentKeys.AuthKey)
	if err != nil {
		return &ErrProtectedFile{"Unable to write auth key", err}
	}
	_, err = writer.Write(h.contentHash)
	if err != nil {
		return &ErrProtectedFile{"Unable to write hash", err}
	}

	localLenBytes := gocrypt.Uint64ToBytes(uint64(len(h.LocalPath())))
	_, err = writer.Write(localLenBytes)
	if err != nil {
		return &ErrProtectedFile{"Unable to write path length", err}
	}

	_, err = writer.Write([]byte(h.LocalPath()))
	if err != nil {
		return &ErrProtectedFile{"Unable to write local path", err}
	}

	if err = writer.Flush(); err != nil {
		return &ErrProtectedFile{"Flushing header failed", err}
	}

	// Encrypt and write header to temp file
	protFile, err := ioutil.TempFile("", "syncerprotfile")
	if err != nil {
		return &ErrProtectedFile{"Unable to create temp protected file", err}
	}
	defer func() {
		protFile.Close()
		os.Remove(protFile.Name())
	}()

	headerBytes.Rewind()
	metakeys := h.sync.Keys()
	_, _, err = aes.Encrypt(headerBytes, protFile, &metakeys)
	if err != nil {
		return &ErrProtectedFile{"Unable to encrypt header", err}
	}

	// Update length of header. Not in file, just used internally for extracting
	headLen, err := protFile.Seek(0, 1)
	h.headerLen = int(headLen)
	if err != nil {
		return &ErrProtectedFile{"Unable to determine length of header", err}
	}

	// Encrypt and append contents
	_, err = localFile.Seek(0, 0)
	if err != nil {
		return &ErrProtectedFile{"Unable to return to beginning of local file", err}
	}

	_, _, err = aes.Encrypt(localFile, protFile, h.contentKeys)
	if err != nil {
		return &ErrProtectedFile{"Unable to encrypt contents", err}
	}

	// Move file to final location
	// TODO create any needed directories?
	protFile.Close()
	err = moveFile(protFile.Name(), h.AbsRemotePath())
	if err != nil {
		return &ErrProtectedFile{"Failed to move final protected file", err}
	}

	return nil
}