├── API-1.0.0 ├── CREDITS ├── ssdeep.php ├── config.w32 ├── config.m4 ├── README ├── LICENSE ├── php_ssdeep.h ├── ax_libssdeep.m4 ├── tests └── ssdeep.phpt ├── examples └── example.php ├── ssdeep.c ├── package.xml └── .github └── workflows └── build-test-and-release.yml /API-1.0.0: -------------------------------------------------------------------------------- 1 | API release notes. 2 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | ssdeep 2 | Simon Holywell 3 | -------------------------------------------------------------------------------- /ssdeep.php: -------------------------------------------------------------------------------- 1 | "; 3 | 4 | if(!extension_loaded('ssdeep')) { 5 | dl('ssdeep.' . PHP_SHLIB_SUFFIX); 6 | } 7 | $module = 'ssdeep'; 8 | $functions = get_extension_funcs($module); 9 | echo "Functions available in the test extension:$br\n"; 10 | foreach($functions as $func) { 11 | echo $func."$br\n"; 12 | } 13 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // vim:ft=javascript 2 | 3 | ARG_WITH("ssdeep", "ssdeep support", "no"); 4 | 5 | if (PHP_SSDEEP != "no") { 6 | if (CHECK_LIB("fuzzy_a.lib;fuzzy.lib", "ssdeep", PHP_SSDEEP) && 7 | CHECK_HEADER_ADD_INCLUDE("fuzzy.h", "CFLAGS_SSDEEP") && 8 | CHECK_HEADER_ADD_INCLUDE("edit_dist.h", "CFLAGS_SSDEEP")) { 9 | EXTENSION("ssdeep", "ssdeep.c"); 10 | } else { 11 | WARNING("ssdeep not enabled; libraries and headers not found"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_WITH(ssdeep, for ssdeep support, 2 | [ --with-ssdeep[=DIR] Include ssdeep support. DIR is the optional path to the ssdeep directory.], yes) 3 | PHP_ARG_ENABLE(ssdeep-debug, whether to enable build debug output, 4 | [ --enable-ssdeep-debug ssdeep: Enable debugging during build], no, no) 5 | 6 | if test "$PHP_SSDEEP" != "no"; then 7 | withssdeep="$PHP_SSDEEP" 8 | ssdeep_enabledebug="$PHP_SSDEEP_DEBUG" 9 | dnl Pass in the library directory name specified by PHP - defaults to lib 10 | ssdeep_libdirname="$PHP_LIBDIR" 11 | 12 | dnl Include common ssdeep availability test function 13 | m4_include(ax_libssdeep.m4) 14 | AX_SSDEEP 15 | 16 | if test $SSDEEP_FOUND = "yes"; then 17 | PHP_CHECK_LIBRARY($SSDEEP_LIB_NAME, fuzzy_compare, 18 | [ 19 | dnl Add the neccessary paths (vars declared in ax_libssdeep.m4) 20 | PHP_ADD_INCLUDE($SSDEEP_INCLUDEDIR_NO_FLAG) 21 | PHP_ADD_LIBRARY_WITH_PATH($SSDEEP_LIB_NAME, $SSDEEP_LIBDIR_NO_FLAG, SSDEEP_SHARED_LIBADD) 22 | AC_DEFINE(HAVE_SSDEEP, 1, [Whether you have SSDEEP]) 23 | ],[ 24 | AC_MSG_ERROR([ssdeep lib not found. See config.log for more information.]) 25 | ],[$SSDEEP_LIBDIR] 26 | ) 27 | PHP_NEW_EXTENSION(ssdeep, ssdeep.c, $ext_shared) 28 | PHP_SUBST(SSDEEP_SHARED_LIBADD) 29 | fi 30 | else 31 | AC_MSG_RESULT([ssdeep was not enabled]) 32 | AC_MSG_ERROR([Enable ssdeep to build this extension.]) 33 | fi 34 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | # ssdeep PECL extension for PHP 2 | 3 | Fuzzy hashing makes it easy to identify similar or almost identical text by simply comparing two hashes against each other. 4 | 5 | The ssdeep project page describes it as a library for "...computing context triggered piecewise hashes (CTPH). Also called fuzzy hashes, CTPH can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length". 6 | 7 | For an in depth paper explaining context triggered piecewise hashes please see http://dfrws.org/2006/proceedings/12-Kornblum.pdf 8 | 9 | ## ssdeep API Information 10 | 11 | Requires at least ssdeep v2.5. 12 | 13 | This extensions wraps the ssdeep fuzzy hashing API created by Jesse Kornblum. 14 | 15 | For more information about ssdeep, the API and context triggered piecewise hashing please see http://ssdeep.sourceforge.net/ 16 | 17 | ## ssdeep Licensing Exemption 18 | 19 | Although ssdeep and the fuzzy hashing API are usually licensed under GNU GPLv2 Jesse Kornblum has licenced them to PECL under the terms of the Perl Artistic Licence with the following declaration: 20 | "I hereby license ssdeep, the current version and all subsequent versions, under the terms of the Perl Artistic License, for inclusion into the PECL." 21 | See http://news.php.net/php.pecl.dev/7625 for the verbatim email. 22 | 23 | ## libfuzzy Windows builds 24 | 25 | Windows PECL dependencies are available from windows.php.net: https://windows.php.net/downloads/pecl/deps/ 26 | 27 | There are build sources on github: https://github.com/winlibs/ssdeep although it is unclear what the source of 2.14.1 builds on windows.php.net is because this has the latest version of ssdeep as 2.13. 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | PECL ssdeep PHP Extension Licence 2 | ------- 3 | This extension is under the BSD Licence: 4 | 5 | Copyright (c) 2018, Simon Holywell 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, this 12 | list of conditions and the following disclaimer. 13 | 14 | * Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | 30 | ssdeep Licensing Exemption 31 | ------- 32 | 33 | Although ssdeep and the fuzzy hashing API are usually licensed under GNU GPLv2 Jesse Kornblum has licenced them to PECL under the terms of the Perl Artistic Licence with the following declaration: 34 | "I hereby license ssdeep, the current version and all subsequent versions, under the terms of the Perl Artistic License, for inclusion into the PECL." 35 | See http://news.php.net/php.pecl.dev/7625 for the verbatim email. 36 | -------------------------------------------------------------------------------- /php_ssdeep.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * php_ssdeep 4 | * 5 | * http://treffynnon.github.com/php_ssdeep/ 6 | * 7 | * A PHP extension to expose ssdeep functionality for fuzzy 8 | * hashing and comparing. 9 | * 10 | * Version 1.1.1 11 | * 12 | * BSD Licensed. 13 | * 14 | * Copyright (c) 2018, Simon Holywell 15 | * All rights reserved. 16 | * 17 | * Redistribution and use in source and binary forms, with or without 18 | * modification, are permitted provided that the following conditions are met: 19 | * 20 | * * Redistributions of source code must retain the above copyright notice, this 21 | * list of conditions and the following disclaimer. 22 | * 23 | * * Redistributions in binary form must reproduce the above copyright notice, 24 | * this list of conditions and the following disclaimer in the documentation 25 | * and/or other materials provided with the distribution. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 34 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 35 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | * 38 | */ 39 | 40 | #ifndef PHP_SSDEEP_H 41 | # define PHP_SSDEEP_H 1 42 | # define PHP_SSDEEP_VERSION "1.1.1" 43 | # define PHP_SSDEEP_EXTNAME "ssdeep" 44 | PHP_FUNCTION(ssdeep_fuzzy_hash); 45 | PHP_FUNCTION(ssdeep_fuzzy_compare); 46 | PHP_FUNCTION(ssdeep_fuzzy_hash_filename); 47 | 48 | extern zend_module_entry php_ssdeep_module_entry; 49 | # define phpext_php_ssdeep_ptr &php_ssdeep_module_entry 50 | 51 | #if PHP_MAJOR_VERSION < 7 52 | typedef int strsize_t; 53 | #define _RETURN_STRING(s) RETURN_STRING(s, 0); 54 | #else 55 | typedef size_t strsize_t; 56 | #define _RETURN_STRING(s) { RETVAL_STRING(s); efree(s); return; } 57 | #endif 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /ax_libssdeep.m4: -------------------------------------------------------------------------------- 1 | ##### 2 | # 3 | # SYNOPSIS 4 | # 5 | # AX_SSDEEP() 6 | # 7 | # DESCRIPTION 8 | # 9 | # This macro provides tests of availability for the SSDEEP library and headers. 10 | # 11 | # This macro calls: 12 | # 13 | # AC_SUBST(SSDEEP_LIBDIR) 14 | # AC_SUBST(SSDEEP_LIBS) 15 | # AC_SUBST(SSDEEP_INCLUDEDIR) 16 | # 17 | ##### 18 | AC_DEFUN([AX_SSDEEP], [ 19 | AC_MSG_CHECKING(for ssdeep) 20 | 21 | AC_CANONICAL_HOST 22 | LIB_EXTENSION="so" 23 | case $host_os in 24 | darwin*) 25 | LIB_EXTENSION="dylib" 26 | ;; 27 | esac 28 | 29 | SSDEEP_LIB_NAME="fuzzy" 30 | SSDEEP_LIB_FILENAME="lib$SSDEEP_LIB_NAME.$LIB_EXTENSION" 31 | SSDEEP_INCLUDE_FILENAME="$SSDEEP_LIB_NAME.h" 32 | 33 | if test -z "$withssdeep" -o "$withssdeep" = "yes"; then 34 | for i in "/usr/$ssdeep_libdirname" "/usr/$ssdeep_libdirname/x86_64-linux-gnu" "/usr/$ssdeep_libdirname/aarch64-linux-gnu" "/usr/local/$ssdeep_libdirname"; do 35 | if test -f "$i/$SSDEEP_LIB_FILENAME"; then 36 | SSDEEP_LIB_PATH="$i" 37 | fi 38 | done 39 | elif test "$withssdeep" != "no"; then 40 | for i in "$withssdeep" "$withssdeep/$ssdeep_libdirname" "$withssdeep/.libs"; do 41 | if test -f "$i/$SSDEEP_LIB_FILENAME"; then 42 | SSDEEP_LIB_PATH="$i" 43 | fi 44 | done 45 | else 46 | AC_MSG_ERROR(["Cannot build whilst ssdeep is disabled."]) 47 | fi 48 | 49 | if test "$SSDEEP_LIB_PATH" = ""; then 50 | AC_MSG_ERROR(["Could not find '$SSDEEP_LIB_FILENAME'. Try specifying the path to the ssdeep build directory."]) 51 | fi 52 | 53 | SSDEEP_LIBDIR="-L$SSDEEP_LIB_PATH" 54 | SSDEEP_LIBS="-l$SSDEEP_LIB_NAME" 55 | SSDEEP_LIBDIR_NO_FLAG="$SSDEEP_LIB_PATH" 56 | 57 | if test -z "$withssdeep" -o "$withssdeep" = "yes"; then 58 | for i in /usr/include /usr/local/include; do 59 | if test -f "$i/$SSDEEP_INCLUDE_FILENAME"; then 60 | SSDEEP_INCLUDEDIR="$i" 61 | fi 62 | done 63 | elif test "$withssdeep" != "no"; then 64 | for i in "$withssdeep" "$withssdeep/.." "$withssdeep/include"; do 65 | if test -f "$i/$SSDEEP_INCLUDE_FILENAME"; then 66 | SSDEEP_INCLUDEDIR="$i" 67 | fi 68 | done 69 | else 70 | AC_MSG_ERROR(["Cannot build whilst ssdeep is disabled."]) 71 | fi 72 | 73 | if test "$SSDEEP_INCLUDEDIR" = ""; then 74 | AC_MSG_ERROR(["Could not find ssdeep '$SSDEEP_INCLUDE_FILENAME' header file. Try specifying the path to the ssdeep build directory."]) 75 | fi 76 | 77 | SSDEEP_INCLUDEDIR_NO_FLAG="$SSDEEP_INCLUDEDIR" 78 | SSDEEP_INCLUDEDIR="-I$SSDEEP_INCLUDEDIR" 79 | 80 | AC_MSG_RESULT([$SSDEEP_LIBDIR, $SSDEEP_INCLUDEDIR_NO_FLAG]) 81 | 82 | AC_DEFINE([SSDEEP_ENABLED], [1], [Enables ssdeep]) 83 | 84 | SSDEEP_FOUND="yes" 85 | 86 | if test "$ssdeep_enabledebug" = "yes"; then 87 | echo " " 88 | echo " " 89 | echo " " 90 | echo "======================== Debug ==============================" 91 | echo " " 92 | echo "\$host_os : $host_os" 93 | echo "\$SSDEEP_LIB_NAME : $SSDEEP_LIB_NAME" 94 | echo "\$SSDEEP_LIB_FILENAME : $SSDEEP_LIB_FILENAME" 95 | echo "\$SSDEEP_INCLUDE_FILENAME : $SSDEEP_INCLUDE_FILENAME" 96 | echo "\$SSDEEP_INC_DIR : $SSDEEP_INCLUDEDIR" 97 | echo "\$SSDEEP_INCLUDEDIR_NO_FLAG : $SSDEEP_INCLUDEDIR_NO_FLAG" 98 | echo "\$SSDEEP_LIBDIR : $SSDEEP_LIBDIR" 99 | echo "\$SSDEEP_LIBDIR_NO_FLAG : $SSDEEP_LIBDIR_NO_FLAG" 100 | echo "\$SSDEEP_FOUND : $SSDEEP_FOUND" 101 | echo "\$withssdeep : $withssdeep" 102 | echo "\$ssdeep_enabledebug : $ssdeep_enabledebug" 103 | echo " " 104 | echo "=============================================================" 105 | echo " " 106 | echo " " 107 | echo " " 108 | fi 109 | 110 | AC_SUBST(SSDEEP_LIBDIR) 111 | AC_SUBST(SSDEEP_LIBS) 112 | AC_SUBST(SSDEEP_INCLUDEDIR) 113 | ]) 114 | -------------------------------------------------------------------------------- /tests/ssdeep.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test ssdeep fuzzy hashing functions 3 | --FILE-- 4 | 41 | --CLEAN-- 42 | 48 | --EXPECT-- 49 | string(78) "24:FPlUMKVsgNfgmjFadP6WboWjb8tsH4RSXqMbLFpjwPDt4tFF:9lUajiiPbbnr4RSXqMbppMZ4t3" 50 | string(76) "48:9lUajiiPbbnr4RSXqMbLbmo03Rcq0K/cvhQ+3/M8M5BEaB6:9HFHsGqabmoMR18hQ+308sBdk" 51 | string(100) "48:9lUajiiPbbnr4RSXqMbppMZ4twUlUajiiPbbnr4RSXqMbLbmo03Rcq0K/cvhQ+3X:9HFHsGqCM6tNHFHsGqabmoMR18hQ+30k" 52 | string(100) "48:9lUajiiPbbnr4RSXqMbLbmo03Rcq0K/cvhQ+3/M8M5BEaB1UlUajiiPbbnr4RSXX:9HFHsGqabmoMR18hQ+308sBdsHFHsGqy" 53 | int(57) 54 | int(75) 55 | int(63) 56 | -------------------------------------------------------------------------------- /examples/example.php: -------------------------------------------------------------------------------- 1 | 50 | 51 | /* For PHP 8 */ 52 | #ifndef TSRMLS_D 53 | #define TSRMLS_D void 54 | #define TSRMLS_DC 55 | #define TSRMLS_C 56 | #define TSRMLS_CC 57 | #define TSRMLS_FETCH() 58 | #endif 59 | 60 | /* True global resources - no need for thread safety here */ 61 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ssdeep_fuzzy_hash, 0, 0, 1) 62 | ZEND_ARG_INFO(0, to_hash) 63 | ZEND_END_ARG_INFO() 64 | 65 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ssdeep_fuzzy_hash_filename, 0, 0, 1) 66 | ZEND_ARG_INFO(0, file_name) 67 | ZEND_END_ARG_INFO() 68 | 69 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ssdeep_fuzzy_compare, 0, 0, 2) 70 | ZEND_ARG_INFO(0, signature1) 71 | ZEND_ARG_INFO(0, signature2) 72 | ZEND_END_ARG_INFO() 73 | 74 | /* {{{ ssdeep_functions[] 75 | */ 76 | const zend_function_entry ssdeep_functions[] = { 77 | PHP_FE(ssdeep_fuzzy_hash, arginfo_ssdeep_fuzzy_hash) 78 | PHP_FE(ssdeep_fuzzy_hash_filename, arginfo_ssdeep_fuzzy_hash_filename) 79 | PHP_FE(ssdeep_fuzzy_compare, arginfo_ssdeep_fuzzy_compare) 80 | #ifdef PHP_FE_END 81 | PHP_FE_END 82 | #else 83 | { NULL, NULL, NULL } /* Must be the last line in ssdeep_functions[] */ 84 | #endif 85 | }; 86 | /* }}} */ 87 | 88 | /* {{{ PHP_MINFO_FUNCTION 89 | */ 90 | PHP_MINFO_FUNCTION(ssdeep) { 91 | php_info_print_table_start(); 92 | php_info_print_table_row(2, PHP_SSDEEP_EXTNAME " Module", "enabled"); 93 | php_info_print_table_row(2, "version", PHP_SSDEEP_VERSION); 94 | if (sapi_module.phpinfo_as_text) { 95 | /* No HTML for you */ 96 | php_info_print_table_row(2, "By", 97 | "Simon Holywell\nhttp://www.simonholywell.com"); 98 | } else { 99 | /* HTMLified version */ 100 | php_printf("