summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md6
-rw-r--r--README.md4
-rw-r--r--config.m418
-rw-r--r--package.xml13
-rw-r--r--php_xpass.h2
-rw-r--r--tests/crypt_gensalt2.phpt15
-rw-r--r--tests/sm3crypt.phpt71
-rw-r--r--tests/sm3yescrypt.phpt71
-rw-r--r--xpass.c63
-rw-r--r--xpass.stub.php6
-rw-r--r--xpass_arginfo.h8
11 files changed, 265 insertions, 12 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5ecd6c..a8d0ef8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
# Unreleased
--
+# Version 1.2.0 - 2026-01-13
+
+- add SM3 hash algos available in libxcrypt 4.5
+- add CRYPT_PREFIX_SM3CRYPT and CRYPT_PREFIX_SM3_YESCRYPT constants
+- add PASSWORD_SM3CRYPT and PASSWORD_SM3_YESCRYPT constants
# Version 1.1.0 - 2024-09-26
diff --git a/README.md b/README.md
index 3b8b354..56f4a5d 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,8 @@ This extension provides password hashing algorithms used by Linux distributions.
* **sha512** (`$6$`) provided for legacy as used on some old distributions (ex: RHEL-8)
* **yescrypt** (`$y$`) used on modern distributions
+* **sm3crypt** (`$sm3$`)
+* **sm3yescrypt** (`$sm3y$`)
Notices: these can be fast, don't expect improved security level.
@@ -28,6 +30,8 @@ See the Linux man pages or [PHP Documentation](https://www.php.net/xpass)
* yescrypt: 0.14" with cost=6
* yescrypt: 0.30" with cost=7
* yescrypt: 0.62" with cost=8
+* sm3crypt: 0.01"
+* yessm3crypt: 0.02"
# Sources
diff --git a/config.m4 b/config.m4
index fb6b2e7..a4156a0 100644
--- a/config.m4
+++ b/config.m4
@@ -50,6 +50,24 @@ int main(void) {
AC_MSG_RESULT([missing])
])
+ AC_MSG_CHECKING([for sm3 algo])
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <string.h>
+#include <unistd.h>
+#include <crypt.h>
+#include <stdlib.h>
+
+int main(void) {
+ char salt[8];
+ salt[0]='$'; salt[1]='s'; salt[2]='m'; salt[3]='3'; salt[4]='$'; salt[5]=0;
+ return crypt_gensalt(salt, 0, NULL, 0) ? 0 : 1;
+}]])],[
+ AC_DEFINE([HAVE_CRYPT_SM3], [1], [ Have sm3 hash support ])
+ AC_MSG_RESULT([available])
+ ], [
+ AC_MSG_RESULT([missing])
+ ])
+
CFLAGS=$old_CFLAGS
LIBS=$old_LIBS
diff --git a/package.xml b/package.xml
index 7fb2348..0db5bc5 100644
--- a/package.xml
+++ b/package.xml
@@ -9,6 +9,8 @@ distributions, using extended crypt library (libxcrypt):
* sha512 provided for legacy as used on some old distributions
* yescrypt used on modern distributions
+* sm3crypt
+* sm3yescrypt
It also provides additional functions from libxcrypt missing in core PHP:
@@ -24,9 +26,9 @@ See PHP documentation on https://www.php.net/xpass
<email>remi@php.net</email>
<active>yes</active>
</lead>
- <date>2024-09-26</date>
+ <date>2026-01-13</date>
<version>
- <release>1.1.1dev</release>
+ <release>1.2.0</release>
<api>1.1.0</api>
</version>
<stability>
@@ -35,7 +37,9 @@ See PHP documentation on https://www.php.net/xpass
</stability>
<license uri="https://www.php.net/license/3_01.txt" filesource="LICENSE">PHP-3.01</license>
<notes><![CDATA[
--
+- add SM3 hash algos available in libxcrypt 4.5
+- add CRYPT_PREFIX_SM3CRYPT and CRYPT_PREFIX_SM3_YESCRYPT constants
+- add PASSWORD_SM3CRYPT and PASSWORD_SM3_YESCRYPT constants
]]></notes>
<contents>
<dir name="/">
@@ -54,9 +58,12 @@ See PHP documentation on https://www.php.net/xpass
<dir name ="tests">
<file name="crypt_checksalt.phpt" role="test"/>
<file name="crypt_gensalt.phpt" role="test"/>
+ <file name="crypt_gensalt2.phpt" role="test"/>
<file name="crypt_preferred_method.phpt" role="test"/>
<file name="password_compat.phpt" role="test"/>
<file name="sha512.phpt" role="test"/>
+ <file name="sm3crypt.phpt" role="test"/>
+ <file name="sm3yescrypt.phpt" role="test"/>
<file name="xpass.phpt" role="test"/>
<file name="yescrypt.phpt" role="test"/>
</dir>
diff --git a/php_xpass.h b/php_xpass.h
index 0d10ff2..d904a0a 100644
--- a/php_xpass.h
+++ b/php_xpass.h
@@ -22,7 +22,7 @@
extern zend_module_entry xpass_module_entry;
#define phpext_xpass_ptr &xpass_module_entry
-#define PHP_XPASS_VERSION "1.1.0"
+#define PHP_XPASS_VERSION "1.2.0"
#define PHP_XPASS_AUTHOR "Remi Collet"
#define PHP_XPASS_LICENSE "PHP-3.01"
diff --git a/tests/crypt_gensalt2.phpt b/tests/crypt_gensalt2.phpt
new file mode 100644
index 0000000..864c614
--- /dev/null
+++ b/tests/crypt_gensalt2.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Test crypt_gensalt
+--SKIPIF--
+<?php
+if (!defined("CRYPT_PREFIX_SM3CRYPT")) die("skip SM3CRYPT missing");
+?>
+--FILE--
+<?php
+var_dump(crypt_gensalt(CRYPT_PREFIX_SM3CRYPT));
+var_dump(crypt_gensalt(CRYPT_PREFIX_SM3_YESCRYPT));
+
+?>
+--EXPECTF--
+string(21) "$sm3$%s"
+string(32) "$sm3y$%s"
diff --git a/tests/sm3crypt.phpt b/tests/sm3crypt.phpt
new file mode 100644
index 0000000..c398eed
--- /dev/null
+++ b/tests/sm3crypt.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Check sm3crypt algo
+--EXTENSIONS--
+xpass
+--SKIPIF--
+<?php
+if (!defined("PASSWORD_SM3CRYPT")) die("skip SM3CRYPT missing");
+?>
+--FILE--
+<?php
+$data = [
+ 'mysecret' => '$sm3$wjwOAHL3D6DzuOsN$QF8mPXc8WfTfOE1PsWw05FgUogEEWqE5jh/ZlhCFof.',
+ 'remicollet' => '$sm3$L/iCXvrL76KHTQBh$Jj0jcZoeFgH7wb3Tepl6yiVhL4Pm5Kd6GcInazUcOs.',
+];
+foreach($data as $pass => $hash) {
+ echo "-- $pass\n";
+ var_dump(password_verify($pass, $hash));
+ var_dump(password_get_info($hash));
+ var_dump(password_verify($pass."bad", $hash));
+ var_dump(password_verify($pass, $hash."bad"));
+ var_dump(password_needs_rehash($hash, PASSWORD_SM3CRYPT));
+}
+
+echo "-- no cost\n";
+$pass = 'secret';
+var_dump($hash = password_hash($pass, PASSWORD_SM3CRYPT));
+var_dump(password_get_info($hash));
+var_dump(password_verify($pass, $hash));
+?>
+--EXPECTF--
+-- mysecret
+bool(true)
+array(3) {
+ ["algo"]=>
+ string(3) "sm3"
+ ["algoName"]=>
+ string(8) "sm3crypt"
+ ["options"]=>
+ array(0) {
+ }
+}
+bool(false)
+bool(false)
+bool(true)
+-- remicollet
+bool(true)
+array(3) {
+ ["algo"]=>
+ string(3) "sm3"
+ ["algoName"]=>
+ string(8) "sm3crypt"
+ ["options"]=>
+ array(0) {
+ }
+}
+bool(false)
+bool(false)
+bool(true)
+-- no cost
+string(65) "$sm3$%s"
+array(3) {
+ ["algo"]=>
+ string(3) "sm3"
+ ["algoName"]=>
+ string(8) "sm3crypt"
+ ["options"]=>
+ array(0) {
+ }
+}
+bool(true)
+
diff --git a/tests/sm3yescrypt.phpt b/tests/sm3yescrypt.phpt
new file mode 100644
index 0000000..a0884d9
--- /dev/null
+++ b/tests/sm3yescrypt.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Check sm3yescrypt algo
+--EXTENSIONS--
+xpass
+--SKIPIF--
+<?php
+if (!defined("PASSWORD_SM3_YESCRYPT")) die("skip SM3_YESCRYPT missing");
+?>
+--FILE--
+<?php
+$data = [
+ 'mysecret' => '$sm3y$j9T$FeOt/DFtz1Mm8/mtgIer2.$MtA20j5f5L.Jz8MM4KuKCFgPstmpnswmC2/9BEPwND.',
+ 'remicollet' => '$sm3y$j9T$ElHlNepC6e7htB1BgBbe4.$VXOJS4j0v49cNKDN/6i66F4nwvTCUT5GsPwqKEewSI/',
+];
+foreach($data as $pass => $hash) {
+ echo "-- $pass\n";
+ var_dump(password_verify($pass, $hash));
+ var_dump(password_get_info($hash));
+ var_dump(password_verify($pass."bad", $hash));
+ var_dump(password_verify($pass, $hash."bad"));
+ var_dump(password_needs_rehash($hash, PASSWORD_SM3_YESCRYPT));
+}
+
+echo "-- no cost\n";
+$pass = 'secret';
+var_dump($hash = password_hash($pass, PASSWORD_SM3_YESCRYPT));
+var_dump(password_get_info($hash));
+var_dump(password_verify($pass, $hash));
+?>
+--EXPECTF--
+-- mysecret
+bool(true)
+array(3) {
+ ["algo"]=>
+ string(4) "sm3y"
+ ["algoName"]=>
+ string(11) "sm3yescrypt"
+ ["options"]=>
+ array(0) {
+ }
+}
+bool(false)
+bool(false)
+bool(false)
+-- remicollet
+bool(true)
+array(3) {
+ ["algo"]=>
+ string(4) "sm3y"
+ ["algoName"]=>
+ string(11) "sm3yescrypt"
+ ["options"]=>
+ array(0) {
+ }
+}
+bool(false)
+bool(false)
+bool(false)
+-- no cost
+string(76) "$sm3y$%s"
+array(3) {
+ ["algo"]=>
+ string(4) "sm3y"
+ ["algoName"]=>
+ string(11) "sm3yescrypt"
+ ["options"]=>
+ array(0) {
+ }
+}
+bool(true)
+
diff --git a/xpass.c b/xpass.c
index 87eb586..ea9ed07 100644
--- a/xpass.c
+++ b/xpass.c
@@ -58,6 +58,11 @@ PHP_MINFO_FUNCTION(xpass)
#else
php_info_print_table_row(2, "yescrypt hash", "no");
#endif
+#ifdef HAVE_CRYPT_SM3
+ php_info_print_table_row(2, "sm3 hash", "yes");
+#else
+ php_info_print_table_row(2, "sm3 hash", "no");
+#endif
php_info_print_table_end();
}
/* }}} */
@@ -97,13 +102,27 @@ static zend_string *php_xpass_hash(const zend_string *password, zend_array *opti
return zend_string_init(data.output, strlen(data.output), 0);
}
+#ifdef HAVE_CRYPT_YESCRYPT
static zend_string *php_xpass_yescrypt_hash(const zend_string *password, zend_array *options) {
return php_xpass_hash(password, options, "$y$");
}
+#endif
+#ifdef HAVE_CRYPT_SHA512
static zend_string *php_xpass_sha512_hash(const zend_string *password, zend_array *options) {
return php_xpass_hash(password, options, "$6$");
}
+#endif
+
+#ifdef HAVE_CRYPT_SM3
+static zend_string *php_xpass_sm3crypt_hash(const zend_string *password, zend_array *options) {
+ return php_xpass_hash(password, options, "$sm3$");
+}
+
+static zend_string *php_xpass_sm3yescrypt_hash(const zend_string *password, zend_array *options) {
+ return php_xpass_hash(password, options, "$sm3y$");
+}
+#endif
static bool php_xpass_verify(const zend_string *password, const zend_string *hash) {
struct crypt_data data;
@@ -130,6 +149,7 @@ static bool php_xpass_needs_rehash(const zend_string *hash, zend_array *options)
return 0;
}
+#ifdef HAVE_CRYPT_SHA512
static const php_password_algo xpass_algo_sha512 = {
"sha512",
php_xpass_sha512_hash,
@@ -138,7 +158,9 @@ static const php_password_algo xpass_algo_sha512 = {
NULL, // php_xpass_yescrypt_get_info,
NULL,
};
+#endif
+#ifdef HAVE_CRYPT_YESCRYPT
static const php_password_algo xpass_algo_yescrypt = {
"yescrypt",
php_xpass_yescrypt_hash,
@@ -147,6 +169,27 @@ static const php_password_algo xpass_algo_yescrypt = {
NULL, // php_xpass_yescrypt_get_info,
NULL,
};
+#endif
+
+#ifdef HAVE_CRYPT_SM3
+static const php_password_algo xpass_algo_sm3crypt = {
+ "sm3crypt",
+ php_xpass_sm3crypt_hash,
+ php_xpass_verify,
+ php_xpass_needs_rehash,
+ NULL, // php_xpass_yescrypt_get_info,
+ NULL,
+};
+
+static const php_password_algo xpass_algo_sm3yescrypt = {
+ "sm3yescrypt",
+ php_xpass_sm3yescrypt_hash,
+ php_xpass_verify,
+ php_xpass_needs_rehash,
+ NULL, // php_xpass_yescrypt_get_info,
+ NULL,
+};
+#endif
/* {{{ Generates a salt for algo */
PHP_FUNCTION(crypt_gensalt)
@@ -203,17 +246,25 @@ PHP_MINIT_FUNCTION(xpass) /* {{{ */ {
register_xpass_symbols(module_number);
#ifdef HAVE_CRYPT_SHA512
- if (FAILURE == php_password_algo_register("6", &xpass_algo_sha512)) {
- return FAILURE;
+ if (SUCCESS == php_password_algo_register("6", &xpass_algo_sha512)) {
+ REGISTER_STRING_CONSTANT("PASSWORD_SHA512", "6", CONST_CS | CONST_PERSISTENT);
}
- REGISTER_STRING_CONSTANT("PASSWORD_SHA512", "6", CONST_CS | CONST_PERSISTENT);
#endif
#ifdef HAVE_CRYPT_YESCRYPT
- if (FAILURE == php_password_algo_register("y", &xpass_algo_yescrypt)) {
- return FAILURE;
+ if (SUCCESS == php_password_algo_register("y", &xpass_algo_yescrypt)) {
+ REGISTER_STRING_CONSTANT("PASSWORD_YESCRYPT", "y", CONST_CS | CONST_PERSISTENT);
+ }
+#endif
+
+#ifdef HAVE_CRYPT_SM3
+ if (SUCCESS == php_password_algo_register("sm3", &xpass_algo_sm3crypt)) {
+ REGISTER_STRING_CONSTANT("PASSWORD_SM3CRYPT", "sm3", CONST_CS | CONST_PERSISTENT);
+ }
+
+ if (SUCCESS == php_password_algo_register("sm3y", &xpass_algo_sm3yescrypt)) {
+ REGISTER_STRING_CONSTANT("PASSWORD_SM3_YESCRYPT", "sm3y", CONST_CS | CONST_PERSISTENT);
}
- REGISTER_STRING_CONSTANT("PASSWORD_YESCRYPT", "y", CONST_CS | CONST_PERSISTENT);
#endif
return SUCCESS;
diff --git a/xpass.stub.php b/xpass.stub.php
index 68718da..18a0b68 100644
--- a/xpass.stub.php
+++ b/xpass.stub.php
@@ -24,6 +24,12 @@ const CRYPT_PREFIX_SCRYPT = '$7$';
const CRYPT_PREFIX_GOST_YESCRYPT = '$gy$';
/** @var string */
const CRYPT_PREFIX_YESCRYPT = '$y$';
+#ifdef HAVE_CRYPT_SM3
+/** @var string */
+const CRYPT_PREFIX_SM3CRYPT = '$sm3$';
+/** @var string */
+const CRYPT_PREFIX_SM3_YESCRYPT = '$sm3y$';
+#endif
/**
* @var int
diff --git a/xpass_arginfo.h b/xpass_arginfo.h
index f530d0f..b3f3e1c 100644
--- a/xpass_arginfo.h
+++ b/xpass_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 9f75db3279543b07de6b59e720e8521694200a7c */
+ * Stub hash: d778eda3c6fd835a9215bde896fbb0c3917c1893 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_crypt_gensalt, 0, 0, IS_STRING, 1)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, prefix, IS_STRING, 1, "null")
@@ -35,6 +35,12 @@ static void register_xpass_symbols(int module_number)
REGISTER_STRING_CONSTANT("CRYPT_PREFIX_SCRYPT", "$7$", CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("CRYPT_PREFIX_GOST_YESCRYPT", "$gy$", CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("CRYPT_PREFIX_YESCRYPT", "$y$", CONST_PERSISTENT);
+#if defined(HAVE_CRYPT_SM3)
+ REGISTER_STRING_CONSTANT("CRYPT_PREFIX_SM3CRYPT", "$sm3$", CONST_PERSISTENT);
+#endif
+#if defined(HAVE_CRYPT_SM3)
+ REGISTER_STRING_CONSTANT("CRYPT_PREFIX_SM3_YESCRYPT", "$sm3y$", CONST_PERSISTENT);
+#endif
REGISTER_LONG_CONSTANT("CRYPT_SALT_OK", CRYPT_SALT_OK, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("CRYPT_SALT_INVALID", CRYPT_SALT_INVALID, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("CRYPT_SALT_METHOD_DISABLED", CRYPT_SALT_METHOD_DISABLED, CONST_PERSISTENT);