PHP 怎么PHP 可验证凭证

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 可验证凭证

  1. 什么是可验证凭证
  2. PHP 实现方案
  3. 推荐的 PHP 库
  4. 最佳实践

我来帮你梳理 PHP 实现可验证凭证(Verifiable Credentials, VC)的相关知识。

什么是可验证凭证

可验证凭证是 W3C 标准下的数字凭证,包含:

  • 凭证元数据(颁发者、有效期等)
  • 声明信息(具体的数据内容)
  • 证明机制(数字签名等)

PHP 实现方案

1 使用 JSON-LD 签名

<?php
class VerifiableCredential {
    private array $credential;
    public function __construct() {
        $this->credential = [
            '@context' => [
                'https://www.w3.org/2018/credentials/v1',
                'https://www.w3.org/2018/credentials/examples/v1'
            ],
            'type' => ['VerifiableCredential', 'UniversityDegreeCredential'],
            'issuer' => '',
            'issuanceDate' => '',
            'credentialSubject' => []
        ];
    }
    public function setIssuer(string $did): self {
        $this->credential['issuer'] = $did;
        return $this;
    }
    public function setSubject(array $subject): self {
        $this->credential['credentialSubject'] = $subject;
        return $this;
    }
    public function addProof(string $type, array $proofData): self {
        $this->credential['proof'] = [
            'type' => $type,
            'created' => date('c'),
            'proofPurpose' => 'assertionMethod',
            ...$proofData
        ];
        return $this;
    }
    public function toJson(): string {
        return json_encode($this->credential, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
    }
}
// 使用示例
$vc = new VerifiableCredential();
$vc->setIssuer('did:example:123456789abcdefghi')
   ->setSubject([
       'id' => 'did:example:123456789abcdefghij',
       'degree' => [
           'type' => 'BachelorDegree',
           'name' => 'Bachelor of Science'
       ]
   ])
   ->addProof('Ed25519Signature2018', [
       'verificationMethod' => 'did:example:123456789abcdefghi#keys-1',
       'jws' => 'eyJhbGciOiJFZERTQSJ9...'
   ]);
echo $vc->toJson();

2 使用 PHP-JWT 实现签名

<?php
require_once 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class VCJWT {
    private string $privateKey;
    private string $publicKey;
    public function __construct() {
        // 生成密钥对(实际项目使用安全的密钥管理)
        $this->generateKeyPair();
    }
    private function generateKeyPair(): void {
        $config = [
            'digest_alg' => 'sha256',
            'private_key_bits' => 2048,
            'private_key_type' => OPENSSL_KEYTYPE_RSA
        ];
        $res = openssl_pkey_new($config);
        openssl_pkey_export($res, $this->privateKey);
        $publicKey = openssl_pkey_get_details($res);
        $this->publicKey = $publicKey['key'];
    }
    public function createVC(array $claims): string {
        $payload = [
            'iss' => 'did:example:issuer',
            'sub' => 'did:example:subject',
            'iat' => time(),
            'exp' => time() + 3600,
            'vc' => [
                '@context' => ['https://www.w3.org/2018/credentials/v1'],
                'type' => ['VerifiableCredential'],
                'credentialSubject' => $claims
            ]
        ];
        return JWT::encode($payload, $this->privateKey, 'RS256');
    }
    public function verifyVC(string $jwt): object {
        try {
            $decoded = JWT::decode($jwt, new Key($this->publicKey, 'RS256'));
            return $decoded;
        } catch (\Exception $e) {
            throw new \Exception('Invalid credential: ' . $e->getMessage());
        }
    }
}
// 使用示例
$vcJwt = new VCJWT();
$credential = $vcJwt->createVC([
    'name' => '张三',
    'age' => 25,
    'degree' => 'Bachelor'
]);
echo "凭证内容:\n";
print_r($vcJwt->verifyVC($credential));

3 完整的 VC 管理类

<?php
class VCCredentialManager {
    private array $credentials = [];
    private array $revokedList = [];
    // 创建可验证凭证
    public function issueCredential(array $data): array {
        $vc = [
            'id' => $this->generateCredentialId(),
            '@context' => [
                'https://www.w3.org/2018/credentials/v1'
            ],
            'type' => ['VerifiableCredential'],
            'issuer' => $data['issuer'] ?? 'did:example:issuer',
            'issuanceDate' => date('c'),
            'credentialSubject' => [
                'id' => $data['subjectId'],
                'data' => $data['claims']
            ],
            'status' => [
                'id' => "https://verifier.example.com/status/" . $this->generateCredentialId(),
                'type' => 'CredentialStatusList2017'
            ]
        ];
        // 添加签名
        $vc['proof'] = $this->generateProof($vc);
        $this->credentials[$vc['id']] = $vc;
        return $vc;
    }
    // 验证凭证
    public function verifyCredential(array $vc): array {
        $result = [
            'valid' => true,
            'errors' => []
        ];
        // 1. 检查结构
        if (!$this->validateStructure($vc)) {
            $result['valid'] = false;
            $result['errors'][] = 'Invalid credential structure';
        }
        // 2. 检查是否被撤销
        if ($this->isRevoked($vc['id'] ?? '')) {
            $result['valid'] = false;
            $result['errors'][] = 'Credential has been revoked';
        }
        // 3. 验证签名
        if (!$this->verifyProof($vc)) {
            $result['valid'] = false;
            $result['errors'][] = 'Invalid proof';
        }
        // 4. 检查有效期
        if (isset($vc['expirationDate'])) {
            if (strtotime($vc['expirationDate']) < time()) {
                $result['valid'] = false;
                $result['errors'][] = 'Credential has expired';
            }
        }
        return $result;
    }
    // 撤销凭证
    public function revokeCredential(string $credentialId): bool {
        if (isset($this->credentials[$credentialId])) {
            $this->revokedList[] = $credentialId;
            $this->credentials[$credentialId]['status']['revoked'] = true;
            return true;
        }
        return false;
    }
    private function validateStructure(array $vc): bool {
        $required = ['@context', 'type', 'issuer', 'issuanceDate', 'credentialSubject'];
        foreach ($required as $field) {
            if (!isset($vc[$field])) {
                return false;
            }
        }
        return true;
    }
    private function generateProof(array $vc): array {
        // 简单的签名生成(实际生产环境使用更强的签名算法)
        $canonical = json_encode($vc, JSON_UNESCAPED_SLASHES);
        return [
            'type' => 'RsaSignature2018',
            'created' => date('c'),
            'verificationMethod' => 'did:example:issuer#keys-1',
            'proofPurpose' => 'assertionMethod',
            'jws' => base64_encode(hash('sha256', $canonical, true))
        ];
    }
    private function verifyProof(array $vc): bool {
        if (!isset($vc['proof'])) {
            return false;
        }
        $proof = $vc['proof'];
        $expectedHash = base64_encode(
            hash('sha256', json_encode($vc, JSON_UNESCAPED_SLASHES), true)
        );
        return $proof['jws'] === $expectedHash;
    }
    private function generateCredentialId(): string {
        return 'urn:uuid:' . bin2hex(random_bytes(16));
    }
    private function isRevoked(string $credentialId): bool {
        return in_array($credentialId, $this->revokedList);
    }
}
// 使用示例
$manager = new VCCredentialManager();
// 颁发凭证
$credential = $manager->issueCredential([
    'subjectId' => 'did:example:user123',
    'claims' => [
        'name' => '张三',
        'email' => 'zhangsan@example.com',
        'age' => 25
    ]
]);
echo "颁发的凭证:\n";
print_r($credential);
// 验证凭证
$result = $manager->verifyCredential($credential);
echo "\n验证结果:\n";
print_r($result);
// 撤销凭证
$manager->revokeCredential($credential['id']);
echo "\n撤销后验证:\n";
print_r($manager->verifyCredential($credential));

推荐的 PHP 库

库名 说明 安装
php-json-ld JSON-LD 处理 composer require ml/json-ld
firebase/php-jwt JWT 生成和验证 composer require firebase/php-jwt
web3signer DID 签名 composer require consensys/web3signer

最佳实践

  1. 安全存储私钥:使用硬件安全模块(HSM)或密钥管理服务
  2. DID 解析:实现 DID 文档解析来获取公钥
  3. 缓存机制:缓存验证结果提高性能
  4. 日志审计:记录所有凭证操作日志
  5. 版本管理:维护 VC 的版本兼容性

需要我帮你实现特定的功能或处理某个具体场景吗?

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