# 漫谈加密隐私

By [kutugu](https://paragraph.com/@kutugu) · 2022-03-13

---

概述
--

**加密**，即将明文信息改变为难以理解的密文内容，使之不可读。只有拥有解密方法的对象，才能将密文还原为明文。

从古至今，密码学已有数千年的历史。从早期的古典密码，到近现代密码，再到未来的量子密码。加密手段也由早期简单的代替和置换，进化到现代数学方法，再到未来的量子性质。

本篇文章无意讲述整个密码学的发展史，而是聚焦于现代计算机应用中所涉及的加密方法和原理，漫谈 **Web2** 和 **区块链** 涉猎的加密内容。

个人能力所限，如有缺漏错误之处，望指正。

推荐阅读：

[https://en.wikipedia.org/wiki/The\_Code\_Book](https://en.wikipedia.org/wiki/The_Code_Book)

现代密码学
-----

### 原理

近现代以来，随着数学方法和的计算机科学蓬勃发展，为加密技术提供了新的概念和工具。一个重要的标志是香农的[《保密系统通信理论》](https://en.wikipedia.org/wiki/Communication_Theory_of_Secrecy_Systems)，将传统密码学推向了基于信息论的科学轨道。

近现代加密技术经历了无数次迭代，大体上可分为两类：**对称密钥算法**和**非对称密钥算法**。

对称密钥，即发送方和接收方采用**相同密钥**对明文进行加解密；非对称密钥则相反，它有两个公钥和私钥，分别用于加密、解密。

对称密钥可以任意选取，只要足够安全；而非对称密钥则是通过一系列[NP问题](https://en.wikipedia.org/wiki/P_versus_NP_problem)生成的。如RSA利用大质数性质，ECC（椭圆曲线）利用离散对数问题。

简单来讲，P问题是在多项式时间内可以解出的；NP问题是在多项式时间内可以验证一个解的；P = NP意味着NP问题也是在多项式时间内可以解出的，而非对称密钥就建立在P != NP的基础上。

以RSA为例，一个大致流程可以理解如下：

*   NP问题 -- RSA算法大质数分解；
    
*   一个特解 -- 两个因子和大质数，利用因子生成公钥、私钥；
    
*   两个精致算法 -- 可以利用**公钥加密、私钥解密** 或 **私钥签名、公钥认证**；
    
*   黑客攻击 -- 暴力分解大质数，拿到因子和私钥
    

### 弊端

*   对于对称密钥加密来说，缺点在于密钥的分发，如何保证安全地分发到发送方和接收方手上；
    
*   对于非对称密钥加密来说，缺点在于加解密的速度，如RSA算法每次加解密需要进行指数和取模运算，而对称密钥只需要做按位运算。
    

所以常见应用场景是结合两种方式，利用非对称密钥加密分发对称密钥，解决上述痛点问题。

Web2
----

### HTTPS

在传统的Web2服务中，一个最常见的加密就是TLS加密，HTTPS = HTTP + TLS。

HTTP是明文传输的，这意味着在网络中所有中间节点都可以看到传输信息。为了保护敏感信息，我们采用TLS加密，使明文内容只对服务端可见。

TLS的一个大致流程如下：

> 1.  完成TCP握手后，客户端发起TLS请求，携带**公开**随机数、支持的对称加密方法、TLS版本、[域名](https://datatracker.ietf.org/doc/html/rfc4366)等信息；
>     
> 2.  服务端返回证书、**公开**随机数、支持的对称加密方法；
>     
> 3.  客户端验证证书有效性，解出服务端公钥，发送一个**加密**随机数；
>     
> 4.  通过三个随机数生成**对称密钥**，加密之后的通信内容
>     

还有面对银行等安全场景的双向验证，服务器端还需验证客户端证书，大致流程也类似。

整个过程有一个问题：要如何信任服务端返回的证书（公钥），而不是中间人攻击替换后的？

在网络的黑暗丛林中，我们需要一个权威机构（CA）来认证，这里就涉及到非对称密钥的另一个用途：**私钥签名、公钥认证**。

CA通过它的私钥来证明证书的有效性，那我们如何确保正确拿到CA的公钥来认证呢？答案是它内置在操作系统或浏览器中，我们也可以手动增删。

最后为了保护这些CA的私钥不泄漏和降低泄漏后的影响面，我们把这些CA按层级划分，形成一个CA证书的信任链。

![Mirror证书信任链](https://storage.googleapis.com/papyrus_images/49f66963d728b2547c1daa9348e82271efad28f812e1d12bc904287d4576b2d3.png)

Mirror证书信任链

### Signal

在C2C的场景中，我们也需要端到端加密，不过是服务端变成了另一个客户端，但我们不希望中间服务器有能力窃听通信内容。

你可能会有疑问：既然是C2C，那为什么我们还需要服务器？原因有很多：

*   公钥的分发，中间服务器在这里相当于CA权威机构的角色，预防中间人攻击
    
*   NAT穿透，由于IPv4的局限性，我们大部分的地址是动态的内网地址，它是无法作为公网IP进行通信的
    
*   信息缓存，历史信息保存 或 一方离线时也需要由服务器缓存相关信息，等该端上线时再进行分发
    
*   信息转发，群组聊天中，需要中间服务器转发给其他成员，发送端只需发送一次到服务端
    
*   垃圾信息过滤，中间服务器采用好友关系等机制限制垃圾信息洪流
    

详情推荐阅读：

[https://iangeli.com/2019/04/25/%E7%AB%AF%E5%AF%B9%E7%AB%AF%E5%8A%A0%E5%AF%86%E9%80%9A%E8%AE%AF%E5%8D%8F%E8%AE%AESignal-protocol-%E5%AD%A6%E4%B9%A0.html](https://iangeli.com/2019/04/25/%E7%AB%AF%E5%AF%B9%E7%AB%AF%E5%8A%A0%E5%AF%86%E9%80%9A%E8%AE%AF%E5%8D%8F%E8%AE%AESignal-protocol-%E5%AD%A6%E4%B9%A0.html)

区块链
---

### 加密货币

区块链上的虚拟货币也被称为 **加密货币**。加密属性从何而来？

个人所认为的加密不只是所谓的**地址代替实名**，而是更有意义的**隐匿**：**隐匿资产**、**隐匿地址关系**、**隐匿交易细节**。

很遗憾，目前主流的区块链本身并没有这一功能，它也不算是必需品，因此后面在区块链协议之上繁衍出了各种应用级产品：**隐私币**、**隐私合约**，最后甚至是专门面向隐私功能的**隐私链**。

在了解这些产品前，我们先来学习下区块链本身的隐匿性。以比特币和以太坊的帐户模型为例，推荐阅读：

[https://zhuanlan.zhihu.com/p/57272282](https://zhuanlan.zhihu.com/p/57272282)

小结下就是：区块链本身的隐匿性聊胜于无，基于UTXO模型的[P2SH类型](https://happypeter.github.io/binfo/p2sh)交易，有一定的隐匿性，可以暂时 **隐匿接收者（地址关系）**，当花费这笔代币时，接收者还是会暴露。

### 零知识证明

在学习下面的加密原理之前，先要理解一个不可或缺的知识点 -- **零知识证明**。可以参考我之前的一篇小结：

[https://mirror.xyz/dashboard/edit/RpJjYqyGm2KcFxpY3FeV9-tDe6qL-uaZ91zHsC6wojA](https://mirror.xyz/dashboard/edit/RpJjYqyGm2KcFxpY3FeV9-tDe6qL-uaZ91zHsC6wojA)

一个简单的程序实现，推荐阅读：

[https://learnblockchain.cn/article/1078](https://learnblockchain.cn/article/1078)

这篇文章比较旧了，相关命令已经失效，具体命令执行流程推荐阅读官方文档：

[https://github.com/iden3/snarkjs#guide](https://github.com/iden3/snarkjs#guide)

有了上面的预备知识，接下来我将带大家简单剖析各个具体的隐私应用，来了解其中的加密原理。

### 隐私币

隐私币一般指基于比特链协议的硬分叉的区块链，一条链即一个币，也基于比特币的UTXO模型。比特链生态是没有智能合约应用概念的，我将这些功能链也视为一个个应用级的产品。

**Dash**

Dash采用**混币系统**来实现一定程度的隐私。它在比特链的基础上进行了扩展，建立了一个由主节点和矿工组成的双层网络。

> 第一层网络中，矿工节点通过POW共识来计帐和保护网络安全;
> 
> 第二层网络实现混币相关的功能，主节点用于执行隐私交易、即时交易和网络管理。 节点将多方交易混合在一起再对外发送，打乱地址关系的映射。

该方法只能实现对地址关系的隐匿，甚至在参与方较少、金额数目特殊的情况下，地址关系也无所遁形。

**Monero**

推荐阅读：

[https://learnblockchain.cn/index.php/article/1123](https://learnblockchain.cn/index.php/article/1123)

**Zcash**

Zcash的隐藏原理基于**单向哈希**和**零知识证明**：

> 要隐藏一个信息很简单，一开始我们就提到了各种加密方法；
> 
> 要隐藏一个不需要恢复的信息更简单，一个单向的哈希就可以做到。

既然我们不想让任何人查看交易细节，那我们就将这些全部做哈希处理再存储到共识节点，不就可以了？

当然共识节点也不傻，你提交一条哈希给我，我如何知道哈希所代表的内容是否准确？这时便需要零知识证明发挥作用了。另外为了防止重放攻击，还需要对证明进行签名。

具体细节推荐阅读：

[https://www.8btc.com/article/526391](https://www.8btc.com/article/526391)

下面我们梳理下整个Zcash的交易流程，与UTXO模型大体类似（UTXO模型的交易流程由于有**P2PKH**、**P2SH**等各种类型，就不再赘述）。

首先Zcash中，UTXO模型（note）结构体如下：

*   持有者的公钥: a\_pk；
    
*   数额: value，简称 v；
    
*   随机数: r；
    
*   随机数hash：rho，即HASH（r）
    

> 1.  A -→ B 转账，多个input note -→ 多个output note（可能有剩余返还给A）
>     
> 2.  A解析并发布这些input note（**hash**）的废弃声明，共识节点在nullifier列表中验证，防止双花；同时发送新生成的output note（**hash**）声明；
>     
>     还要发送零知识证明和签名，证明A发送的这些hash声明对应的交易内容是完全正确的
>     
> 3.  A将属于B的output note（**detail**）发送给B
>     

注意第三步，由于链上存储的都是hash，B是不知道note细节的，但是在花费这些note时，B需要发布基于rho的废弃声明，所以A需要发送具体内容给B。

那么怎么在不安全的网络安全地发送明文内容呢？

Zcash的具体加密方案，推荐阅读：

[https://learnblockchain.cn/2019/07/28/zcash-sprout](https://learnblockchain.cn/2019/07/28/zcash-sprout)

Zcash白皮书：

[https://github.com/zcash/zips/blob/main/protocol/protocol.pdf](https://github.com/zcash/zips/blob/main/protocol/protocol.pdf)

### 隐私合约

**Tornado Cash**

Tornado是基于以太坊的混币应用，也是只能打乱地址的映射关系。

不过它有意思的地方在于利用零知识证明，实现了验证逻辑。整体流程如下：

> 1.  存款前生成随机数secret和nullifier，nullifier -→ nullifierHash，secret + nullifier -→ commitment，tornado note = nullifier + secret；
>     
> 2.  存款时，提交commitment，没有冲突就会将commitment插入到合约地址维护的Merkle树中；
>     
> 3.  取款前，输入凭证note，解析出nullifierHash和commitment，并从Merkle树中获取commitment的链路；
>     
> 4.  取款时，输入取款地址，与secret、nullifier和其他证明一起生成零知识证明，以供验证
>     

PS：Tornado的中继服务解决了支付困境问题，提款时交易费由中继者支付，同时扣除提款总额的一部分作为服务费。

官方文档：

[https://docs.tornado.cash/general/readme](https://docs.tornado.cash/general/readme)

源码地址：

[https://github.com/tornadocash/tornado-core](https://github.com/tornadocash/tornado-core)

源码解读：

[https://zhuanlan.zhihu.com/p/94979076](https://zhuanlan.zhihu.com/p/94979076)

**Automata Network**

Automata Network的定位是应用中间件，支持多链协议，它的隐私功能致力于提供一套安全可信的运行环境。

不过个人理解，像预言机一样，它提供的只是链下隐私，进行相关的证明验证，得到结果后再通知链上DAPP。

具体实现原理是通过 **TEE可信执行环境** 与 **Oblivious RAM** 算法，创建一个本地数据无法被第三方（甚至本地进程）访问的安全空间。

TEE的具体实现通过Intel的SGX，它保证了**数据隐私**和**远程证明**。保证数据隐私很好理解，远程证明是指向其他第三方提供相关远程安全证明：

*   硬件检查：硬件制造商会有相关私钥签名，可以通过公钥进行验证；
    
*   软件检查：生成软件代码哈希，进行校验
    

那TEE有什么作用呢？

> 前面我们提到过完全加密很好处理，一个单向哈希即可，但难的是我们需要同时让矿工节点知道交易内容的准确性。
> 
> 一种解决方案是零知识证明，但它的生成很复杂；另一种就是TEE。TEE提供了一个可信环境，除了特定的一组接口，无法通过其他方法读写数据。
> 
> 通过这个特点，我们可以在其中进行任何隐私验证。如通过编写TA程序（Trusted Application），我们可以把矿工验证逻辑放到TEE中，矿工只需要知道一个验证结果。同时在不同节点远程校验，从而形成共识。
> 
> 当然TEE和零知识证明也不是互斥的，我们甚至可以在TEE之上使用零知识证明。

只是对数据加密还不够，通过\*\*侧信道攻击（side channel attack）\*\*也可能获取敏感信息：由于[数据访问模式](https://en.wikipedia.org/wiki/Memory_access_pattern)，当频繁读写某些数据时，攻击者可以定位到数据储存位置，甚至推测出敏感信息。这时便需要 **Oblivious RAM** 算法来隐藏真实访问。

算法原理也很好理解，每次读写数据时，不仅仅读写所需的数据，同时读写其他数据进行混淆

### 隐私链

**Secret Network**

Secret Network是基于Cosmos的一条支持智能合约的异构链，它利用TEE实现了对隐私的支持。

一个大致流程如下：

> 1.  开发人员编写智能合约并部署，合约加密发送到矿工节点TEE中；
>     
> 2.  节点在TEE中解密验证交易内容，提出一个包含加密输出和更新加密状态的区块；
>     
> 3.  2/3 的验证者就加密输出和状态达成共识，存储合约代码到TEE中；
>     
> 4.  用户向智能合约发起交易，包括加密的数据输入，流程同上；
>     

学习 Secret Network 合约，首先要了解 Rust 语言，这里推荐 Rust 圣经：

[https://course.rs/](https://course.rs/)

学习 Secret Network 前，需要了解CosmWasm，前者建立在后者的基础上。CosmWasm 和 Solidity 有很多不同，也需要了解：

[https://docs.cosmwasm.com/docs/1.0/](https://docs.cosmwasm.com/docs/1.0/)

对 Secret Network 的学习，推荐先阅读官方文档大致了解下，也提供了许多学习资源：

[https://build.scrt.network/](https://build.scrt.network/)

开发入门，强烈推荐教程：

[https://learn.figment.io/protocols/secret](https://learn.figment.io/protocols/secret)

里面有很多细节，如：

*   编译不成功，利用docker编译：[https://learn.figment.io/tutorials/deploy-your-own-secret-nft#compile-the-contract](https://learn.figment.io/tutorials/deploy-your-own-secret-nft#compile-the-contract)
    
*   调用传参，uint128类型对应js的string类型：[https://learn.figment.io/tutorials/creating-a-secret-contract-from-scratch#a-note-about-data-types-between-the-client-and-contract](https://learn.figment.io/tutorials/creating-a-secret-contract-from-scratch#a-note-about-data-types-between-the-client-and-contract)
    
*   Query和Handle的花费和安全如何取舍：[https://learn.figment.io/tutorials/create-your-first-secret-nft#querying-the-contract](https://learn.figment.io/tutorials/create-your-first-secret-nft#querying-the-contract)
    

测试网络：

[https://github.com/scrtlabs/testnet/blob/master/pulsar-2/details.md](https://github.com/scrtlabs/testnet/blob/master/pulsar-2/details.md)

最后提下ERC20、ERC721规范的兼容实现：

[https://build.scrt.network/dev/tutorials.html#references-for-secret-contracts](https://build.scrt.network/dev/tutorials.html#references-for-secret-contracts)

PS：这个只是对规范的兼容，没有实现支付、白名单等功能。下面这个库增加了这些功能：

[https://github.com/luminaryphi/secret-random-minting-snip721-impl](https://github.com/luminaryphi/secret-random-minting-snip721-impl)

**Oasis Network**

Oasis Network是一条支持智能合约的区块链。它采用**模块化**设计，提供了对**隐私**、**私有链**的支持。

Oasis 由两层网络构成：共识层和ParaTime层。你可以将其理解为二层的架构设计，类似于以太坊L2的多链，在ParaTime层中执行智能合约的计算。整体架构图如下所示：

![Oasis网络架构](https://storage.googleapis.com/papyrus_images/87093135c687217eeb3a69f2ec2851ab14f28b58b56fdd854fcbecab5115d8fc.png)

Oasis网络架构

前面提到的模块化就是指ParaTime的实现非常灵活，支持自由组合：

*   在代码规范方面可以支持 EVM 或 WASM；
    
*   在加密隐私方面可以直接裸奔，或选择TEE、零知识证明等加密；
    
*   在公私链方面可以设计为有无许可系统
    

项目介绍：

[https://www.chaincatcher.com/article/2072039](https://www.chaincatcher.com/article/2072039)

白皮书：

[https://docsend.com/view/6sui2cag4p45ea45](https://docsend.com/view/6sui2cag4p45ea45)

### 隐私项目

推荐阅读：

[https://www.chaincatcher.com/article/2070927](https://www.chaincatcher.com/article/2070927)

---

*Originally published on [kutugu](https://paragraph.com/@kutugu/bGk6BHFDlK8bRL5LA56d)*
