diff --git a/common/source/java/ch/systemsx/cisd/common/io/ByteArrayBasedContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/ByteArrayBasedContentNode.java
index 33c6d6920a5e7f2199352c4ddc6293996498b841..4f3da04d574390c0ef954026e76c3ae406ddc020 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/ByteArrayBasedContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/ByteArrayBasedContentNode.java
@@ -40,6 +40,8 @@ public class ByteArrayBasedContentNode implements IHierarchicalContentNode
     private final String nameOrNull;
 
     private long lastModified;
+    
+    private Long checksum;
 
     /**
      * Creates an instance for the specified byte array.
@@ -114,6 +116,15 @@ public class ByteArrayBasedContentNode implements IHierarchicalContentNode
         return byteArray.length;
     }
 
+    public long getChecksumCRC32() throws UnsupportedOperationException
+    {
+        if (checksum == null)
+        {
+            checksum = IOUtilities.getChecksumCRC32(new ByteArrayInputStream(byteArray));
+        }
+        return checksum;
+    }
+
     public IRandomAccessFile getFileContent() throws UnsupportedOperationException,
             IOExceptionUnchecked
     {
diff --git a/common/source/java/ch/systemsx/cisd/common/io/FileBasedContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/FileBasedContentNode.java
index dcaa21daf374ae4707da7cdb929c39f076b6f196..1d94123442a840e8f80485c44dc2d669a7ceaf63 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/FileBasedContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/FileBasedContentNode.java
@@ -20,9 +20,12 @@ import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 
+import org.apache.commons.io.FileUtils;
+
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked;
 import ch.systemsx.cisd.base.io.IRandomAccessFile;
@@ -121,6 +124,17 @@ public class FileBasedContentNode implements IHierarchicalContentNode
         return file.length();
     }
 
+    public long getChecksumCRC32() throws UnsupportedOperationException
+    {
+        try
+        {
+            return FileUtils.checksumCRC32(file);
+        } catch (IOException ex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+        }
+    }
+
     public IRandomAccessFile getFileContent() throws UnsupportedOperationException,
             IOExceptionUnchecked
     {
diff --git a/common/source/java/ch/systemsx/cisd/common/io/HierarchicalContentNodeBasedHierarchicalContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/HierarchicalContentNodeBasedHierarchicalContentNode.java
index 412b4e3bf431598b838c3b77011ad00a8ccd1d7b..5c898ac4fdd054592c7a97aba4907c2c6a9811f5 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/HierarchicalContentNodeBasedHierarchicalContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/HierarchicalContentNodeBasedHierarchicalContentNode.java
@@ -72,6 +72,11 @@ public class HierarchicalContentNodeBasedHierarchicalContentNode implements
                 return 0;
             }
 
+            public long getChecksumCRC32() throws UnsupportedOperationException
+            {
+                return 0;
+            }
+
             public IRandomAccessFile getFileContent() throws UnsupportedOperationException,
                     IOExceptionUnchecked
             {
@@ -172,6 +177,11 @@ public class HierarchicalContentNodeBasedHierarchicalContentNode implements
         return getContent().getFileLength();
     }
 
+    public long getChecksumCRC32() throws UnsupportedOperationException
+    {
+        return getContent().getChecksumCRC32();
+    }
+
     public IRandomAccessFile getFileContent() throws UnsupportedOperationException,
             IOExceptionUnchecked
     {
diff --git a/common/source/java/ch/systemsx/cisd/common/io/IOUtilities.java b/common/source/java/ch/systemsx/cisd/common/io/IOUtilities.java
new file mode 100644
index 0000000000000000000000000000000000000000..7bef4b9d6a67b6f7e45f16968d5beccdfff30338
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/io/IOUtilities.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedInputStream;
+import java.util.zip.Checksum;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.NullOutputStream;
+
+import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
+
+/**
+ * Useful utility methods.
+ *
+ * @author Franz-Josef Elmer
+ */
+public class IOUtilities
+{
+    /**
+     * Calculates the CRC32 checksum of specified input stream.
+     * Note, that the input stream is closed after invocation of this method.
+     */
+    public static long getChecksumCRC32(InputStream inputStream)
+    {
+        Checksum checksummer = new CRC32();
+        InputStream in = null;
+        try {
+            in = new CheckedInputStream(inputStream, checksummer);
+            IOUtils.copy(in, new NullOutputStream());
+        } catch (IOException ex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+        } finally {
+            IOUtils.closeQuietly(in);
+        }
+        return checksummer.getValue();
+    }
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalContentNode.java
index 61e7f9ce7df6fa8d09c04c80e05303c7e94c207a..67b688939520f9a5126cbd7eaea2df6498cabbea 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalContentNode.java
@@ -47,6 +47,9 @@ public abstract class AbstractHierarchicalContentNode implements IHierarchicalCo
     /** Returns size of a node known NOT to be a directory. */
     abstract protected long doGetFileLength();
 
+    /** Returns checksum of a node known NOT to be a directory. */
+    abstract protected long doGetChecksumCRC32();
+    
     /** Returns {@link IRandomAccessFile} of a node known NOT to be a directory. */
     abstract protected IRandomAccessFile doGetFileContent();
 
@@ -92,6 +95,12 @@ public abstract class AbstractHierarchicalContentNode implements IHierarchicalCo
         return doGetFileLength();
     }
 
+    public long getChecksumCRC32() throws UnsupportedOperationException
+    {
+        failOnDirectory();
+        return doGetChecksumCRC32();
+    }
+    
     public final IRandomAccessFile getFileContent()
     {
         failOnDirectory();
diff --git a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalDirectoryContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalDirectoryContentNode.java
index c53211cca47c5bb414eebcc26b71035398527c97..22d9261b50cfc165c3fe0a537d485fdb342d2816 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalDirectoryContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalDirectoryContentNode.java
@@ -34,6 +34,12 @@ public abstract class AbstractHierarchicalDirectoryContentNode extends
         throw new UnsupportedOperationException(OPERATION_NOT_SUPPORTED_FOR_A_DIRECTORY);
     }
 
+    @Override
+    protected long doGetChecksumCRC32()
+    {
+        throw new UnsupportedOperationException(OPERATION_NOT_SUPPORTED_FOR_A_DIRECTORY);
+    }
+
     @Override
     protected final IRandomAccessFile doGetFileContent()
     {
diff --git a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentNode.java
index fac958829efb872a0a20ff7de4ac5cdbf8ee21de..4655beb189c03d25887b6ca64324cc3245ada105 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentNode.java
@@ -19,10 +19,13 @@ package ch.systemsx.cisd.common.io.hierarchical_content;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.io.FileUtils;
+
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.base.io.IRandomAccessFile;
 import ch.systemsx.cisd.base.io.RandomAccessFileImpl;
@@ -119,6 +122,18 @@ class DefaultFileBasedHierarchicalContentNode extends AbstractHierarchicalConten
         return file.length();
     }
 
+    @Override
+    protected long doGetChecksumCRC32()
+    {
+        try
+        {
+            return FileUtils.checksumCRC32(file);
+        } catch (IOException ex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+        }
+    }
+
     @Override
     public IRandomAccessFile doGetFileContent()
     {
diff --git a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/HDF5ContainerBasedHierarchicalContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/HDF5ContainerBasedHierarchicalContentNode.java
index 234cdf081e5f49efcff63907fd933addf019c516..e1d55337195838f2af58c9d266c429beb3e4fcb9 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/HDF5ContainerBasedHierarchicalContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/HDF5ContainerBasedHierarchicalContentNode.java
@@ -27,6 +27,7 @@ import ch.systemsx.cisd.base.io.AdapterIInputStreamToInputStream;
 import ch.systemsx.cisd.base.io.IRandomAccessFile;
 import ch.systemsx.cisd.common.hdf5.HDF5Container;
 import ch.systemsx.cisd.common.hdf5.IHDF5ContainerReader;
+import ch.systemsx.cisd.common.io.IOUtilities;
 import ch.systemsx.cisd.common.io.hierarchical_content.api.IHierarchicalContent;
 import ch.systemsx.cisd.common.io.hierarchical_content.api.IHierarchicalContentNode;
 import ch.systemsx.cisd.hdf5.h5ar.ArchiveEntry;
@@ -259,6 +260,8 @@ public class HDF5ContainerBasedHierarchicalContentNode extends
         private HDF5DataSetBasedContent contentOrNull;
 
         private final HDF5ContainerBasedHierarchicalContentNode containerNode;
+        
+        private Long checksum;
 
         public HDF5FileNode(HDF5ContainerBasedHierarchicalContentNode containerNode,
                 ArchiveEntry entry)
@@ -310,6 +313,23 @@ public class HDF5ContainerBasedHierarchicalContentNode extends
             return entry.getSize();
         }
 
+        @Override
+        protected long doGetChecksumCRC32()
+        {
+            if (checksum == null)
+            {
+                int entryChecksum = entry.getCrc32();
+                if (entryChecksum != 0)
+                {
+                    checksum = (long) entryChecksum;
+                } else
+                {
+                    checksum = IOUtilities.getChecksumCRC32(doGetInputStream());
+                }
+            }
+            return checksum;
+        }
+
         @Override
         protected IRandomAccessFile doGetFileContent()
         {
diff --git a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/VirtualHierarchicalContent.java b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/VirtualHierarchicalContent.java
index fc1fe9c6b3c683996884af8e13f3dc50319042b4..9037e3a624405c075b544bf82215736e1e8b3b6f 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/VirtualHierarchicalContent.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/VirtualHierarchicalContent.java
@@ -437,6 +437,11 @@ class VirtualHierarchicalContent implements IHierarchicalContent
             }
         }
 
+        public long getChecksumCRC32() throws UnsupportedOperationException
+        {
+            return lastExistingNode().getChecksumCRC32();
+        }
+
         public IRandomAccessFile getFileContent() throws UnsupportedOperationException,
                 IOExceptionUnchecked
         {
diff --git a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/api/IHierarchicalContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/api/IHierarchicalContentNode.java
index 4e18a1e3cc4e35e3d1e5924477d07941a3175179..0022b9e3c346e42cf0684db60fe8092438727956 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/api/IHierarchicalContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/hierarchical_content/api/IHierarchicalContentNode.java
@@ -91,6 +91,15 @@ public interface IHierarchicalContentNode
      * @throws UnsupportedOperationException if the node is an abstraction of a directory.
      */
     long getFileLength() throws UnsupportedOperationException;
+    
+    /**
+     * Returns the CRC32 checksum of a file abstracted by this node.
+     * <p>
+     * NOTE: Call {@link #isDirectory()} first to make sure this node is NOT a directory.
+     * 
+     * @throws UnsupportedOperationException if the node is an abstraction of a directory.
+     */
+    long getChecksumCRC32() throws UnsupportedOperationException;
 
     /**
      * Returns a read only {@link IRandomAccessFile} with file content of the node. *
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalContentNodeTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalContentNodeTest.java
index f45da3dbb92baec92e0bb7d9e4dff316db4ea165..09cd68e2c485fa3f14e7abe3e6b415963c2e4b82 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalContentNodeTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/io/hierarchical_content/AbstractHierarchicalContentNodeTest.java
@@ -171,6 +171,12 @@ public class AbstractHierarchicalContentNodeTest extends AssertJUnit
                     return 0;
                 }
 
+                @Override
+                protected long doGetChecksumCRC32()
+                {
+                    return 0;
+                }
+
                 @Override
                 protected IRandomAccessFile doGetFileContent()
                 {
@@ -238,6 +244,12 @@ public class AbstractHierarchicalContentNodeTest extends AssertJUnit
                     return 0;
                 }
 
+                @Override
+                protected long doGetChecksumCRC32()
+                {
+                    return 0;
+                }
+
                 @Override
                 protected IRandomAccessFile doGetFileContent()
                 {
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentTest.java
index 1070487d7bf63b841dacad140665a3c0c138e32f..bf4f46190e74c6632b484640de6e7515e0ff81e4 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentTest.java
@@ -659,6 +659,11 @@ public class DefaultFileBasedHierarchicalContentTest extends AbstractFileSystemT
                     throw new UnsupportedOperationException(METHOD_NOT_IMPLEMENTED);
                 }
 
+                public long getChecksumCRC32() throws UnsupportedOperationException
+                {
+                    throw new UnsupportedOperationException(METHOD_NOT_IMPLEMENTED);
+                }
+
                 public InputStream getInputStream() throws UnsupportedOperationException,
                         IOExceptionUnchecked
                 {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/PathInfoProviderBasedHierarchicalContent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/PathInfoProviderBasedHierarchicalContent.java
index 60998aad20ff135baf25b16dddfbda2bbcb26655..16a1a5e7a0a0a37ae994d123927aaec52dc67119 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/PathInfoProviderBasedHierarchicalContent.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/PathInfoProviderBasedHierarchicalContent.java
@@ -237,6 +237,13 @@ class PathInfoProviderBasedHierarchicalContent implements IHierarchicalContent
             return pathInfo.getSizeInBytes();
         }
 
+        @Override
+        protected long doGetChecksumCRC32()
+        {
+            // TODO Auto-generated method stub
+            return 0;
+        }
+
         public File getFile() throws UnsupportedOperationException
         {
             File result = doGetFile();
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/ImageUtilTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/ImageUtilTest.java
index c20da02064ba7c82fd7291282091b70ff54f03e7..e5c728592c4a54f000038ad73b48f29209c6db82 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/ImageUtilTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/ImageUtilTest.java
@@ -94,6 +94,11 @@ public class ImageUtilTest extends AssertJUnit
             throw new UnsupportedOperationException();
         }
 
+        public long getChecksumCRC32() throws UnsupportedOperationException
+        {
+            throw new UnsupportedOperationException();
+        }
+
         public IRandomAccessFile getFileContent() throws UnsupportedOperationException,
                 IOExceptionUnchecked
         {