先给结论:
                                                                                                                          国密 SM2/SM3/SM4 集成到 PHP,最佳方式是“做一个标准 PHP 扩展 + 依赖成熟国密库(OpenSSL 国密分支或 GmSSL)+ 按需静态编 进──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   PHP”。                                                                                                                不要硬改 Zend 核心,也不要自己从零手搓密码学实现。

  ---
  一、先分清三种“集成层级”

  1. 动态扩展 so(推荐起步)
    - extension=gmcrypto.so
    - 开发快、升级快、回滚快
  2. 静态编译进 PHP(推荐生产稳态)
    - --enable-gmcrypto 不带 shared
    - 部署更统一,不怕漏装 so
  3. 魔改 php-src 内核
    - 不推荐,升级痛苦,维护成本爆炸

  ---
  二、你要集成的能力长这样

  - sm3(string $data): string -> 返回摘要 hex
  - sm4_encrypt(string $plain, string $key, string $iv, string $mode): string
  - sm4_decrypt(...)
  - sm2_sign(string $data, string $priKeyPem): string
  - sm2_verify(string $data, string $sig, string $pubKeyPem): bool
  - sm2_encrypt/sm2_decrypt(看业务是否需要)

  ---
  三、底层实现最稳路线

  方案 A:基于 OpenSSL EVP(优先)

  如果你环境 OpenSSL 已支持 SM 算法(国密版/支持分支),直接走 EVP 接口。

  优点:
  - 接口统一
  - 性能和安全性更可控
  - 容易跟 TLS 体系协同

  方案 B:基于 GmSSL

  如果 OpenSSL 版本不带国密,直接用 GmSSL。

  优点:
  - 国密能力全
  - 资料和实践较多

  ---
  四、扩展结构(最小工程)

  ext/gmcrypto/
    config.m4
    php_gmcrypto.h
    gmcrypto.c
    tests/

  ---
  五、核心代码骨架(示意,够你开工)

  config.m4

  PHP_ARG_ENABLE(gmcrypto, whether to enable gmcrypto,
  [  --enable-gmcrypto   Enable gmcrypto], no)

  if test "$PHP_GMCRYPTO" != "no"; then
    PHP_ADD_LIBRARY(ssl,, GMCRYPTO_SHARED_LIBADD)
    PHP_ADD_LIBRARY(crypto,, GMCRYPTO_SHARED_LIBADD)
    PHP_SUBST(GMCRYPTO_SHARED_LIBADD)
    PHP_NEW_EXTENSION(gmcrypto, gmcrypto.c, $ext_shared)
  fi

  gmcrypto.c(示意)

  PHP_FUNCTION(sm3_hash);
  PHP_FUNCTION(sm4_encrypt);
  PHP_FUNCTION(sm4_decrypt);
  PHP_FUNCTION(sm2_sign);
  PHP_FUNCTION(sm2_verify);

  static const zend_function_entry gmcrypto_functions[] = {
      PHP_FE(sm3_hash, NULL)
      PHP_FE(sm4_encrypt, NULL)
      PHP_FE(sm4_decrypt, NULL)
      PHP_FE(sm2_sign, NULL)
      PHP_FE(sm2_verify, NULL)
      PHP_FE_END
  };

  zend_module_entry gmcrypto_module_entry = {
      STANDARD_MODULE_HEADER,
      "gmcrypto",
      gmcrypto_functions,
      PHP_MINIT(gmcrypto),
      NULL, NULL, NULL,
      PHP_MINFO(gmcrypto),
      "1.0.0",
      STANDARD_MODULE_PROPERTIES
  };

  ---
  六、编译方式

  动态扩展

  phpize
  ./configure --enable-gmcrypto
  make -j"$(nproc)"
  make install

  php.ini:
  extension=gmcrypto.so

  静态内置

  把扩展放进 php-src 的 ext/,然后:
  ./buildconf --force
  ./configure ... --enable-gmcrypto
  make -j"$(nproc)"
  make install

  ---
  七、生产最佳实践(非常关键)

  1. 密码实现别自己写数学细节,只封装成熟库 API
  2. 密钥别落盘明文,走 HSM/KMS 或最少加密存储
  3. SM4 必须带随机 IV/nonce,不要固定 IV
  4. 优先 AEAD 或“加密+完整性校验”,别只加密不验完整性
  5. 接口版本化(如 sm4_encrypt_v2),避免后续升级打断业务
  6. 写 phpt + 交叉验签测试(和 Java/Go 国密库互通)

  ---
  八、常见坑

  - 把 SM4 当成“ECB 默认模式”直接用(不安全)
  - PEM/DER 编码处理混乱,跨语言互通失败
  - 签名原文编码不统一(UTF-8/GBK)导致验签失败
  - 只在开发机可用,线上 OpenSSL 不支持国密算法

  ---
  一句话收尾:

  国密集成最优解是“扩展化封装 + 依赖成熟国密库 + 先动态后静态 + 严格密钥与模式规范”,这样既安全又可长期维护。

更多推荐