diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2801d6e..b463059 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.5)
 
 project(crc16 LANGUAGES C)
 project(crc32 LANGUAGES C)
+project(jamcrc LANGUAGES C)
 
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
@@ -19,6 +20,10 @@ set(CRC32_SOURCES
     libcrc-2.0/src/crc32.c
 )
 
+set(JAMCRC_SOURCES
+    src/plugin_jamcrc.c
+)
+
 add_library(crc16 SHARED
     ${LIBCRC_HEADERS}
     ${CRC16_SOURCES}
@@ -29,8 +34,15 @@ add_library(crc32 SHARED
     ${CRC32_SOURCES}
 )
 
+add_library(jamcrc SHARED
+    ${LIBCRC_HEADERS}
+    ${JAMCRC_SOURCES}
+)
+
 target_include_directories(crc16 PRIVATE libcrc-2.0/include)
 target_include_directories(crc32 PRIVATE libcrc-2.0/include)
+target_include_directories(jamcrc PRIVATE libcrc-2.0/include)
 
 install(TARGETS crc16 DESTINATION share/checkbrute/plugins)
 install(TARGETS crc32 DESTINATION share/checkbrute/plugins)
+install(TARGETS jamcrc DESTINATION share/checkbrute/plugins)
diff --git a/src/plugin_jamcrc.c b/src/plugin_jamcrc.c
new file mode 100644
index 0000000..4c7fad5
--- /dev/null
+++ b/src/plugin_jamcrc.c
@@ -0,0 +1,69 @@
+#include <stdbool.h>
+#include "checksum.h"
+
+static void init_crc32_tab(void);
+static bool crc_tab32_init = false;
+static uint32_t	crc_tab32[256];
+
+static void init_crc32_tab(void) {
+
+    uint32_t i;
+    uint32_t j;
+    uint32_t crc;
+
+    for (i = 0; i < 256; i++) {
+        crc = i;
+        for (j = 0; j < 8; j++) {
+            if (crc & 0x00000001L) {
+                crc = (crc >> 1) ^ CRC_POLY_32;
+            }
+            else {
+                crc = crc >> 1;
+            }
+        }
+        crc_tab32[i] = crc;
+    }
+    crc_tab32_init = true;
+}
+
+const char* checkbrute_format()
+{
+    return "JAMCRC";
+}
+
+const char* checkbrute_version()
+{
+    return "0.1";
+}
+
+uint32_t checkbrute_hash32(unsigned char* data, size_t size)
+{
+    uint32_t crc;
+    uint32_t tmp;
+    uint32_t long_c;
+    const unsigned char *ptr;
+    size_t a;
+
+    if (!crc_tab32_init)
+        init_crc32_tab();
+
+    crc = CRC_START_32;
+    ptr = data;
+
+    if (ptr != NULL)
+        for (a = 0; a < size; a++) {
+            long_c = 0x000000FFL & (uint32_t)*ptr;
+            tmp = crc ^ long_c;
+            crc = (crc >> 8) ^ crc_tab32[tmp & 0xff];
+            ptr++;
+        }
+
+    crc ^= 0x00000000L;
+
+    return crc & 0xffffffffL;
+}
+
+int checkbrute_hashsz()
+{
+    return 4;
+}