Search code examples
c#hashoffice365onedrive

How to compute OneDrive XOrHash in C#


We wish to compute the XOrHash the same way that OneDrive does so we can detect any changes needed to sync with the OD4B backend.

I have the current implementation for the XOrHash Algorithm used which can be found here https://learn.microsoft.com/en-us/onedrive/developer/code-snippets/quickxorhash

However there is nothing to suggest how I can compute the same hash in our code to match the hash that OD4B provides us with.

We Use the XOrHash Algorithm provided in the link above to give us the byte array for the hash which has a typical length of 20 bytes.

public static byte[] ComputeHash(string filePath)
{
    using (var quickXor = XOrHash.Create())
    {
        using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            return quickXor.ComputeHash(stream);
        }
    }
}

 public static string ConvertHexToString(this byte[] bytes)
 {            
     return Convert.ToBase64String(bytes);
 }

returns "4FPisLqvTiuaxUVVz6Zk+RxMClE=" OD4B tells us the hash is "LmpqMT5KKX4ATcd372ZTyVr3gIk="

Clearly we are mismatching and are unable to find any documentation on this other than the following page which suggests to use that the hash is a base64 string https://learn.microsoft.com/en-us/onedrive/developer/rest-api/resources/hashes

Any example code or hints as to how we should be computing the hash and then returning the string would be much appreciated.

Link to example file: https://dnqa-my.sharepoint.com/:p:/g/personal/autoslave10_dnqauk_co_uk/EcPZl9l2eXNImfD0paFXKyoBHdZwt5mCMRemLKU9wNYIYg?e=63c7632212d948238dd9696c90a11963

OD4B json

{"@odata.context":"omitted","@odata.type":"#oneDrive.item","@odata.id":"omitted","@odata.etag":"\"{D997D9C3-7976-4873-99F0-F4A5A1572B2A},2\"","@odata.editLink":"omitted","createdDateTime":"2017-12-04T17:07:40Z","id":"omitted","lastModifiedDateTime":"2017-12-04T17:07:40Z","name":"pptx001.pptx","file":{"hashes":{"quickXorHash":"LmpqMT5KKX4ATcd372ZTyVr3gIk="},"mimeType":"application/vnd.openxmlformats-officedocument.presentationml.presentation"},"size":29765}

Solution

  • By doing this:

    XOrHash.Create()
    

    you are not actually using your quick xor algorithm. Create() is static method of HashAlgorithm class, which creates some default hash algorithm instance (SHA1 as I remember). So what you are actually calling is:

    HashAlgorithm.Create()
    

    Instead, do it like this:

    using (var quickXor = new XOrHash())