Simple Checksum that a noob can use?

Hi All,

I’m making a data logger using Arduino Uno Rev3 and an adafruit SD data logger shield.

When the user is finished with this logger they will then take out the SD card and put it into their PC.

I want to make sure that the user doesn’t modify the data on the SD card using their PC so I write 2 files with the Arduino that are named with the same number: “logger##” and “CheckS##”

Logger## contains the logger data and CheckS## contains the number of bytes in the Logger## file.

The user has to use a program I wrote in visual basic on the PC to look the logger files which compares the filesize of Logger## and the data in CheckS## to see if they match.

This works fine but of course the data can still be changed without my program detecting it as long as the number of bytes remain the same.

I’ve looked at CRC on arduino across google and I’ll be honest it’s going way over my head.

Does anyone know of a simple way to produce a checksum file of my logger data?

Cheers

Steve

Well, does it have to be secure? If not, you can just calculate an 8 bit checksum by repeated addition mod 256. Or you can use a lateral exclusive or:

byte stringChecksum(char *s)
{
    byte c = 0;
    while(*s != '\0')
        c ^= *s++; 
    return c;
}

But even a weekend hacker can crack this in less than 20 minutes, after seeing a checksum file that contains only a few bytes. Unless you obfuscate it in some way.

megamef:
I’ve looked at CRC on arduino across google and I’ll be honest it’s going way over my head.

Does anyone know of a simple way to produce a checksum file of my logger data?

You can easily create 16-bit crc values using the built-in crc functions of the AVR LIBC, which is the main library of the Arduino software.

Here is an example function that uses the built-in _crc16_update() function to create a CRC across a string:

#include <util/crc16.h>

uint16_t calcCRC(char* str)
{
  uint16_t crc=0; // starting value as you like, must be the same before each calculation
  for (int i=0;i<strlen(str);i++) // for each character in the string
  {
    crc= _crc16_update (crc, str[i]); // update the crc value
  }
  return crc;
}

char str[]="The quick brown fox jumps over the lazy dog.";

void setup() {
  Serial.begin(9600);
  Serial.println(str);
  Serial.print("CRC: ");Serial.println(calcCRC(str));
}

void loop() {
}

With a data logger logging ASCII data lines in CSV format you could for example create a crc value for each line and append the crc value as the last value.

Or you could create another function that creates a CRC value across a whole file.

When reading in the data, you could then recalculate the CRC value if it is the same, for a single line or for a whole file.

As the CRC functions in the AVR LIBC are written in optimized assembler, you will need another code for your PC platform to calculate the same value. This would be the equivalent function in C to calculate the crc:

uint16_t crc16_update(uint16_t crc, uint8_t a)
{
  int i;
  crc ^= a;
  for (i = 0; i < 8; ++i)
  {
    if (crc & 1)
    crc = (crc >> 1) ^ 0xA001;
    else
    crc = (crc >> 1);
  }
  return crc;
}

As there are many different types and CRC value calculations, you must be sure that you have the same calculation for your Arduino and your PC, so that the calculated CRCs will be identical on different platforms

The user has to use a program I wrote in visual basic on the PC to look the logger files

What if the user uses a different program to look at the (possibly modified) data?

crc16.h: avr-libc: crc16.h File Reference

justinmreina: crc16.h: avr-libc: crc16.h File Reference

Did you see the same answer in reply #2, given 5 years ago?