区块链集成
SirrChat 的区块链集成实现了使用 EVM 钱包签名的无密码认证。这种创新方法消除了传统密码漏洞,同时提供了加密安全的访问控制。
概述
区块链认证模块(auth.pass_blockchain)允许用户使用他们的以太坊(或 EVM 兼容)钱包签名进行认证,而不是传统密码。
工作原理
- 用户注册: 用户的钱包地址与邮件账户注册
- 认证请求: 客户端使用私钥签名挑战消息
- 签名验证: 服务器从签名中恢复公钥
- 授予访问: 如果恢复的地址匹配注册地址,则授予访问权限
配置
基本设置
在 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 | 生产 |
| 以太坊 Goerli | 5 | 测试网 |
| 以太坊 Sepolia | 11155111 | 测试网 |
| BSC 主网 | 56 | 生产 |
| BSC 测试网 | 97 | 测试网 |
| Polygon 主网 | 137 | 生产 |
| Polygon Mumbai | 80001 | 测试网 |
| Arbitrum One | 42161 | 生产 |
| Optimism | 10 | 生产 |
认证流程
1. 挑战生成
当用户尝试认证时,服务器生成一个挑战消息:
Challenge: <random_nonce>
Timestamp: <unix_timestamp>
Service: sirrchat2. 客户端签名
客户端使用以太坊钱包签名挑战:
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 服务器
// ... 使用凭证进行认证
}
}安全考虑
最佳实践
- 永远不要共享私钥: 私钥绝不应传输或存储在服务器上
- 使用硬件钱包: 对于生产使用,考虑硬件钱包集成
- 实施 Nonce 过期: 挑战 nonce 应在短时间后过期
- 速率限制: 对认证尝试实施速率限制
- 审计日志: 记录所有认证尝试以进行安全监控
重放攻击防护
服务器包含反重放保护:
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 ð_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)
}资源
区块链认证通过加密验证消除密码,同时增强安全性。