PHP 怎么Artifact签名

wen PHP项目 2

本文目录导读:

PHP 怎么Artifact签名

  1. 使用 OpenSSL 进行 PGP/GPG 签名(最常用)
  2. 使用 Hash + 数字签名(更轻量)
  3. 使用 Ed25519 签名(现代加密标准)
  4. Maven/Gradle Artifact 签名(针对 Java 发布)
  5. 完整示例:带元数据的签名格式
  6. 注意事项

在 PHP 中进行 Artifact(制品/构建产物)签名,通常有几种不同的场景,这里主要介绍最常见的几种情况,你可以根据具体需求选择对应的方法:

使用 OpenSSL 进行 PGP/GPG 签名(最常用)

这是签名发布包、JAR 文件或 Debian 包最标准的方式。

<?php
// 场景:对文件进行 PGP 签名
$fileToSign = '/path/to/your/artifact.tar.gz';
$privateKey = '/path/to/private-key.pem';
$passphrase = 'your-passphrase';
// 方法1:使用 exec 调用 GPG
exec("gpg --batch --yes --passphrase-fd 0 --armor --detach-sign --output {$fileToSign}.sig {$fileToSign}", 
     $output, $returnCode);
// 方法2:使用 PHP 的 gnupg 扩展(需要安装)
if (function_exists('gnupg_init')) {
    $gpg = gnupg_init();
    gnupg_setsignmode($gpg, GNUPG_SIG_MODE_DETACH);
    gnupg_addsignkey($gpg, 'your-key-id', $passphrase);
    $signature = gnupg_sign($gpg, file_get_contents($fileToSign));
    file_put_contents($fileToSign . '.sig', $signature);
}

使用 Hash + 数字签名(更轻量)

适合自定义的校验机制:

<?php
// 对文件生成 SHA-256 哈希,然后用私钥签名
function signArtifact($filePath, $privateKeyPath) {
    // 1. 计算文件哈希
    $hash = hash_file('sha256', $filePath);
    // 2. 读取私钥
    $privateKey = file_get_contents($privateKeyPath);
    $key = openssl_pkey_get_private($privateKey);
    // 3. 签名
    openssl_sign($hash, $signature, $key, OPENSSL_ALGO_SHA256);
    return base64_encode($signature);
}
// 验证签名
function verifyArtifact($filePath, $signature, $publicKeyPath) {
    $hash = hash_file('sha256', $filePath);
    $publicKey = file_get_contents($publicKeyPath);
    $key = openssl_pkey_get_public($publicKey);
    return openssl_verify($hash, base64_decode($signature), $key, OPENSSL_ALGO_SHA256) === 1;
}

使用 Ed25519 签名(现代加密标准)

PHP 8.1+ 内置支持:

<?php
// 生成密钥对
$keyPair = sodium_crypto_sign_keypair();
$privateKey = sodium_crypto_sign_secretkey($keyPair);
$publicKey = sodium_crypto_sign_publickey($keyPair);
// 签名
$content = file_get_contents('/path/to/artifact.zip');
$signature = sodium_crypto_sign_detached($content, $privateKey);
file_put_contents('/path/to/artifact.sig', $signature);
// 验证
$signature = file_get_contents('/path/to/artifact.sig');
$isValid = sodium_crypto_sign_verify_detached($signature, $content, $publicKey);

Maven/Gradle Artifact 签名(针对 Java 发布)

如果是发布到 Maven 仓库的 JAR:

<?php
// 使用 maven-gpg-plugin 等价操作
exec('mvn gpg:sign-and-deploy-file -Dfile=my-artifact.jar -DpomFile=pom.xml');
// 或者手动对 .jar 和 .pom 文件进行签名
$files = ['my-artifact.jar', 'my-artifact.pom'];
foreach ($files as $file) {
    exec("gpg --armor --detach-sign {$file}", $output, $code);
}

完整示例:带元数据的签名格式

<?php
class ArtifactSigner {
    private $privateKey;
    private $passphrase;
    public function __construct($privateKeyPath, $passphrase = null) {
        $this->privateKey = file_get_contents($privateKeyPath);
        $this->passphrase = $passphrase;
    }
    public function sign($artifactPath) {
        // 生成签名清单
        $manifest = [
            'file' => basename($artifactPath),
            'size' => filesize($artifactPath),
            'sha256' => hash_file('sha256', $artifactPath),
            'md5' => md5_file($artifactPath),
            'timestamp' => date(DATE_ATOM),
            'version' => '1.0.0'
        ];
        // 对清单内容签名
        $content = json_encode($manifest, JSON_PRETTY_PRINT);
        $key = openssl_pkey_get_private($this->privateKey, $this->passphrase);
        openssl_sign($content, $signature, $key, OPENSSL_ALGO_SHA256);
        // 保存签名文件
        $sigFilePath = $artifactPath . '.sig';
        file_put_contents($sigFilePath, json_encode([
            'manifest' => $manifest,
            'signature' => base64_encode($signature)
        ], JSON_PRETTY_PRINT));
        return $sigFilePath;
    }
    public function verify($artifactPath, $sigFilePath, $publicKeyPath) {
        $sigData = json_decode(file_get_contents($sigFilePath), true);
        $manifest = $sigData['manifest'];
        // 重新计算哈希
        $currentHash = hash_file('sha256', $artifactPath);
        if ($currentHash !== $manifest['sha256']) {
            return false;
        }
        // 验证签名
        $publicKey = file_get_contents($publicKeyPath);
        $key = openssl_pkey_get_public($publicKey);
        $content = json_encode($manifest, JSON_PRETTY_PRINT);
        return openssl_verify($content, base64_decode($sigData['signature']), $key, OPENSSL_ALGO_SHA256) === 1;
    }
}

注意事项

  1. 安全存储密钥:不要将私钥硬编码在代码中,使用环境变量或密钥管理服务
  2. 使用安全的哈希算法:推荐 SHA-256 或更强
  3. 考虑签名过期时间:在需签名的元数据中包含时间戳
  4. 备份签名验证公钥:用于后续验证

选择哪种方式取决于你的使用场景(是发布包、内部工具还是安全要求),可以根据需求灵活选择。

抱歉,评论功能暂时关闭!