3740 字
19 分钟
密码学

密码学#

概述#

密码学是Web3和区块链技术的基础,为数字资产的安全存储、传输和验证提供了强大的技术保障。本章节详细介绍了密码学在Web3中的应用,包括哈希函数、数字签名、加密算法、零知识证明等核心概念,以及它们在区块链系统中的实际应用。

1. 密码学基础#

1.1 基本概念#

1.1.1 密码学目标#

  • 机密性(Confidentiality):保护信息不被未授权访问
  • 完整性(Integrity):确保信息不被篡改
  • 认证性(Authentication):验证身份的真实性
  • 不可否认性(Non-repudiation):防止否认已执行的操作

1.1.2 密码学分类#

  • 对称密码学:加密和解密使用相同密钥
  • 非对称密码学:加密和解密使用不同密钥
  • 哈希函数:单向函数,用于数据完整性验证
  • 数字签名:用于身份验证和数据完整性

1.2 数学基础#

1.2.1 有限域#

// 1. 有限域运算
class PrimeField {
constructor(prime) {
this.prime = BigInt(prime);
}
// 加法
add(a, b) {
return (BigInt(a) + BigInt(b)) % this.prime;
}
// 乘法
multiply(a, b) {
return (BigInt(a) * BigInt(b)) % this.prime;
}
// 幂运算
power(a, b) {
return this.modPow(BigInt(a), BigInt(b));
}
// 模幂运算
modPow(base, exponent) {
let result = 1n;
base = base % this.prime;
while (exponent > 0n) {
if (exponent % 2n === 1n) {
result = (result * base) % this.prime;
}
exponent = exponent >> 1n;
base = (base * base) % this.prime;
}
return result;
}
}
// 2. 使用示例
const field = new PrimeField(21888242871839275222246405745257275088548364400416034343698204186575808495617n);
const result = field.add(5, 3); // 8

1.2.2 椭圆曲线#

// 1. 椭圆曲线定义
class EllipticCurve {
constructor(field, a, b) {
this.field = field;
this.a = a;
this.b = b;
}
// 点加法
pointAdd(p1, p2) {
if (p1.isInfinity()) return p2;
if (p2.isInfinity()) return p1;
if (p1.x === p2.x) {
if (p1.y === p2.y) {
return this.pointDouble(p1);
} else {
return Point.infinity();
}
}
const slope = this.field.multiply(
this.field.add(p2.y, -p1.y),
this.field.inverse(this.field.add(p2.x, -p1.x))
);
const x3 = this.field.add(
this.field.multiply(slope, slope),
-p1.x - p2.x
);
const y3 = this.field.add(
this.field.multiply(slope, this.field.add(p1.x, -x3)),
-p1.y
);
return new Point(x3, y3);
}
// 点倍乘
pointDouble(p) {
if (p.isInfinity()) return p;
const slope = this.field.multiply(
this.field.add(
this.field.multiply(3n, this.field.multiply(p.x, p.x)),
this.a
),
this.field.inverse(this.field.multiply(2n, p.y))
);
const x3 = this.field.add(
this.field.multiply(slope, slope),
-this.field.multiply(2n, p.x)
);
const y3 = this.field.add(
this.field.multiply(slope, this.field.add(p.x, -x3)),
-p.y
);
return new Point(x3, y3);
}
}
// 2. 点类定义
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
isInfinity() {
return this.x === 0n && this.y === 0n;
}
static infinity() {
return new Point(0n, 0n);
}
}

2. 哈希函数#

2.1 基本概念#

2.1.1 哈希函数性质#

  • 确定性:相同输入总是产生相同输出
  • 单向性:从输出难以推导出输入
  • 雪崩效应:输入微小变化导致输出巨大变化
  • 抗碰撞性:难以找到两个不同的输入产生相同输出

2.1.2 常见哈希函数#

  • SHA-256:比特币使用,输出256位
  • Keccak-256:以太坊使用,输出256位
  • Blake2b:性能优秀,输出可变长度
  • MD5:已不推荐用于安全应用

2.2 技术实现#

2.2.1 SHA-256实现#

const crypto = require('crypto');
// 1. 基本哈希
function sha256(data) {
const hash = crypto.createHash('sha256');
hash.update(data);
return hash.digest('hex');
}
// 2. 多次哈希
function doubleSha256(data) {
return sha256(sha256(data));
}
// 3. 哈希链
function hashChain(data, iterations) {
let result = data;
for (let i = 0; i < iterations; i++) {
result = sha256(result);
}
return result;
}
// 4. 使用示例
const message = "Hello, World!";
const hash = sha256(message);
console.log("SHA-256:", hash);

2.2.2 在区块链中的应用#

// 1. 区块哈希
function calculateBlockHash(block) {
const data = JSON.stringify({
index: block.index,
timestamp: block.timestamp,
previousHash: block.previousHash,
data: block.data,
nonce: block.nonce
});
return sha256(data);
}
// 2. Merkle树根
function calculateMerkleRoot(transactions) {
if (transactions.length === 0) return null;
if (transactions.length === 1) return transactions[0];
const nextLevel = [];
for (let i = 0; i < transactions.length; i += 2) {
const left = transactions[i];
const right = transactions[i + 1] || transactions[i];
nextLevel.push(sha256(left + right));
}
return calculateMerkleRoot(nextLevel);
}
// 3. 地址生成
function generateAddress(publicKey) {
const hash = sha256(publicKey);
return '0x' + hash.slice(-40);
}

3. 数字签名#

3.1 基本概念#

3.1.1 数字签名原理#

  • 私钥签名:使用私钥对消息进行签名
  • 公钥验证:使用公钥验证签名
  • 不可伪造:只有私钥持有者才能生成有效签名
  • 不可否认:签名者无法否认已签名的消息

3.1.2 常见签名算法#

  • ECDSA:椭圆曲线数字签名算法
  • EdDSA:Edwards曲线数字签名算法
  • Schnorr:Schnorr签名算法
  • RSA:RSA数字签名算法

3.2 ECDSA实现#

3.2.1 密钥生成#

const secp256k1 = require('secp256k1');
const crypto = require('crypto');
// 1. 生成私钥
function generatePrivateKey() {
let privateKey;
do {
privateKey = crypto.randomBytes(32);
} while (!secp256k1.privateKeyVerify(privateKey));
return privateKey;
}
// 2. 从私钥生成公钥
function generatePublicKey(privateKey) {
return secp256k1.publicKeyCreate(privateKey);
}
// 3. 生成密钥对
function generateKeyPair() {
const privateKey = generatePrivateKey();
const publicKey = generatePublicKey(privateKey);
return { privateKey, publicKey };
}

3.2.2 签名和验证#

// 1. 签名消息
function signMessage(message, privateKey) {
const messageHash = crypto.createHash('sha256').update(message).digest();
const signature = secp256k1.ecdsaSign(messageHash, privateKey);
return signature.signature;
}
// 2. 验证签名
function verifySignature(message, signature, publicKey) {
const messageHash = crypto.createHash('sha256').update(message).digest();
return secp256k1.ecdsaVerify(signature, messageHash, publicKey);
}
// 3. 使用示例
const { privateKey, publicKey } = generateKeyPair();
const message = "Hello, World!";
const signature = signMessage(message, privateKey);
const isValid = verifySignature(message, signature, publicKey);
console.log("Signature valid:", isValid);

3.3 在区块链中的应用#

3.3.1 交易签名#

// 1. 交易结构
class Transaction {
constructor(from, to, amount, nonce) {
this.from = from;
this.to = to;
this.amount = amount;
this.nonce = nonce;
}
// 2. 计算交易哈希
hash() {
const data = JSON.stringify({
from: this.from,
to: this.to,
amount: this.amount,
nonce: this.nonce
});
return crypto.createHash('sha256').update(data).digest();
}
// 3. 签名交易
sign(privateKey) {
const hash = this.hash();
const signature = secp256k1.ecdsaSign(hash, privateKey);
this.signature = signature.signature;
return this;
}
// 4. 验证交易
verify() {
if (!this.signature) return false;
const hash = this.hash();
return secp256k1.ecdsaVerify(this.signature, hash, this.from);
}
}

3.3.2 多重签名#

// 1. 多重签名钱包
class MultiSigWallet {
constructor(publicKeys, threshold) {
this.publicKeys = publicKeys;
this.threshold = threshold;
this.signatures = new Map();
}
// 2. 添加签名
addSignature(signer, signature) {
if (!this.publicKeys.includes(signer)) {
throw new Error('Invalid signer');
}
this.signatures.set(signer, signature);
}
// 3. 验证签名
verify(message) {
const validSignatures = [];
for (const [signer, signature] of this.signatures) {
if (secp256k1.ecdsaVerify(signature, message, signer)) {
validSignatures.push(signer);
}
}
return validSignatures.length >= this.threshold;
}
}

4. 加密算法#

4.1 对称加密#

4.1.1 AES加密#

const crypto = require('crypto');
// 1. AES加密
function aesEncrypt(data, key) {
const cipher = crypto.createCipher('aes-256-cbc', key);
let encrypted = cipher.update(data, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
// 2. AES解密
function aesDecrypt(encryptedData, key) {
const decipher = crypto.createDecipher('aes-256-cbc', key);
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// 3. 使用示例
const data = "Sensitive data";
const key = "my-secret-key";
const encrypted = aesEncrypt(data, key);
const decrypted = aesDecrypt(encrypted, key);
console.log("Original:", data);
console.log("Decrypted:", decrypted);

4.1.2 在钱包中的应用#

// 1. 私钥加密存储
class SecureKeyStore {
constructor(password) {
this.password = password;
this.encryptedKeys = new Map();
}
// 2. 加密私钥
encryptPrivateKey(privateKey) {
const key = crypto.scryptSync(this.password, 'salt', 32);
const cipher = crypto.createCipher('aes-256-cbc', key);
let encrypted = cipher.update(privateKey, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
// 3. 解密私钥
decryptPrivateKey(encryptedKey) {
const key = crypto.scryptSync(this.password, 'salt', 32);
const decipher = crypto.createDecipher('aes-256-cbc', key);
let decrypted = decipher.update(encryptedKey, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}

4.2 非对称加密#

4.2.1 RSA加密#

const crypto = require('crypto');
// 1. 生成RSA密钥对
function generateRSAKeyPair() {
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});
return { publicKey, privateKey };
}
// 2. RSA加密
function rsaEncrypt(data, publicKey) {
const encrypted = crypto.publicEncrypt(publicKey, Buffer.from(data));
return encrypted.toString('hex');
}
// 3. RSA解密
function rsaDecrypt(encryptedData, privateKey) {
const decrypted = crypto.privateDecrypt(privateKey, Buffer.from(encryptedData, 'hex'));
return decrypted.toString('utf8');
}

5. 零知识证明#

5.1 基本概念#

5.1.1 零知识证明性质#

  • 完整性:如果陈述为真,诚实的证明者能够说服诚实的验证者
  • 可靠性:如果陈述为假,任何证明者都无法说服诚实的验证者
  • 零知识性:验证者除了陈述为真之外,无法获得任何额外信息

5.1.2 应用场景#

  • 隐私保护:保护交易隐私和身份隐私
  • 扩容技术:ZK Rollup等扩容方案
  • 身份验证:匿名身份验证
  • 数据完整性:证明数据未被篡改

5.2 技术实现#

5.2.1 简单零知识证明#

// 1. 简单零知识证明示例
class SimpleZKProof {
constructor() {
this.secret = Math.floor(Math.random() * 1000);
this.publicValue = this.secret * this.secret;
}
// 2. 生成证明
generateProof() {
const r = Math.floor(Math.random() * 1000);
const commitment = r * r;
const challenge = Math.floor(Math.random() * 2);
let response;
if (challenge === 0) {
response = r;
} else {
response = r + this.secret;
}
return { commitment, challenge, response };
}
// 3. 验证证明
verifyProof(proof) {
const { commitment, challenge, response } = proof;
if (challenge === 0) {
return response * response === commitment;
} else {
return (response * response - this.publicValue) === commitment;
}
}
}

5.2.2 在区块链中的应用#

// 1. 隐私交易证明
class PrivacyTransactionProof {
constructor() {
this.circuit = new SimpleZKProof();
}
// 2. 生成交易证明
generateTransactionProof(transaction) {
const proof = this.circuit.generateProof();
return {
transaction,
proof,
publicSignals: [transaction.amount, transaction.to]
};
}
// 3. 验证交易证明
verifyTransactionProof(proofData) {
const { proof, publicSignals } = proofData;
return this.circuit.verifyProof(proof);
}
}

6. 密码学协议#

6.1 密钥交换#

6.1.1 Diffie-Hellman密钥交换#

// 1. Diffie-Hellman密钥交换
class DiffieHellman {
constructor(prime, generator) {
this.prime = BigInt(prime);
this.generator = BigInt(generator);
}
// 2. 生成私钥
generatePrivateKey() {
return BigInt(Math.floor(Math.random() * Number(this.prime)));
}
// 3. 生成公钥
generatePublicKey(privateKey) {
return this.modPow(this.generator, privateKey);
}
// 4. 计算共享密钥
computeSharedSecret(privateKey, otherPublicKey) {
return this.modPow(BigInt(otherPublicKey), privateKey);
}
// 5. 模幂运算
modPow(base, exponent) {
let result = 1n;
base = base % this.prime;
while (exponent > 0n) {
if (exponent % 2n === 1n) {
result = (result * base) % this.prime;
}
exponent = exponent >> 1n;
base = (base * base) % this.prime;
}
return result;
}
}

6.1.2 在区块链中的应用#

// 1. 安全通信
class SecureCommunication {
constructor() {
this.dh = new DiffieHellman(23, 5); // 使用小素数示例
this.privateKey = this.dh.generatePrivateKey();
this.publicKey = this.dh.generatePublicKey(this.privateKey);
}
// 2. 建立安全通道
establishSecureChannel(otherPublicKey) {
const sharedSecret = this.dh.computeSharedSecret(this.privateKey, otherPublicKey);
return sharedSecret;
}
// 3. 加密消息
encryptMessage(message, sharedSecret) {
const key = sharedSecret.toString();
return aesEncrypt(message, key);
}
// 4. 解密消息
decryptMessage(encryptedMessage, sharedSecret) {
const key = sharedSecret.toString();
return aesDecrypt(encryptedMessage, key);
}
}

6.2 数字证书#

6.2.1 证书生成#

// 1. 数字证书
class DigitalCertificate {
constructor(subject, issuer, publicKey, validityPeriod) {
this.subject = subject;
this.issuer = issuer;
this.publicKey = publicKey;
this.validityPeriod = validityPeriod;
this.issuedAt = new Date();
this.expiresAt = new Date(this.issuedAt.getTime() + validityPeriod);
}
// 2. 签名证书
sign(privateKey) {
const data = JSON.stringify({
subject: this.subject,
issuer: this.issuer,
publicKey: this.publicKey,
issuedAt: this.issuedAt,
expiresAt: this.expiresAt
});
this.signature = signMessage(data, privateKey);
return this;
}
// 3. 验证证书
verify(issuerPublicKey) {
if (new Date() > this.expiresAt) {
return false;
}
const data = JSON.stringify({
subject: this.subject,
issuer: this.issuer,
publicKey: this.publicKey,
issuedAt: this.issuedAt,
expiresAt: this.expiresAt
});
return verifySignature(data, this.signature, issuerPublicKey);
}
}

7. 安全考虑#

7.1 常见攻击#

7.1.1 侧信道攻击#

// 1. 防侧信道攻击
class SideChannelResistant {
constructor() {
this.constantTime = true;
}
// 2. 常数时间比较
constantTimeCompare(a, b) {
if (a.length !== b.length) {
return false;
}
let result = 0;
for (let i = 0; i < a.length; i++) {
result |= a[i] ^ b[i];
}
return result === 0;
}
// 3. 常数时间选择
constantTimeSelect(condition, a, b) {
const mask = condition ? 0xFFFFFFFF : 0x00000000;
return (a & mask) | (b & ~mask);
}
}

7.1.2 时序攻击#

// 1. 防时序攻击
class TimingAttackResistant {
constructor() {
this.minExecutionTime = 100; // 最小执行时间(毫秒)
}
// 2. 固定时间执行
async fixedTimeExecution(operation) {
const startTime = Date.now();
const result = await operation();
const executionTime = Date.now() - startTime;
if (executionTime < this.minExecutionTime) {
await this.delay(this.minExecutionTime - executionTime);
}
return result;
}
// 3. 延迟函数
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}

7.2 安全最佳实践#

7.2.1 密钥管理#

// 1. 安全密钥管理
class SecureKeyManagement {
constructor() {
this.keys = new Map();
this.encryptionKey = this.generateEncryptionKey();
}
// 2. 生成加密密钥
generateEncryptionKey() {
return crypto.randomBytes(32);
}
// 3. 存储密钥
storeKey(keyId, privateKey) {
const encrypted = this.encryptPrivateKey(privateKey);
this.keys.set(keyId, encrypted);
}
// 4. 检索密钥
retrieveKey(keyId) {
const encrypted = this.keys.get(keyId);
if (!encrypted) {
throw new Error('Key not found');
}
return this.decryptPrivateKey(encrypted);
}
// 5. 加密私钥
encryptPrivateKey(privateKey) {
const cipher = crypto.createCipher('aes-256-cbc', this.encryptionKey);
let encrypted = cipher.update(privateKey, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
// 6. 解密私钥
decryptPrivateKey(encryptedKey) {
const decipher = crypto.createDecipher('aes-256-cbc', this.encryptionKey);
let decrypted = decipher.update(encryptedKey, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}

7.2.2 随机数生成#

// 1. 安全随机数生成
class SecureRandomGenerator {
constructor() {
this.entropyPool = [];
this.minEntropy = 256; // 最小熵值
}
// 2. 添加熵
addEntropy(data) {
this.entropyPool.push(data);
}
// 3. 生成随机数
generateRandom(length) {
if (this.entropyPool.length < this.minEntropy) {
throw new Error('Insufficient entropy');
}
const random = crypto.randomBytes(length);
this.entropyPool = []; // 清空熵池
return random;
}
// 4. 生成随机整数
generateRandomInt(min, max) {
const random = this.generateRandom(4);
const value = random.readUInt32BE(0);
return min + (value % (max - min + 1));
}
}

8. 性能优化#

8.1 算法优化#

8.1.1 快速幂运算#

// 1. 快速幂运算
function fastModPow(base, exponent, modulus) {
let result = 1n;
base = base % modulus;
while (exponent > 0n) {
if (exponent % 2n === 1n) {
result = (result * base) % modulus;
}
exponent = exponent >> 1n;
base = (base * base) % modulus;
}
return result;
}
// 2. 预计算表
class PrecomputedTable {
constructor(base, modulus, maxExponent) {
this.base = base;
this.modulus = modulus;
this.table = new Map();
this.precompute(maxExponent);
}
precompute(maxExponent) {
for (let i = 0; i <= maxExponent; i++) {
this.table.set(i, fastModPow(this.base, BigInt(i), this.modulus));
}
}
lookup(exponent) {
return this.table.get(Number(exponent));
}
}

8.1.2 批量操作#

// 1. 批量签名
class BatchSigner {
constructor() {
this.pendingSignatures = [];
}
// 2. 添加签名任务
addSignature(message, privateKey) {
this.pendingSignatures.push({ message, privateKey });
}
// 3. 批量签名
async batchSign() {
const signatures = await Promise.all(
this.pendingSignatures.map(({ message, privateKey }) =>
signMessage(message, privateKey)
)
);
this.pendingSignatures = [];
return signatures;
}
}

8.2 内存优化#

8.2.1 对象池#

// 1. 对象池
class ObjectPool {
constructor(createFn, resetFn, maxSize = 100) {
this.createFn = createFn;
this.resetFn = resetFn;
this.maxSize = maxSize;
this.pool = [];
}
// 2. 获取对象
acquire() {
if (this.pool.length > 0) {
return this.pool.pop();
}
return this.createFn();
}
// 3. 释放对象
release(obj) {
if (this.pool.length < this.maxSize) {
this.resetFn(obj);
this.pool.push(obj);
}
}
}
// 4. 使用示例
const keyPool = new ObjectPool(
() => new Array(32), // 创建函数
(arr) => arr.fill(0), // 重置函数
50 // 最大池大小
);

9. 测试#

9.1 单元测试#

9.1.1 密码学函数测试#

describe('Cryptography', () => {
describe('Hash Functions', () => {
it('should generate consistent hashes', () => {
const data = 'test data';
const hash1 = sha256(data);
const hash2 = sha256(data);
expect(hash1).toBe(hash2);
});
it('should generate different hashes for different data', () => {
const hash1 = sha256('data1');
const hash2 = sha256('data2');
expect(hash1).not.toBe(hash2);
});
});
describe('Digital Signatures', () => {
it('should sign and verify messages', () => {
const { privateKey, publicKey } = generateKeyPair();
const message = 'test message';
const signature = signMessage(message, privateKey);
const isValid = verifySignature(message, signature, publicKey);
expect(isValid).toBe(true);
});
it('should reject invalid signatures', () => {
const { privateKey, publicKey } = generateKeyPair();
const message = 'test message';
const signature = signMessage(message, privateKey);
const isValid = verifySignature('different message', signature, publicKey);
expect(isValid).toBe(false);
});
});
});

9.1.2 安全测试#

describe('Security', () => {
it('should prevent timing attacks', async () => {
const timingResistant = new TimingAttackResistant();
const startTime = Date.now();
await timingResistant.fixedTimeExecution(() => {
// 快速操作
return 'result';
});
const executionTime = Date.now() - startTime;
expect(executionTime).toBeGreaterThanOrEqual(100);
});
it('should generate secure random numbers', () => {
const generator = new SecureRandomGenerator();
generator.addEntropy('entropy1');
generator.addEntropy('entropy2');
const random1 = generator.generateRandom(32);
const random2 = generator.generateRandom(32);
expect(random1).not.toEqual(random2);
expect(random1.length).toBe(32);
});
});

9.2 集成测试#

9.2.1 端到端测试#

describe('End-to-End', () => {
it('should complete full transaction flow', async () => {
// 1. 生成密钥对
const { privateKey, publicKey } = generateKeyPair();
// 2. 创建交易
const transaction = new Transaction(
publicKey,
'0x...',
1000,
0
);
// 3. 签名交易
transaction.sign(privateKey);
// 4. 验证交易
const isValid = transaction.verify();
expect(isValid).toBe(true);
});
});

10. 学习建议#

10.1 理论学习#

  1. 数学基础:掌握有限域、椭圆曲线等数学知识
  2. 密码学理论:学习密码学的基本原理和算法
  3. 安全知识:了解密码学安全相关知识
  4. 区块链应用:学习密码学在区块链中的应用

10.2 实践练习#

  1. 简单实现:从基础算法开始实现
  2. 复杂应用:构建完整的密码学应用
  3. 性能优化:学习性能优化技巧
  4. 安全审计:学习安全审计方法

10.3 源码阅读#

  1. 开源项目:阅读密码学库的源码
  2. 标准实现:学习密码学标准实现
  3. 工具源码:了解开发工具实现

11. 总结#

密码学是Web3和区块链技术的基础,为数字资产的安全存储、传输和验证提供了强大的技术保障。通过深入理解密码学的原理和实现,我们可以构建更安全、更可靠的Web3应用。

在实际开发中,需要注意:

  1. 安全性:重视密码学安全,防止常见攻击
  2. 性能优化:优化密码学算法的性能
  3. 标准遵循:遵循密码学标准和最佳实践
  4. 测试覆盖:编写全面的测试用例
  5. 持续学习:关注密码学技术的最新发展

随着Web3技术的发展,密码学技术也在不断演进,新的算法和方案不断涌现。通过持续学习和实践,我们可以更好地掌握密码学技术,构建更优秀的Web3应用。


本文档基于playground-web3仓库中的密码学模块整理,结合Web3技术特点进行了扩展和补充。

密码学
https://website-truelovings-projects.vercel.app/posts/web3/12-密码学/
作者
欢迎来到StarSky的网站!
发布于
2025-09-05
许可协议
CC BY-NC-SA 4.0