diff --git a/apps/dav/lib/connector/sabre/file.php b/apps/dav/lib/connector/sabre/file.php
index 38a1ee5f4e2fae34fbd825688df3915b0dbc04c8..9c8344bc5db8522140ce81be98384dc672e565de 100644
--- a/apps/dav/lib/connector/sabre/file.php
+++ b/apps/dav/lib/connector/sabre/file.php
@@ -215,11 +215,16 @@ class File extends Node implements IFile {
 				}
 			}
 
+			$this->refreshInfo();
+
 			if (isset($request->server['HTTP_OC_CHECKSUM'])) {
 				$checksum = trim($request->server['HTTP_OC_CHECKSUM']);
 				$this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
+				$this->refreshInfo();
+			} else if ($this->getChecksum() !== null && $this->getChecksum() !== '') {
+				$this->fileView->putFileInfo($this->path, ['checksum' => '']);
+				$this->refreshInfo();
 			}
-			$this->refreshInfo();
 
 		} catch (StorageNotAvailableException $e) {
 			throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
@@ -457,8 +462,16 @@ class File extends Node implements IFile {
 
 				$this->emitPostHooks($exists, $targetPath);
 
+				// FIXME: should call refreshInfo but can't because $this->path is not the of the final file
 				$info = $this->fileView->getFileInfo($targetPath);
 
+				if (isset($request->server['HTTP_OC_CHECKSUM'])) {
+					$checksum = trim($request->server['HTTP_OC_CHECKSUM']);
+					$this->fileView->putFileInfo($targetPath, ['checksum' => $checksum]);
+				} else if ($info->getChecksum() !== null && $info->getChecksum() !== '') {
+					$this->fileView->putFileInfo($this->path, ['checksum' => '']);
+				}
+
 				$this->fileView->unlockFile($targetPath, ILockingProvider::LOCK_SHARED);
 
 				return $info->getEtag();
diff --git a/apps/dav/lib/connector/sabre/filesplugin.php b/apps/dav/lib/connector/sabre/filesplugin.php
index eb9116d219b9ae98632f3614969f5374ab8b4f7a..4b05922adfda52adf6c91de380dc335252235a61 100644
--- a/apps/dav/lib/connector/sabre/filesplugin.php
+++ b/apps/dav/lib/connector/sabre/filesplugin.php
@@ -27,6 +27,7 @@
 
 namespace OCA\DAV\Connector\Sabre;
 
+use Sabre\DAV\Exception\NotFound;
 use Sabre\DAV\IFile;
 use \Sabre\DAV\PropFind;
 use \Sabre\DAV\PropPatch;
@@ -197,7 +198,7 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin {
 			//Add OC-Checksum header
 			/** @var $node File */
 			$checksum = $node->getChecksum();
-			if ($checksum !== null) {
+			if ($checksum !== null && $checksum !== '') {
 				$response->addHeader('OC-Checksum', $checksum);
 			}
 		}
@@ -252,6 +253,10 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin {
 
 			$propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
 				$checksum = $node->getChecksum();
+				if ($checksum === NULL || $checksum === '') {
+					return null;
+				}
+
 				return new ChecksumList($checksum);
 			});
 
diff --git a/build/integration/config/behat.yml b/build/integration/config/behat.yml
index d0c4586d285aa90195a04f1a1593376822b6ea1d..4b5b5b16ef8188e41d68d653b7c070fca545ed4d 100644
--- a/build/integration/config/behat.yml
+++ b/build/integration/config/behat.yml
@@ -20,6 +20,8 @@ default:
             baseUrl: http://localhost:8080
         - CalDavContext:
             baseUrl: http://localhost:8080
+        - ChecksumsContext:
+            baseUrl: http://localhost:8080
     federation:
       paths:
         - %paths.base%/../federation_features
diff --git a/build/integration/features/bootstrap/ChecksumsContext.php b/build/integration/features/bootstrap/ChecksumsContext.php
new file mode 100644
index 0000000000000000000000000000000000000000..a5d20ba965d989a7920f8fee2bb52af8dbc874e3
--- /dev/null
+++ b/build/integration/features/bootstrap/ChecksumsContext.php
@@ -0,0 +1,227 @@
+<?php
+
+require __DIR__ . '/../../vendor/autoload.php';
+
+use Behat\Gherkin\Node\TableNode;
+use GuzzleHttp\Client;
+use GuzzleHttp\Message\ResponseInterface;
+
+class ChecksumsContext implements \Behat\Behat\Context\Context {
+	/** @var string  */
+	private $baseUrl;
+	/** @var Client */
+	private $client;
+	/** @var ResponseInterface */
+	private $response;
+
+	/**
+	 * @param string $baseUrl
+	 */
+	public function __construct($baseUrl) {
+		$this->baseUrl = $baseUrl;
+
+		// in case of ci deployment we take the server url from the environment
+		$testServerUrl = getenv('TEST_SERVER_URL');
+		if ($testServerUrl !== false) {
+			$this->baseUrl = substr($testServerUrl, 0, -5);
+		}
+	}
+
+	/** @BeforeScenario */
+	public function tearUpScenario() {
+		$this->client = new Client();
+	}
+
+	/** @AfterScenario */
+	public function tearDownScenario() {
+	}
+
+
+	/**
+	 * @param string $userName
+	 * @return string
+	 */
+	private function getPasswordForUser($userName) {
+		if($userName === 'admin') {
+			return 'admin';
+		}
+		return '123456';
+	}
+
+	/**
+	 * @When user :user uploads file :source to :destination with checksum :checksum
+	 */
+	public function userUploadsFileToWithChecksum($user, $source, $destination, $checksum)
+	{
+		$file = \GuzzleHttp\Stream\Stream::factory(fopen($source, 'r'));
+		try {
+			$this->response = $this->client->put(
+				$this->baseUrl . '/remote.php/webdav' . $destination,
+				[
+					'auth' => [
+						$user,
+						$this->getPasswordForUser($user)
+					],
+					'body' => $file,
+					'headers' => [
+						'OC-Checksum' => $checksum
+					]
+				]
+			);
+		} catch (\GuzzleHttp\Exception\ServerException $e) {
+			// 4xx and 5xx responses cause an exception
+			$this->response = $e->getResponse();
+		}
+	}
+
+	/**
+	 * @Then The webdav response should have a status code :statusCode
+	 */
+	public function theWebdavResponseShouldHaveAStatusCode($statusCode) {
+		if((int)$statusCode !== $this->response->getStatusCode()) {
+			throw new \Exception("Expected $statusCode, got ".$this->response->getStatusCode());
+		}
+	}
+
+	/**
+	 * @When user :user request the checksum of :path via propfind
+	 */
+	public function userRequestTheChecksumOfViaPropfind($user, $path)
+	{
+		$request = $this->client->createRequest(
+			'PROPFIND',
+			$this->baseUrl . '/remote.php/webdav' . $path,
+			[
+				'body' => '<?xml version="1.0"?>
+<d:propfind  xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
+  <d:prop>
+    <oc:checksums />
+  </d:prop>
+</d:propfind>',
+				'auth' => [
+					$user,
+					$this->getPasswordForUser($user),
+				]
+			]
+		);
+		$this->response = $this->client->send($request);
+	}
+
+	/**
+	 * @Then The webdav checksum should match :checksum
+	 */
+	public function theWebdavChecksumShouldMatch($checksum)
+	{
+		$service = new Sabre\Xml\Service();
+		$parsed = $service->parse($this->response->getBody()->getContents());
+
+		/*
+		 * Fetch the checksum array
+		 * Maybe we want to do this a bit cleaner ;)
+		 */
+		$checksums = $parsed[0]['value'][1]['value'][0]['value'][0];
+
+		if ($checksums['value'][0]['value'] !== $checksum) {
+			throw new \Exception("Expected $checksum, got ".$checksums['value'][0]['value']);
+		}
+	}
+
+	/**
+	 * @When user :user downloads the file :path
+	 */
+	public function userDownloadsTheFile($user, $path)
+	{
+		$this->response = $this->client->get(
+			$this->baseUrl . '/remote.php/webdav' . $path,
+			[
+				'auth' => [
+					$user,
+					$this->getPasswordForUser($user),
+				]
+			]
+		);
+	}
+
+	/**
+	 * @Then The header checksum should match :checksum
+	 */
+	public function theHeaderChecksumShouldMatch($checksum)
+	{
+		if ($this->response->getHeader('OC-Checksum') !== $checksum) {
+			throw new \Exception("Expected $checksum, got ".$this->response->getHeader('OC-Checksum'));
+		}
+	}
+
+	/**
+	 * @Given User :user copied file :source to :destination
+	 */
+	public function userCopiedFileTo($user, $source, $destination)
+	{
+		$request = $this->client->createRequest(
+			'MOVE',
+			$this->baseUrl . '/remote.php/webdav' . $source,
+			[
+				'auth' => [
+					$user,
+					$this->getPasswordForUser($user),
+				],
+				'headers' => [
+					'Destination' => $this->baseUrl . '/remote.php/webdav' . $destination,
+				],
+			]
+		);
+		$this->response = $this->client->send($request);
+	}
+
+	/**
+	 * @Then The webdav checksum should be empty
+	 */
+	public function theWebdavChecksumShouldBeEmpty()
+	{
+		$service = new Sabre\Xml\Service();
+		$parsed = $service->parse($this->response->getBody()->getContents());
+
+		/*
+		 * Fetch the checksum array
+		 * Maybe we want to do this a bit cleaner ;)
+		 */
+		$status = $parsed[0]['value'][1]['value'][1]['value'];
+
+		if ($status !== 'HTTP/1.1 404 Not Found') {
+			throw new \Exception("Expected 'HTTP/1.1 404 Not Found', got ".$status);
+		}
+	}
+
+	/**
+	 * @Then The OC-Checksum header should not be there
+	 */
+	public function theOcChecksumHeaderShouldNotBeThere()
+	{
+		if ($this->response->hasHeader('OC-Checksum')) {
+			throw new \Exception("Expected no checksum header but got ".$this->response->getHeader('OC-Checksum'));
+		}
+	}
+
+	/**
+	 * @Given user :user uploads chunk file :num of :total with :data to :destination with checksum :checksum
+	 */
+	public function userUploadsChunkFileOfWithToWithChecksum($user, $num, $total, $data, $destination, $checksum)
+	{
+		$num -= 1;
+		$this->response = $this->client->put(
+			$this->baseUrl . '/remote.php/webdav' . $destination . '-chunking-42-'.$total.'-'.$num,
+			[
+				'auth' => [
+					$user,
+					$this->getPasswordForUser($user)
+				],
+				'body' => $data,
+				'headers' => [
+					'OC-Checksum' => $checksum,
+					'OC-Chunked' => '1',
+				]
+			]
+		);
+
+	}
+}
diff --git a/build/integration/features/checksums.feature b/build/integration/features/checksums.feature
new file mode 100644
index 0000000000000000000000000000000000000000..d391e93afe8dabc84df044896d21531bf195a3f9
--- /dev/null
+++ b/build/integration/features/checksums.feature
@@ -0,0 +1,76 @@
+Feature: checksums
+
+  Scenario: Uploading a file with checksum should work
+    Given user "user0" exists
+    When user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a"
+    Then The webdav response should have a status code "201"
+
+  Scenario: Uploading a file with checksum should return the checksum in the propfind
+    Given user "user0" exists
+    And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a"
+    When user "user0" request the checksum of "/myChecksumFile.txt" via propfind
+    Then The webdav checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a"
+
+  Scenario: Uploading a file with checksum should return the checksum in the download header
+    Given user "user0" exists
+    And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a"
+    When user "user0" downloads the file "/myChecksumFile.txt"
+    Then The header checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a"
+
+  Scenario: Moving a file with checksum should return the checksum in the propfind
+    Given user "user0" exists
+    And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a"
+    When User "user0" moved file "/myChecksumFile.txt" to "/myMovedChecksumFile.txt"
+    And user "user0" request the checksum of "/myMovedChecksumFile.txt" via propfind
+    Then The webdav checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a"
+
+  Scenario: Moving file with checksum should return the checksum in the download header
+    Given user "user0" exists
+    And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a"
+    When User "user0" moved file "/myChecksumFile.txt" to "/myMovedChecksumFile.txt"
+    And user "user0" downloads the file "/myMovedChecksumFile.txt"
+    Then The header checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a"
+
+  Scenario: Copying a file with checksum should return the checksum in the propfind
+    Given user "user0" exists
+    And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a"
+    When User "user0" copied file "/myChecksumFile.txt" to "/myChecksumFileCopy.txt"
+    And user "user0" request the checksum of "/myChecksumFileCopy.txt" via propfind
+    Then The webdav checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a"
+
+  Scenario: Copying file with checksum should return the checksum in the download header
+    Given user "user0" exists
+    And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a"
+    When User "user0" copied file "/myChecksumFile.txt" to "/myChecksumFileCopy.txt"
+    And user "user0" downloads the file "/myChecksumFileCopy.txt"
+    Then The header checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a"
+
+  Scenario: Overwriting a file with checksum should remove the checksum and not return it in the propfind
+    Given user "user0" exists
+    And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a"
+    When user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt"
+    And user "user0" request the checksum of "/myChecksumFile.txt" via propfind
+    Then The webdav checksum should be empty
+
+  Scenario: Overwriting a file with checksum should remove the checksum and not return it in the download header
+    Given user "user0" exists
+    And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a"
+    When user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt"
+    And user "user0" downloads the file "/myChecksumFile.txt"
+    Then The OC-Checksum header should not be there
+
+  Scenario: Uploading a chunked file with checksum should return the checksum in the propfind
+    Given user "user0" exists
+    And user "user0" uploads chunk file "1" of "3" with "AAAAA" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88"
+    And user "user0" uploads chunk file "2" of "3" with "BBBBB" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88"
+    And user "user0" uploads chunk file "3" of "3" with "CCCCC" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88"
+    When user "user0" request the checksum of "/myChecksumFile.txt" via propfind
+    Then The webdav checksum should match "MD5:e892fdd61a74bc89cd05673cc2e22f88"
+
+  Scenario: Uploading a chunked file with checksum should return the checksum in the download header
+    Given user "user0" exists
+    And user "user0" uploads chunk file "1" of "3" with "AAAAA" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88"
+    And user "user0" uploads chunk file "2" of "3" with "BBBBB" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88"
+    And user "user0" uploads chunk file "3" of "3" with "CCCCC" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88"
+    When user "user0" downloads the file "/myChecksumFile.txt"
+    Then The header checksum should match "MD5:e892fdd61a74bc89cd05673cc2e22f88"