Skip to content

区块链集成

SirrChat 的区块链集成实现了使用 EVM 钱包签名的无密码认证。这种创新方法消除了传统密码漏洞,同时提供了加密安全的访问控制。

概述

区块链认证模块(auth.pass_blockchain)允许用户使用他们的以太坊(或 EVM 兼容)钱包签名进行认证,而不是传统密码。

工作原理

  1. 用户注册: 用户的钱包地址与邮件账户注册
  2. 认证请求: 客户端使用私钥签名挑战消息
  3. 签名验证: 服务器从签名中恢复公钥
  4. 授予访问: 如果恢复的地址匹配注册地址,则授予访问权限

配置

基本设置

sirrchatd.conf 中添加区块链认证:

conf
# 区块链配置
blockchain sirrchatd {
    rpc_endpoint https://mainnet.infura.io/v3/YOUR_PROJECT_ID
    chain_id 1  # 以太坊主网
}

# 认证模块
auth.pass_blockchain blockchain_auth {
    blockchain &sirrchatd
    storage &local_mailboxes
}

# 在 IMAP 端点中使用
imap tls://0.0.0.0:993 {
    auth &blockchain_auth
    storage &local_mailboxes
}

支持的链

SirrChat 支持任何 EVM 兼容的区块链:

Chain ID网络
以太坊主网1生产
以太坊 Goerli5测试网
以太坊 Sepolia11155111测试网
BSC 主网56生产
BSC 测试网97测试网
Polygon 主网137生产
Polygon Mumbai80001测试网
Arbitrum One42161生产
Optimism10生产

认证流程

1. 挑战生成

当用户尝试认证时,服务器生成一个挑战消息:

Challenge: <random_nonce>
Timestamp: <unix_timestamp>
Service: sirrchat

2. 客户端签名

客户端使用以太坊钱包签名挑战:

javascript
// 使用 ethers.js 的示例
const message = `Challenge: ${nonce}\nTimestamp: ${timestamp}\nService: sirrchat`;
const signature = await wallet.signMessage(message);

3. 服务器端验证

服务器验证签名并恢复地址:

go
// 内部验证过程
func (bc *Ethereum) CheckSign(ctx context.Context, pk, sign, message string) (bool, error) {
    hash := crypto.Keccak256Hash([]byte(message))
    signature := hexutil.MustDecode(sign)

    // 从签名恢复公钥
    pubKey, err := crypto.SigToPub(hash.Bytes(), signature)
    if err != nil {
        return false, err
    }

    // 从公钥获取地址
    recoveredAddr := crypto.PubkeyToAddress(*pubKey)

    // 与注册地址比较
    return recoveredAddr.Hex() == pk, nil
}

用户管理

注册区块链用户

bash
# 使用钱包地址注册邮件账户
sirrchatd creds create-blockchain \
    --email [email protected] \
    --address 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb

# 列出区块链用户
sirrchatd creds list-blockchain

更新钱包地址

bash
# 更新现有账户的钱包地址
sirrchatd creds update-blockchain \
    --email [email protected] \
    --address 0xNewAddress

移除区块链认证

bash
# 移除区块链认证(保留邮件账户)
sirrchatd creds remove-blockchain --email [email protected]

客户端实现

邮件客户端配置

配置您的邮件客户端使用区块链认证:

IMAP 设置:

  • 服务器: your-domain.com
  • 端口: 993
  • 安全性: SSL/TLS
  • 用户名: [email protected]
  • 密码: <signature>(钱包签名)

自定义客户端示例

以下是在自定义客户端中实现区块链认证的简单示例:

javascript
const ethers = require('ethers');

class BlockchainEmailAuth {
    constructor(walletAddress, privateKey) {
        this.wallet = new ethers.Wallet(privateKey);
        this.address = walletAddress;
    }

    async generateAuthCredentials(challenge, timestamp) {
        const message = `Challenge: ${challenge}\nTimestamp: ${timestamp}\nService: sirrchat`;
        const signature = await this.wallet.signMessage(message);

        return {
            username: `[email protected]`,
            password: signature,
            address: this.address
        };
    }

    async connectIMAP(host, port) {
        // 从服务器获取挑战
        const { challenge, timestamp } = await this.getChallengeFromServer();

        // 生成凭证
        const creds = await this.generateAuthCredentials(challenge, timestamp);

        // 连接到 IMAP 服务器
        // ... 使用凭证进行认证
    }
}

安全考虑

最佳实践

  1. 永远不要共享私钥: 私钥绝不应传输或存储在服务器上
  2. 使用硬件钱包: 对于生产使用,考虑硬件钱包集成
  3. 实施 Nonce 过期: 挑战 nonce 应在短时间后过期
  4. 速率限制: 对认证尝试实施速率限制
  5. 审计日志: 记录所有认证尝试以进行安全监控

重放攻击防护

服务器包含反重放保护:

conf
auth.pass_blockchain blockchain_auth {
    blockchain &sirrchatd
    storage &local_mailboxes

    # 挑战配置
    challenge_expiry 300s  # 5 分钟
    nonce_cache_size 10000
}

相比传统认证的优势

安全优势

  • 无密码存储: 消除密码数据库泄露
  • 加密验证: 基于经过验证的椭圆曲线加密
  • 无密码重用: 每个签名都是唯一的
  • 抗钓鱼: 无法被骗取凭证

用户体验

  • 无密码管理: 用户不需要记住密码
  • 多设备: 同一钱包可在所有设备上使用
  • 恢复选项: 使用钱包恢复机制而不是密码重置

与 Web3 应用集成

DApp 集成

将邮件功能集成到您的 DApp 中:

javascript
// 示例:从 DApp 发送邮件
async function sendEmailFromDApp(web3Provider) {
    const signer = web3Provider.getSigner();
    const address = await signer.getAddress();

    // 获取挑战
    const challenge = await fetchChallenge();

    // 签名挑战
    const signature = await signer.signMessage(challenge.message);

    // 认证并发送邮件
    await sendEmail({
        from: `${address}@yourdomain.com`,
        signature: signature,
        to: '[email protected]',
        subject: '来自 DApp 的问候',
        body: '这封邮件使用区块链认证发送!'
    });
}

故障排查

常见问题

签名验证失败

bash
# 检查地址是否已注册
sirrchatd creds list-blockchain | grep [email protected]

# 验证挑战格式
# 确保客户端和服务器使用相同的消息格式

RPC 连接问题

bash
# 测试 RPC 端点
curl -X POST https://mainnet.infura.io/v3/YOUR_PROJECT_ID \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'

高级配置

多链支持

conf
# 支持多条链
blockchain eth_mainnet {
    rpc_endpoint https://mainnet.infura.io/v3/YOUR_PROJECT_ID
    chain_id 1
}

blockchain bsc_mainnet {
    rpc_endpoint https://bsc-dataseed1.binance.org
    chain_id 56
}

auth.pass_blockchain multi_chain_auth {
    blockchain &eth_mainnet &bsc_mainnet
    storage &local_mailboxes
}

自定义验证逻辑

扩展区块链模块以实现自定义验证:

go
// 自定义验证实现
type CustomBlockchainAuth struct {
    baseAuth *blockchain.Ethereum
}

func (c *CustomBlockchainAuth) VerifyWithNFT(ctx context.Context, address, signature string) (bool, error) {
    // 验证签名
    valid, err := c.baseAuth.CheckSign(ctx, address, signature, message)
    if err != nil || !valid {
        return false, err
    }

    // 额外的 NFT 所有权检查
    hasNFT, err := c.checkNFTOwnership(ctx, address)
    return hasNFT, err
}

API 参考

核心接口

go
type BlockChain interface {
    // 向区块链发送原始交易
    SendRawTx(ctx context.Context, rawTx string) error

    // 获取区块链类型
    ChainType(ctx context.Context) string

    // 验证签名并检查是否匹配公钥
    CheckSign(ctx context.Context, pk, sign, message string) (bool, error)
}

资源


区块链认证通过加密验证消除密码,同时增强安全性。

Released under the GPL 3.0 License.