Proposal of a Checksum for RESTful Record Validation

To ensure the integrity and validity of records in a RESTful database, each record should include a checksum value. This value helps verify that the record's reported last modification is correct and that the data has not been tampered with. We recommend using the SHA-256 cryptographic hash standard for generating these checksums. SHA-256 is part of the SHA-2 family, endorsed by the National Institute of Standards and Technology (NIST) under the FIPS 180-4 standard. It is known for its computational speed, data integrity, and change detection capabilities, making it an industry-standard approach for creating and verifying checksums.

Why SHA-256?

Security and Robustness

SHA-256 offers a high level of security compared to other hash functions. It generates a unique 256-bit (32-byte) hash value for any input, making it practically impossible to reverse-engineer the original data from the hash. The large output size also reduces the risk of hash collisions, where two different inputs produce the same hash value.

Industry Acceptance

SHA-256 is widely accepted and used across various industries for its reliability and security. Major companies and institutions utilize SHA-256 for its strong cryptographic properties. For example:

  • Google uses SHA-256 in their certificates and data integrity checks.
  • Apple employs SHA-256 for file verification and ensuring the integrity of software downloads.
  • Microsoft uses SHA-256 in their security protocols and digital signatures.
  • Amazon Web Services (AWS) implements SHA-256 for securing data in transit and at rest.

Performance

Despite its robust security features, SHA-256 is computationally efficient. It is fast enough for real-time applications, making it suitable for validating REST API responses without causing significant delays.

Regulatory Compliance

Using SHA-256 helps in complying with various security regulations and standards, such as GDPR, HIPAA, and PCI-DSS, which often recommend or require strong cryptographic measures to protect data integrity.

The Checksum Use Case

The checksum for RESTful record validation will be generated using SHA-256 to hash a concatenation of the following fields:

  • @type: the type of Element or Thing
  • elementId: The ID of the record.
  • coreMetaData.modified.timeStamp: The most recent modification timestamp of the record.
  • coreMetaData.liveStatus: A Boolean indicating if the record is live (true) or deprecated (false).

These fields combined uniquely identify the record, indicate its last modification time, and specify its status.

Important Note:

Ensure to use the string value of "true" or "false" when converting liveStatus field value to the string to be hashed

Creating or Updating a Record

When creating or updating a record, the system will calculate the checksum using SHA-256 based on the concatenated values of @type, timeStamp, elementId, and liveStatus. For example, given the following values:

{
    "@context": "https://grcschema.org/",
    "@type": "Group",
    "@id": "https://api.app.unifiedcompliance.com/api/group/12",
    "elementId": 12,
    "coreMetaData": {
        "@type": "CoreMetaData",
        "created": {
            "@type": "Created",
            "timeStamp": "2021-07-28T18:53:23.000000Z",
            "organization": null,
            "person": {
                "@type": "Person",
                "@id": "https://api.app.unifiedcompliance.com/api/person/1",
                "elementId": 1,
                "name": "System System"
            }
        },
        "liveStatus": true,
        "modified": {
            "@type": "Modified",
            "timeStamp": "2021-07-28T18:53:23.000000Z",
            "organization": null,
            "person": {
                "@type": "Person",
                "@id": "https://api.app.unifiedcompliance.com/api/person/1",
                "elementId": 1,
                "name": "System System"
            }
        },
        "notes": null,
        "status": null,
        "supersededBy": null,
        "validated": true,
        "checksum": "6ba4d7c11f3faefb8b2eb8d3a6c0058c5a4ee31d959713cba308b3551ff549af"
    }
}

The concatenated string would be:

"Group122021-07-28T18:53:23.000000Ztrue"

The SHA-256 hash of this string will be stored in the checksum field of the record.

Verifying the Checksum

Upon receiving data from the API, users can verify the checksum by recalculating the SHA-256 hash using the same fields (@type, elementId, timeStamp, liveStatus). If the calculated hash matches the stored checksum, the data is valid. Any discrepancy indicates potential tampering or an error.

Example Code for SHA-256 Hashing

Python

import hashlib

def calculate_checksum(type_, element_id, time_stamp, live_status):
    data = f"{type_}{element_id}{time_stamp}{live_status}"
    return hashlib.sha256(data.encode('utf-8')).hexdigest()

# Example usage
type_ = "Group"
element_id = "12"
time_stamp = "2021-07-28T18:53:23.000000Z"
live_status = "true"

checksum = calculate_checksum(type_, element_id, time_stamp, live_status)
print(checksum)

JavaScript (Node.js)

async function hashString(message) {
    const encoder = new TextEncoder();
    const data = encoder.encode(message);
    const hashBuffer = await window.crypto.subtle.digest('SHA-256', data);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
    return hashHex;
}

// Example usage
const type = "Group";
const timeStamp = "2021-07-28T18:53:23.000000Z";
const elementId = "12";
const liveStatus = "true";

const data = `${type}${elementId}${timeStamp}${liveStatus}`;
hashString(data).then(hash => console.log(hash));

PHP

<?php
function calculate_checksum($type, $elementId, $timeStamp, $liveStatus) {
    $data = $type . $elementId . $timeStamp . ($liveStatus ? 'true' : 'false');
    return hash('sha256', $data);
}

// Example usage
$type = "Group";
$elementId = "12";
$timeStamp = "2021-07-28T18:53:23.000000Z";
$liveStatus = true;

$checksum = calculate_checksum($type, $elementId, $timeStamp, $liveStatus);
echo $checksum;
?>

Java

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class ChecksumCalculator {

    public static String calculateChecksum(String type, String elementId, String timeStamp, String liveStatus) throws NoSuchAlgorithmException {
        String data = type + elementId + timeStamp + liveStatus;
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(data.getBytes(StandardCharsets.UTF_8));
        StringBuilder hexString = new StringBuilder();
        
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        
        return hexString.toString();
    }

    public static void main(String[] args) throws NoSuchAlgorithmException {
        String type = "Group";
        String elementId = "12";
        String timeStamp = "2021-07-28T18:53:23.000000Z";
        String liveStatus = "true";

        String checksum = calculateChecksum(type, elementId, timeStamp, liveStatus);
        System.out.println(checksum);
    }
}

C#

using System;
using System.Security.Cryptography;
using System.Text;

public class ChecksumCalculator
{
    public static string CalculateChecksum(string type, string elementId, string timeStamp, string liveStatus)
    {
        string data = $"{type}{elementId}{timeStamp}{liveStatus}";
        using (SHA256 sha256 = SHA256.Create())
        {
            byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(data));
            StringBuilder hashString = new StringBuilder();
            
            foreach (byte b in hashBytes)
            {
                hashString.Append(b.ToString("x2"));
            }
            
            return hashString.ToString();
        }
    }

    public static void Main()
    {
        string type = "Group";
        string elementId = "12";
        string timeStamp = "2021-07-28T18:53:23.000000Z";
        string liveStatus = "true";

        string checksum = CalculateChecksum(type, elementId, timeStamp, liveStatus);
        Console.WriteLine(checksum);
    }
}

By utilizing SHA-256 for checksum calculations, we can ensure data integrity and validate that records have not been altered. This method provides a robust solution for maintaining trust in the data served by our REST API.