Sanctum:密码学可否认的保险库系统(IPFS 存储)

发布: (2026年1月9日 GMT+8 07:03)
8 分钟阅读
原文: Dev.to

Source: Dev.to

Sanctum 插图

🎭 问题:加密不足

传统的加密存储存在致命缺陷:

Attacker: "Give me the password or else."
You:      "I don't have one."
Attacker: *checks encrypted file* "This is clearly encrypted. Try again."

你无法证明数据的不存在——直到现在。

✨ 解决方案:加密否认

Sanctum 创建 三个不可区分的层

描述
Decoy Layer无害内容(家庭照片、一个装有 200 美元的小钱包)
Hidden Layer真正的机密(举报者文档、主要加密钱包)
Panic Layer在胁迫下显示 “保险箱已删除”

魔法是什么? 三者在密码学上完全相同。对手无法证明哪一层是真实的——甚至无法确定是否存在隐藏层。

🏗️ 架构:零信任设计

客户端加密流程

// 1. User creates vault with decoy + hidden content
const decoyBlob  = encrypt(decoyContent, '');               // Empty passphrase
const hiddenBlob = encrypt(hiddenContent, deriveKey(passphrase));

// 2. XOR both layers (makes them indistinguishable)
const combined = xor(decoyBlob, hiddenBlob);

// 3. Upload to IPFS
const decoyCID  = await ipfs.upload(decoyBlob);
const hiddenCID = await ipfs.upload(hiddenBlob);

// 4. Split‑key architecture
const keyA = randomBytes(32); // Stays in URL
const keyB = randomBytes(32); // Encrypted in database
const vaultURL = `https://sanctumvault.online/unlock/${vaultId}#${encode(keyA)}`;

技术栈

  • Frontend: Next.js 15 + React + Web Crypto API
  • Cryptography: XChaCha20‑Poly1305 + Argon2id(256 MB 内存,3 次迭代)
  • Storage: IPFS via Pinata / Filebase(免费层)
  • Database: Cloudflare D1(仅分键存储)
  • Hosting: Cloudflare Pages(静态站点)

安全特性

// RAM‑only storage (no disk persistence)
class SecureStorage {
  private keys = new Map();

  store(key: string, value: Uint8Array): void {
    this.keys.set(key, value);
    // Auto‑clear after 5 minutes
    setTimeout(() => this.wipe(key), 300_000);
  }

  wipe(key: string): void {
    const data = this.keys.get(key);
    if (data) {
      data.fill(0);               // Overwrite memory
      this.keys.delete(key);
    }
  }
}

// Panic key: Double‑press Escape
let escapeCount = 0;
document.addEventListener('keydown', (e) => {
  if (e.key === 'Escape') {
    escapeCount++;
    if (escapeCount === 2) {
      wipeAllKeys();
      window.location.href = '/';
    }
    setTimeout(() => (escapeCount = 0), 500);
  }
});

🎯 实际使用案例

  1. 记者保护信息来源

    Decoy:  Published articles, public research notes
    Hidden: Confidential source documents, whistleblower communications
    Scenario: Device seized at border → reveal decoy, sources stay protected
  2. 受压迫的加密资产持有者

    Decoy: Small wallet with $200 ("this is all I have")
    Hidden: Main wallet with life savings
    Scenario: $5 wrench attack → hand over decoy wallet, real funds stay safe
  3. 专制政权下的活动人士

    Decoy: Personal photos, innocuous social media content
    Hidden: Protest coordination plans, evidence of government abuse
    Scenario: Police raid → show decoy layer, cannot prove hidden content exists

🛡️ 攻击防御

Attack VectorDefense
Physical Duress揭示诱饵密码短语;隐藏层保持不可区分。
Disk ForensicsRAM‑only 存储;密钥从未写入磁盘;在标签关闭时自动擦除。
Timing Analysis对所有操作随机延迟 500‑2000 ms。
Blob Size Analysis填充至标准大小(1 KB、10 KB、100 KB、1 MB、10 MB、25 MB)。
Brute ForceArgon2id 使用 256 MB 内存,使暴力破解在计算上不可行。

🚀 快速开始

对于用户

访问 sanctumvault.online

  • 配置 Pinata 或 Filebase(免费 IPFS 提供商)
  • 创建一个带有可选诱饵内容的保险库
  • 为隐藏层设置密码短语
  • 分享链接——只有你知道密码短语

对于开发者

# Clone repository
git clone https://github.com/Teycir/Sanctum.git
cd Sanctum

# Install dependencies
npm install

# Run development server
npm run dev

🔬 技术深度解析

为什么选择 XChaCha20‑Poly1305?

// AES‑GCM: 96‑bit nonce (collision risk after 2^48 encryptions)
// XChaCha20: 192‑bit nonce (collision risk after 2^96 encryptions)

import { xchacha20poly1305 } from '@noble/ciphers/chacha';

export function encrypt(
  plaintext: Uint8Array,
  key: Uint8Array
): Uint8Array {
  const nonce = randomBytes(24); // 192‑bit nonce
  const cipher = xchacha20poly1305(key, nonce);
  return cipher.encrypt(plaintext);
}

XChaCha20‑Poly1305 提供了极其庞大的 nonce 空间,消除了 nonce 重用的顾虑,并在浏览器中提供了具有强大性能的认证加密。

// Encryption function
function encryptData(
  plaintext: Uint8Array,
  key: Uint8Array
): EncryptionResult {
  const nonce = randomBytes(24); // 192‑bit nonce
  const cipher = xchacha20poly1305(key, nonce);
  const ciphertext = cipher.encrypt(plaintext);

  return {
    ciphertext,
    nonce,
    // Authenticated encryption tag (last 16 bytes)
    authTag: ciphertext.slice(-16),
  };
}

分割密钥架构

// KeyA: Stays in URL fragment (never sent to server)
// KeyB: Encrypted in database with vault‑specific key

const vaultKey = deriveKey(vaultId + salt);
const encryptedKeyB = encrypt(keyB, vaultKey);

// To decrypt IPFS CIDs:
const masterKey = xor(keyA, keyB);
const decoyCID = decrypt(encryptedDecoyCID, masterKey);
const hiddenCID = decrypt(encryptedHiddenCID, masterKey);

30‑Day Grace Period

-- Stage 1: Soft delete (mark inactive)
UPDATE vaults
SET is_active = 0
WHERE expires_at < NOW();
  • ✅ 未收到任何:

    • 国家安全信函(NSLs)
    • FISA 法院命令
    • 禁言令
    • 实施后门的请求
  • ✅ 架构保证:

    • 零知识:无法解密用户保险库
    • 无用户日志:不记录 IP 地址或元数据
    • 无后门:所有代码均为开源
    • 仅使用 RAM:密钥不进行持久化存储

🌐 为什么选择 IPFS?

传统云存储存在单点故障:

IssueCloud StorageIPFS
CentralizedProvider can be compelled to hand over dataData replicated across many nodes
CensorableGovernments can block accessContent‑addressed (CID), not location‑based
DeletableProvider can delete your dataImmutable – once uploaded, cannot be modified
CostOngoing feesFree tiers: Pinata (1 GB) + Filebase (5 GB)

🚫 What Sanctum Is NOT

  • 密码管理器 – 使用 KeePassXC / Bitwarden
  • 备份解决方案 – IPFS 数据可能被取消固定
  • 文件共享服务 – 链接是永久的,无法删除
  • VPN – 使用 Tor 浏览器实现匿名

💡 经验教训

1. 仅 RAM 存储很困难

// ❌ WRONG: localStorage persists to disk
localStorage.setItem('key', encode(key));

// ✅ CORRECT: In‑memory only
const keyStore = new Map();

2. 时序攻击是真实存在的

// ❌ WRONG: Instant response reveals wrong passphrase
if (passphrase !== correctPassphrase) {
  return { error: 'Invalid passphrase' };
}

// ✅ CORRECT: Constant‑time comparison + random delay
const isValid = timingSafeEqual(hash(passphrase), hash(correctPassphrase));
await sleep(randomInt(500, 2000));
return isValid ? { data } : { error: 'Invalid passphrase' };

3. 浏览器历史是泄漏源

// Vault URLs contain KeyA in fragment.
// Must clear from browser history.
if (window.history.replaceState) {
  window.history.replaceState(null, '', '/unlock');
}

🔮 未来路线图

  • Shamir Secret Sharing – 将金库访问权限拆分给多个人
  • Dead Man’s Switch – 在长时间不活动后自动释放
  • Steganography – 将金库隐藏在看似无害的图像中
  • Hardware Key Support – 支持 YubiKey / Ledger 集成
  • Mobile Apps – iOS / Android 支持生物识别解锁的移动应用

🙏 致谢

  • VeraCrypt – 可实现合理否认的灵感
  • Cloudflare Pages – 免费静态站点托管
  • Pinata / Filebase – 免费 IPFS 固定服务
  • @noble/ciphers – 已审计的密码学库

📜 许可证

Business Source License 1.1 – 免费用于非生产使用。生产使用在 4 年后需要商业许可证。

🔗 链接

  • 现场演示:
  • GitHub:
  • 视频演示:
  • 联系:

💬 讨论

你怎么看?你会为敏感数据使用加密否认性吗?你还能想象哪些其他用例?

在下方留下评论或在 GitHub 上打开 issue!

Teycir Ben Soltane 用 ❤️ 和 🔒 构建

免责声明:Sanctum 是满足合法隐私需求的工具。用户需自行遵守当地法律。开发者不支持任何非法活动。

Back to Blog

相关文章

阅读更多 »

你好,我是新人。

嗨!我又回到 STEM 的领域了。我也喜欢学习能源系统、科学、技术、工程和数学。其中一个项目是…