本文目录导读:

我来帮你梳理 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 |
最佳实践
- 安全存储私钥:使用硬件安全模块(HSM)或密钥管理服务
- DID 解析:实现 DID 文档解析来获取公钥
- 缓存机制:缓存验证结果提高性能
- 日志审计:记录所有凭证操作日志
- 版本管理:维护 VC 的版本兼容性
需要我帮你实现特定的功能或处理某个具体场景吗?