diff --git a/CMakeLists.txt b/CMakeLists.txt
index c4b2238303e7025235ad7c4c8dfbb0d1fa621407..7983b271566373a46549e3c21f4bd245c895febc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,6 +17,7 @@ add_custom_target(check
 add_library(common OBJECT
         src/Message.cpp
 	src/MessageParser.cpp
+        src/Helpers/CRCHelper.cpp
 	src/Services/EventReportService.cpp
         src/Services/MemoryManagementService.cpp
         src/Services/ParameterService.cpp
diff --git a/inc/Helpers/CRCHelper.hpp b/inc/Helpers/CRCHelper.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d70ca5782b7a33add0110990bd23c0c2253dd1e7
--- /dev/null
+++ b/inc/Helpers/CRCHelper.hpp
@@ -0,0 +1,43 @@
+#ifndef ECSS_SERVICES_CRCHELPER_HPP
+#define ECSS_SERVICES_CRCHELPER_HPP
+
+#include <cstdint>
+
+class CRCHelper {
+
+	/**
+	 * CRC32 calculation helper class
+	 * This class declares a function which calculates the CRC16 checksum of the given data.
+	 *
+	 * For now the actual implementation is the CRC16/CCITT variant (ECSS-E-ST-70-41C, pg.615)
+	 * (polynomial 0x1021, normal input), but this can change at any time
+	 * (even to a hardware CRC implementation, if available)
+	 *
+	 * Please report all found bugs.
+	 *
+	 * @author (CRC explanation) http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html
+	 * @author (class code & dox) Grigoris Pavlakis <grigpavl@ece.auth.gr>
+	 */
+
+// TODO: Change this to hardware implementation or a trusted software one
+// TODO: Use CRC with received TC and transmitted TM packets
+public:
+	/**
+	 * Actual CRC calculation function.
+	 * @param  message (pointer to the data to be checksummed)
+	 * @param  length (size in bytes)
+	 * @return the CRC32 checksum of the input data
+	 */
+	static uint16_t calculateCRC(const uint8_t* message, uint32_t length);
+
+	/**
+	 * CRC validation function. Make sure the passed message actually contains a CRC checksum
+	 * appended at the very end!
+	 * @param  message (pointer to the data to be validated)
+	 * @param  length (in bytes, plus 2 bytes for the CRC checksum)
+	 * @return 0 when the data is valid, a nonzero uint16 when the data is corrupted
+	 */
+	 static uint16_t validateCRC(const uint8_t* message, uint32_t length);
+};
+
+#endif //ECSS_SERVICES_CRCHELPER_HPP
diff --git a/src/Helpers/CRCHelper.cpp b/src/Helpers/CRCHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e0cd4ebf914ff885c7f50a52aeec4cd3e42c8da8
--- /dev/null
+++ b/src/Helpers/CRCHelper.cpp
@@ -0,0 +1,34 @@
+#include "Helpers/CRCHelper.hpp"
+
+// TODO: THIS IS TEMPORARY CODE, WILL SURELY BE REPLACED
+
+uint16_t CRCHelper::calculateCRC(const uint8_t* message, uint32_t length) {
+	// shift register contains all 1's initially (ECSS-E-ST-70-41C, Annex B - CRC and ISO checksum)
+	uint16_t shiftReg = 0xFFFFu;
+
+	// CRC16-CCITT generator polynomial (as specified in standard)
+	uint16_t polynomial = 0x1021u;
+
+	for (int i = 0; i < length; i++) {
+		// "copy" (XOR w/ existing contents) the current msg bits into the MSB of the shift register
+		shiftReg ^= (message[i] << 8u);
+
+		for (int j = 0; j < 8; j++) {
+			// if the MSB is set, the bitwise AND gives 1
+			if ((shiftReg & 0x8000u) != 0) {
+				// toss out of the register the MSB and divide (XOR) its content with the generator
+				shiftReg = ((shiftReg << 1u) ^ polynomial);
+			}
+			else {
+				// just toss out the MSB and make room for a new bit
+				shiftReg <<= 1u;
+			}
+		}
+	}
+	return shiftReg;
+}
+
+uint16_t CRCHelper::validateCRC(const uint8_t *message, uint32_t length) {
+	return calculateCRC(message, length);
+	// CRC result of a correct msg w/checksum appended is 0
+}
diff --git a/src/main.cpp b/src/main.cpp
index 277cb16107311a6a318abbc86079f8aa6022e69c..8e2d90d253fad7a1425dca04d07f3766eed5dd89 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include "Helpers/CRCHelper.hpp"
 #include "Services/TestService.hpp"
 #include "Services/ParameterService.hpp"
 #include "Services/RequestVerificationService.hpp"
diff --git a/test/Helpers/CRCHelper.cpp b/test/Helpers/CRCHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..73909a920026b63e62ba0364f0db51777ea665c9
--- /dev/null
+++ b/test/Helpers/CRCHelper.cpp
@@ -0,0 +1,51 @@
+#include "catch2/catch.hpp"
+#include "Helpers/CRCHelper.hpp"
+
+TEST_CASE("CRC calculation - Basic string tests") {
+	CHECK(CRCHelper::calculateCRC((uint8_t*) "Raccoon Squad!", 14) == 0x08FC);
+	CHECK(CRCHelper::calculateCRC((uint8_t*) "ASAT", 4) == 0xBFFA);
+	CHECK(CRCHelper::calculateCRC((uint8_t*) "All your space are belong to us", 31) == 0x545F);
+	CHECK(CRCHelper::calculateCRC((uint8_t*) "SPAAAAAAAAACE!", 14) == 0xB441);
+}
+
+TEST_CASE("CRC calculation - Basic byte tests") {
+	SECTION("ECSS compliance verification tests (p.617)") {
+		uint8_t data1[2] = {0x00, 0x00};
+		uint8_t data2[3] = {0x00, 0x00, 0x00};
+		uint8_t data3[4] = {0xAB, 0xCD, 0xEF, 0x01};
+		uint8_t data4[6] = {0x14, 0x56, 0xF8, 0x9A, 0x00, 0x01};
+
+		CHECK(CRCHelper::calculateCRC(data1, 2) == 0x1D0F);
+		CHECK(CRCHelper::calculateCRC(data2, 3) == 0xCC9C);
+		CHECK(CRCHelper::calculateCRC(data3, 4) == 0x04A2);
+		CHECK(CRCHelper::calculateCRC(data4, 6) == 0x7FD5);
+	}
+
+	SECTION("Null (0x00) before ending") {
+		uint8_t data1[5] = {0x45, 0xF2, 0x00, 0xA2, 0x01};
+		uint8_t data2[8] = {0x21, 0x65, 0xDF, 0x00, 0xC4, 0x00, 0x00, 0xBF};
+		uint8_t data3[4] = {0x07, 0x00, 0x05, 0xFF};
+
+		CHECK(CRCHelper::calculateCRC(data1, 5) == 0x3A2B);
+		CHECK(CRCHelper::calculateCRC(data2, 8) == 0x89EE);
+		CHECK(CRCHelper::calculateCRC(data3, 4) == 0x34E8);
+	}
+}
+
+TEST_CASE("CRC validation - Basic tests") {
+	uint8_t data1[7] = {'H', 'e', 'l', 'l', 'o', 0xDA, 0xDA};
+	uint8_t data2[6] = {'A', 'S', 'A', 'T', 0xBF, 0xFA};
+	uint8_t data3[10] = {'S', 'p', 'A', '@', 'A', 'c', '3', '!', 0xB4, 0x41};
+	// checksum from original SPAAAAAAAAACE! string
+	uint8_t data4[6] = {'A', 0x43, 0x52, 0xDF, 0xBF, 0xFA};
+	// ASAT, but "corrupted" with the last 2 bytes the original checksum of the 'ASAT' string
+
+	uint8_t data5[9] = {'C', 'U', 'B', 'E', 'S', 'A', 'T', 0x53, 0x15};  //corrupted CRC checksum
+
+
+	CHECK(CRCHelper::validateCRC(data1, 7) == 0x0);
+	CHECK(CRCHelper::validateCRC(data2, 6) == 0x0);
+	CHECK(CRCHelper::validateCRC(data3, 10) != 0x0);
+	CHECK(CRCHelper::validateCRC(data4, 6) != 0x0);
+	CHECK(CRCHelper::validateCRC(data5, 9) != 0x0);
+}