加密,即将明文信息改变为难以理解的密文内容,使之不可读。只有拥有解密方法的对象,才能将密文还原为明文。
从古至今,密码学已有数千年的历史。从早期的古典密码,到近现代密码,再到未来的量子密码。加密手段也由早期简单的代替和置换,进化到现代数学方法,再到未来的量子性质。
本篇文章无意讲述整个密码学的发展史,而是聚焦于现代计算机应用中所涉及的加密方法和原理,漫谈 Web2 和 区块链 涉猎的加密内容。
个人能力所限,如有缺漏错误之处,望指正。
推荐阅读:
近现代以来,随着数学方法和的计算机科学蓬勃发展,为加密技术提供了新的概念和工具。一个重要的标志是香农的《保密系统通信理论》,将传统密码学推向了基于信息论的科学轨道。
近现代加密技术经历了无数次迭代,大体上可分为两类:对称密钥算法和非对称密钥算法。
对称密钥,即发送方和接收方采用相同密钥对明文进行加解密;非对称密钥则相反,它有两个公钥和私钥,分别用于加密、解密。
对称密钥可以任意选取,只要足够安全;而非对称密钥则是通过一系列NP问题生成的。如RSA利用大质数性质,ECC(椭圆曲线)利用离散对数问题。
简单来讲,P问题是在多项式时间内可以解出的;NP问题是在多项式时间内可以验证一个解的;P = NP意味着NP问题也是在多项式时间内可以解出的,而非对称密钥就建立在P != NP的基础上。
以RSA为例,一个大致流程可以理解如下:
所以常见应用场景是结合两种方式,利用非对称密钥加密分发对称密钥,解决上述痛点问题。
在传统的Web2服务中,一个最常见的加密就是TLS加密,HTTPS = HTTP + TLS。
HTTP是明文传输的,这意味着在网络中所有中间节点都可以看到传输信息。为了保护敏感信息,我们采用TLS加密,使明文内容只对服务端可见。
TLS的一个大致流程如下:
- 完成TCP握手后,客户端发起TLS请求,携带公开随机数、支持的对称加密方法、TLS版本、域名等信息;
- 服务端返回证书、公开随机数、支持的对称加密方法;
- 客户端验证证书有效性,解出服务端公钥,发送一个加密随机数;
- 通过三个随机数生成对称密钥,加密之后的通信内容
还有面对银行等安全场景的双向验证,服务器端还需验证客户端证书,大致流程也类似。
整个过程有一个问题:要如何信任服务端返回的证书(公钥),而不是中间人攻击替换后的?
在网络的黑暗丛林中,我们需要一个权威机构(CA)来认证,这里就涉及到非对称密钥的另一个用途:私钥签名、公钥认证。
CA通过它的私钥来证明证书的有效性,那我们如何确保正确拿到CA的公钥来认证呢?答案是它内置在操作系统或浏览器中,我们也可以手动增删。
最后为了保护这些CA的私钥不泄漏和降低泄漏后的影响面,我们把这些CA按层级划分,形成一个CA证书的信任链。
在C2C的场景中,我们也需要端到端加密,不过是服务端变成了另一个客户端,但我们不希望中间服务器有能力窃听通信内容。
你可能会有疑问:既然是C2C,那为什么我们还需要服务器?原因有很多:
详情推荐阅读:
区块链上的虚拟货币也被称为 加密货币。加密属性从何而来?
个人所认为的加密不只是所谓的地址代替实名,而是更有意义的隐匿:隐匿资产、隐匿地址关系、隐匿交易细节。
很遗憾,目前主流的区块链本身并没有这一功能,它也不算是必需品,因此后面在区块链协议之上繁衍出了各种应用级产品:隐私币、隐私合约,最后甚至是专门面向隐私功能的隐私链。
在了解这些产品前,我们先来学习下区块链本身的隐匿性。以比特币和以太坊的帐户模型为例,推荐阅读:
小结下就是:区块链本身的隐匿性聊胜于无,基于UTXO模型的P2SH类型交易,有一定的隐匿性,可以暂时 隐匿接收者(地址关系),当花费这笔代币时,接收者还是会暴露。
在学习下面的加密原理之前,先要理解一个不可或缺的知识点 -- 零知识证明。可以参考我之前的一篇小结:
一个简单的程序实现,推荐阅读:
这篇文章比较旧了,相关命令已经失效,具体命令执行流程推荐阅读官方文档:
有了上面的预备知识,接下来我将带大家简单剖析各个具体的隐私应用,来了解其中的加密原理。
隐私币一般指基于比特链协议的硬分叉的区块链,一条链即一个币,也基于比特币的UTXO模型。比特链生态是没有智能合约应用概念的,我将这些功能链也视为一个个应用级的产品。
Dash
Dash采用混币系统来实现一定程度的隐私。它在比特链的基础上进行了扩展,建立了一个由主节点和矿工组成的双层网络。
第一层网络中,矿工节点通过POW共识来计帐和保护网络安全;
第二层网络实现混币相关的功能,主节点用于执行隐私交易、即时交易和网络管理。 节点将多方交易混合在一起再对外发送,打乱地址关系的映射。
该方法只能实现对地址关系的隐匿,甚至在参与方较少、金额数目特殊的情况下,地址关系也无所遁形。
Monero
推荐阅读:
Zcash
Zcash的隐藏原理基于单向哈希和零知识证明:
要隐藏一个信息很简单,一开始我们就提到了各种加密方法;
要隐藏一个不需要恢复的信息更简单,一个单向的哈希就可以做到。
既然我们不想让任何人查看交易细节,那我们就将这些全部做哈希处理再存储到共识节点,不就可以了?
当然共识节点也不傻,你提交一条哈希给我,我如何知道哈希所代表的内容是否准确?这时便需要零知识证明发挥作用了。另外为了防止重放攻击,还需要对证明进行签名。
具体细节推荐阅读:
下面我们梳理下整个Zcash的交易流程,与UTXO模型大体类似(UTXO模型的交易流程由于有P2PKH、P2SH等各种类型,就不再赘述)。
首先Zcash中,UTXO模型(note)结构体如下:
A -→ B 转账,多个input note -→ 多个output note(可能有剩余返还给A)
A解析并发布这些input note(hash)的废弃声明,共识节点在nullifier列表中验证,防止双花;同时发送新生成的output note(hash)声明;
还要发送零知识证明和签名,证明A发送的这些hash声明对应的交易内容是完全正确的
A将属于B的output note(detail)发送给B
注意第三步,由于链上存储的都是hash,B是不知道note细节的,但是在花费这些note时,B需要发布基于rho的废弃声明,所以A需要发送具体内容给B。
那么怎么在不安全的网络安全地发送明文内容呢?
Zcash的具体加密方案,推荐阅读:
Zcash白皮书:
Tornado Cash
Tornado是基于以太坊的混币应用,也是只能打乱地址的映射关系。
不过它有意思的地方在于利用零知识证明,实现了验证逻辑。整体流程如下:
- 存款前生成随机数secret和nullifier,nullifier -→ nullifierHash,secret + nullifier -→ commitment,tornado note = nullifier + secret;
- 存款时,提交commitment,没有冲突就会将commitment插入到合约地址维护的Merkle树中;
- 取款前,输入凭证note,解析出nullifierHash和commitment,并从Merkle树中获取commitment的链路;
- 取款时,输入取款地址,与secret、nullifier和其他证明一起生成零知识证明,以供验证
PS:Tornado的中继服务解决了支付困境问题,提款时交易费由中继者支付,同时扣除提款总额的一部分作为服务费。
官方文档:
源码地址:
源码解读:
Automata Network
Automata Network的定位是应用中间件,支持多链协议,它的隐私功能致力于提供一套安全可信的运行环境。
不过个人理解,像预言机一样,它提供的只是链下隐私,进行相关的证明验证,得到结果后再通知链上DAPP。
具体实现原理是通过 TEE可信执行环境 与 Oblivious RAM 算法,创建一个本地数据无法被第三方(甚至本地进程)访问的安全空间。
TEE的具体实现通过Intel的SGX,它保证了数据隐私和远程证明。保证数据隐私很好理解,远程证明是指向其他第三方提供相关远程安全证明:
那TEE有什么作用呢?
前面我们提到过完全加密很好处理,一个单向哈希即可,但难的是我们需要同时让矿工节点知道交易内容的准确性。
一种解决方案是零知识证明,但它的生成很复杂;另一种就是TEE。TEE提供了一个可信环境,除了特定的一组接口,无法通过其他方法读写数据。
通过这个特点,我们可以在其中进行任何隐私验证。如通过编写TA程序(Trusted Application),我们可以把矿工验证逻辑放到TEE中,矿工只需要知道一个验证结果。同时在不同节点远程校验,从而形成共识。
当然TEE和零知识证明也不是互斥的,我们甚至可以在TEE之上使用零知识证明。
只是对数据加密还不够,通过**侧信道攻击(side channel attack)**也可能获取敏感信息:由于数据访问模式,当频繁读写某些数据时,攻击者可以定位到数据储存位置,甚至推测出敏感信息。这时便需要 Oblivious RAM 算法来隐藏真实访问。
算法原理也很好理解,每次读写数据时,不仅仅读写所需的数据,同时读写其他数据进行混淆
Secret Network
Secret Network是基于Cosmos的一条支持智能合约的异构链,它利用TEE实现了对隐私的支持。
一个大致流程如下:
- 开发人员编写智能合约并部署,合约加密发送到矿工节点TEE中;
- 节点在TEE中解密验证交易内容,提出一个包含加密输出和更新加密状态的区块;
- 2/3 的验证者就加密输出和状态达成共识,存储合约代码到TEE中;
- 用户向智能合约发起交易,包括加密的数据输入,流程同上;
学习 Secret Network 合约,首先要了解 Rust 语言,这里推荐 Rust 圣经:
学习 Secret Network 前,需要了解CosmWasm,前者建立在后者的基础上。CosmWasm 和 Solidity 有很多不同,也需要了解:
对 Secret Network 的学习,推荐先阅读官方文档大致了解下,也提供了许多学习资源:
开发入门,强烈推荐教程:
里面有很多细节,如:
测试网络:
最后提下ERC20、ERC721规范的兼容实现:
PS:这个只是对规范的兼容,没有实现支付、白名单等功能。下面这个库增加了这些功能:
Oasis Network
Oasis Network是一条支持智能合约的区块链。它采用模块化设计,提供了对隐私、私有链的支持。
Oasis 由两层网络构成:共识层和ParaTime层。你可以将其理解为二层的架构设计,类似于以太坊L2的多链,在ParaTime层中执行智能合约的计算。整体架构图如下所示:
前面提到的模块化就是指ParaTime的实现非常灵活,支持自由组合:
项目介绍:
白皮书:
推荐阅读: