查看原文
其他

应用的加密:互联网计算机的一个公钥

DFINITY 2022-07-07




互联网计算机是由运行高级去中心化协议的独立数据中心网络创建的革命性区块链计算机,使开发人员、组织和企业家能够构建和部署安全的应用程序和自治软件程序。


与在专有基础结构或特定托管服务上运行的典型的基于云或分布式体系结构不同,互联网计算机提供了一个开放平台,软件和服务可直接在开放互联网上运行。


分散的互联网计算机协议(ICP)通过实施高级加密技术来创建此安全网络。


在分散的分布式系统中,会出现各种问题。在对等级别,我们如何在这种敌对的开放环境中的节点之间传播工件?我们如何以最有效的方式做到这一点?我们如何定义最合适的网络拓扑?


接下来,有一个共识协议,主要问题是确保在没有中央权限的情况下,以正确的顺序验证和处理正确的交易。


在DFINITY基金会,研发与我们创建的公共平台之间没有区别。


我们的研发团队成员定期实施新技术,并了解他们的想法在实际应用中的应用。


在加密级别实现此功能的一个很好的例子是互联网计算机的非交互式分布式密钥生成(NIDKG)协议-基金会首次发布了新颖的核心加密技术。


引入非交互式DKG


在互联网计算机上运行的应用程序或服务的最终用户与软件容器进行交互,并且不会直接看到用于构建此分散式开发平台的高级加密技术。


互联网计算机定义了一个简单而干净的界面,该界面指定了容器的工作方式,从而实现了一个软件生态系统,其中不同的应用程序可以相互通信并使用彼此的API。



深入研究揭示了数字签名的用法,通过该签名,互联网计算机可以对输出进行认证和验证。


数字签名是现代加密技术曙光的一部分,出现在1970年代后期的Diffie-Hellman和RSA的开创性著作中。


最终用户和与其他容器对话的容器需要信息进行认证。


但是,在互联网计算机上,容器托管在子网中,子网由全球各地的节点集合运行。


因此,节点必须运行分布式协议以达成一致并签署互联网计算机的输出。


阈值签名使子网上的节点可以协同签名数据,如果有足够的节点合作,则可以签名。


另一方面,一些恶意节点无法偏离和签署未经授权的消息。


到目前为止,一切都很好,但是有一个转折。


在互联网计算机上,运行子网的节点集将发生变化,节点可以加入并离开各自的子网。


根据网络的需求和要求,所需的安全级别、数据中心的可用容量、随机硬件故障等,运行子网的节点集会随着时间而变化,这意味着阈值签名者组会随着时间而发展。



这样做的影响是,在子网内不断变化的节点中,继续生成、注册和分发新的公共密钥会在逻辑上变得很复杂。


作为替代解决方案,即使同一子网始终可以被静态公钥引用,即使组成子网的节点处于不断变化的状态,也可以极大地简化密钥管理。


幸运的是,公共密钥保存具有加密解决方案,并且可以重新共享密钥。


通过这些密钥重新共享方案,参与阈值签名方案的一组签名者可以将阈值签名的能力转移给另一组签名者。


现有的密钥重分配方案有很多好处,但是它们有一个局限性:它们是交互式的,从而引发了异步问题。


如果缺少来自节点的消息,则不清楚该消息是仅延迟还是该节点崩溃或受到损害。


DFINITY研发团队已经发明了一种新的非交互式密钥重新共享协议,每个旧的签名者只需要向新的签名者广播一条消息。


为了确保安全地完成此操作,使用了高级密码学中的许多概念,包括使用前向机密和非交互式零知识证明的加密。


因为它是非交互的,所以密钥重新共享协议的操作方式非常适合异步环境,其好处包括密钥保存。


在子网的整个生命周期中,单个公用密钥就可以知道它,并且互联网计算机上的其他各方不必跟踪更改公用密钥的情况。



查看子网密钥管理的不同阶段,该协议首先适用于初始密钥生成。


互联网计算机可以使用NIDKG协议来启动新的子网,并为初始节点提供阈值签名密钥,而不必在设置过程中涉及初始节点。


节点仅了解它们已被分配给子网,就可以推断出它们的签名密钥的秘密份额,然后开始运行该子网。


在子网运行时,分布式密钥重新共享协议用于注册新的加入节点。


不需要长时间的注册过程,因为子网只是将加密的密钥材料留给了加入的节点。


预期最经常发生的是,一组节点将自己重新分配密钥,这听起来有些违反直觉,因为节点已经具有阈值签名密钥。


但是,这种想法源于主动安全性的概念。


问题在于,随着时间的流逝,节点可能会受到损害。


想象一个由相同节点运行一定时间长度的子网,这为攻击者提供了一个时间窗,在此期间,他们可以以某种方式了解节点在签名密钥中的阈值份额。


主动安全性通过继续刷新签名密钥的阈值份额来提供解决方案,这意味着节点重新共享密钥以获取签名密钥的新阈值秘密共享。


之后,它们将删除其旧共享,这意味着即使攻击者随着时间的推移从每个节点学习了一些共享,只要在任何给定时间仅知道任何给定纪元的少数共享,阈值签名密钥仍然是安全的。


NIDKG是DFINITY研发团队带头推动的众多创新之一,其追求互联网计算机的宏伟愿景来更新Web的创新能力,这一愿景正在稳步成为公共现实。


我们期待着欢迎开发人员探索网络的功能并创建未来的应用程序和服务。


加入我们的开发人员社区,并在forum.dfinity.org上开始构建。


延伸阅读


仔细研究软件容器-智能合约的发展


互联网计算机-通过运行一个先进的分散协议的独立数据中心网络创造了一个革命性的区块链计算机-实现了无缝的软件生态系统,不同的应用程序和程序通信,并使用对方的API。

通过容器(由代码和数据组成的计算单元)使之成为可能,容器可以部署在互联网计算机上,并可以通过互联网访问。

软件容器是开放式协作互联网的基础,并且是互联网计算机的关键概念。初次听说容器时,背景不同的人会建立不同的关联:

  • 以太坊开发人员可能会考虑智能合约

  • 博士学位学生可能考虑actor模型

  • 系统工程师可能会像在操作系统中一样考虑进程

  • 虚拟机专家可能会想到WebAssembly模块


尽管每个比较都是正确的,但它们也不完整。但总的来说,它们描绘了一幅完整的图画。

容器作为智能合约

容器就像智能合约一样,因为其执行受安全协议互联网计算机协议(ICP)的支配。

因此,容器是防篡改的,这意味着只能通过由协议控制的区块链中包含的消息来修改其状态。

此外,由于容器代码的执行是完全确定性的,因此可以通过检查区块链中的消息以加密安全的方式审核容器的状态。

容器具有传统智能合约的所有功能。但是,与智能合约相反,容器具有性能特征,因此可以使用它们来构建可扩展的软件服务。

容器作为actor

现在,让我们退后一步,从更抽象的角度考虑“容器”。从这个角度看,容器更象是一个actor在由计算机科学家卡尔·休伊特和其他捐助者开创的角色模型。

参与者模型是并发计算的数学模型,其中参与者响应一条消息,可以修改其本地或私有状态,发送消息并创建更多参与者。

在许多方面,容器都像actor一样。例如,actor有:

  • 只能由容器本身修改的私有状态

  • 一个执行线程,因此不需要基于锁的同步

  • 通过异步消息与其他容器通信的能力

  • 创建新容器的能力


传统actor和容器之间的重要区别是互联网计算机上的容器具有双向消息传递。

邮件分为请求和响应,可以在其中答复请求,并且互联网计算机会跟踪响应的回调。

用actor的术语来说,每个参与者都有一个用于接收消息的邮件地址。容器还具有一个邮寄地址,该邮寄地址看起来类似于IPv6地址。

单个容器只有一个执行线程进行更新,但是互联网计算机会并行执行可能数量庞大的容器。

这就是互联网计算机克服某些早期智能合约平台性能的限制的方式。此外,我们区分了需要更新容器状态的请求和不能修改容器状态的查询。

尽管容器的更新吞吐量受到区块链和单执行线程的限制,但容器可以同时服务数百个查询,从而实现每秒数千个查询的吞吐量,并以毫秒为单位测量延迟。

为了完善此图,必须补充一点,即最终用户至少在某种程度上也要作为参与者参与模型。这意味着浏览器和移动应用程序可以直接在容器上执行更新和查询操作。

由DFINITY基金会开发的Motoko编程语言受actor模型的启发。

容器作为进程

容器非常类似于Linux、MacOS或Windows等操作系统中的进程。操作系统跟踪进程的有效内存范围,而容器在其线性内存上有一个边界,该边界由互联网计算机强制执行。

当有工作要做时,操作系统调度程序会唤醒进程,而互联网计算机会调度容器的执行。

操作系统代表进程维护状态,例如打开文件描述符和父进程。

同样,互联网计算机代表容器来维护状态,但是代替文件描述符之类的东西,它会跟踪容器的令牌和cycles的余额、未完成的调用和权限等等。

正如进程无法直接修改其文件描述符表一样,容器也无法直接修改其令牌余额。

操作系统为进程提供功能,使它们能够执行特殊操作,例如处理文件和与外围设备通信。

同样,互联网计算机向容器提供API,以便它们可以:

  • 付款

  • 呼唤其他容器

  • 创建和管理容器

  • 管理权限

  • 获取系统时间(分布式系统中的重要功能)


互联网计算机的一个独特功能是它提供对安全随机性的访问。将来,容器还可以通过此类API签署比特币和以太坊合约。

在幕后,进程和容器之间的最大区别在于,容器在子网中的所有节点上复制。

当进程发生故障时,它崩溃,但是由于WebAssembly中的陷阱导致容器发生故障时,它不会崩溃。而是将其状态回滚到开始执行当前消息之前的状态,以便容器可以继续执行新消息。

当然,如果容器在接收到的所有消息上崩溃时,这都没有什么帮助,但是对于容器逻辑中的意外丢失案例,这是非常有用的保护措施。

实际上,容器无法与进程可以相同的方式终止-因为没有exit()或abort()系统调用。只能由其控制器通过管理命令从互联网计算机中删除容器。

容器的控制器是允许执行管理命令(例如删除或更新容器)的用户或其他容器。在互联网计算机上构建自治服务时,控制另一个容器的容器是关键要素。

容器作为WebAssembly模块实例

容器非常类似于WebAssembly模块实例。这不仅仅是一个类比-这是在互联网计算机上实际实现容器的方式。

从技术上讲,容器的代码部分是一个WebAssembly模块,该模块可导入系统API。

也就是说,互联网计算机提供给容器的功能。而且,容器可以导出自己的API,其他容器也可以调用该API。

根据WebAssembly规范:“模块实例是模块的动态表示,具有其自己的状态和执行堆栈。”

因此,容器是WebAssembly模块的实例,而不仅仅是WebAssembly模块的一个重要区别。

容器使用正交持久性来使模块实例看起来永远存在,从而使数据库或文件IO变得过时。要持久存储变量,开发人员只需将变量写入内存即可。

持久化数据的操作对开发人员是完全透明的,并且在某种意义上讲,正交化是指开发人员不必执行任何特殊的操作即可持久化数据。

跟踪到容器的线性内存的所有“写入”有两个原因。

首先,这样就可以回滚失败的计算或WebAssembly陷阱。

接下来,如果子网中的一个副本由于断电等不可预见的事件而崩溃,则当该副本恢复联机时,它将请求其他副本的已修改页面,从而可以恢复操作。

这就是互联网计算机保持给WebAssembly模块实例提供无限期生命的错觉。

拥抱WebAssembly可为互联网计算机带来以下好处:

  • 容器可以用可以编译成WebAssembly的任何语言(例如Motoko、Rust)编写,并且以不同语言编写的容器可以完全互操作。


  • WebAssembly是确定性的,除了一些容易排除的边缘情况。


  • WebAssembly具有形式语义,在更长的时间内,我们期望看到端到端经过正式验证的WebAssembly执行环境,以提高安全性。


此外,我们将随着WebAssembly规范的发展而发展,在新功能变得足够成熟时增加对新功能的支持。例如,在我们的路线图上可以在单个容器中支持多个模块。

软件容器是互联网计算机的基础,互联网规模的服务将由许多合作伙伴共同实施。拥有十亿用户的服务可能需要数千个容器才能存储用户数据。

但这不是问题。容器抽象旨在按比例缩放,非常直接,通过随着时间的推移变得更强大来实现,但主要是通过水平缩放,或使用大量协作实现单个服务的容器来向外扩展。

互联网计算机极大地简化了编写和部署代码的过程,访问官网开始使用容器在互联网计算机上进行构建。

在dfinity.org/sodium上注册以访问互联网计算机的Sodium开发者网络。

加入我们的开发人员社区,并在forum.dfinity.org开始构建。

撰文:DFINITY工程总监Johan Granström


Candid:互联网计算机上应用程序接口的通用语言

DFINITY基金会致力于通过推出互联网计算机来恢复互联网的自由和开放根源,这是世界上第一个具有无限计算能力的Web速度区块链网络,旨在增强开发人员的体验并提供更多选择,这是我们一直以来的关注重点。

互联网计算机托管软件容器,这是可扩展的传统智能合约的发展,它将WebAssembly字节代码与代码在其中运行的内存页面捆绑在一起。

这使开发人员能够构建革命性的互操作性应用程序、系统和安全可靠的互联网服务,利用令牌化等区块链功能,并直接在互联网上而不是在专有基础架构上部署软件。

为了支持在开放平台上重新定义的软件范围的增长,在该平台上不同的程序可以直接相互集成,并且可以轻松地组合和扩展服务,我们的语言团队开发了Candid接口描述语言(IDL)。

该接口可以使那些人协作建立互联网计算机生态系统以完全无缝地连接其代码,即使使用不同的语言编写也是如此,我们很高兴在今天对其进行更详细的描述。

什么是Candid?

Candid是专门为互联网计算机设计的IDL,它为应用程序接口提供了一种通用语言,以促进以不同编程语言编写的服务之间的通信。

Candid的主要优势之一是它与语言无关,可实现以不同编程语言(例如Motoko、Rust和JavaScript等)编写的服务和前端之间的互操作性。它使开发人员可以安全、无缝地构建彼此依赖的服务,而不必担心外部服务的接口升级。

通过Candid,我们试图…

  • 提供接口和数据描述:使用Candid的开发人员能够描述服务的公共接口,通常以部署为容器的程序的形式进行描述。作为开发人员,您可以将运行在互联网计算机上的外部服务称为异步函数调用。


  • 原则上支持接口的演变:Candid通过精确指定可以在不破坏现有客户端的情况下进行的更改来支持服务接口的演变,例如,这意味着您可以安全地向服务中添加新的可选参数而不会失去与现有客户的兼容性。


  • 支持互联网计算机功能:Candid特别适合开发互联网计算机的应用程序。


Candid在某种程度上受到了类似IDL和数据定义语言(DDL),例如Protobuf、Thrift和JSON的启发,但是Candid提供了这些其他技术所没有的独特功能组合:

  • Candid是一种完整的界面描述语言,而不仅仅是一种数据描述语言。


  • Candid实现可以将Candid值直接映射到宿主语言的类型和值。


  • Candid本质上是一种高阶语言,它允许消息参数包含对其他服务和方法的引用。


  • Candid具有对特定互联网计算机功能(例如query注释)的内置支持。


  • Candid定义了有关如何以合理和综合的方式升级服务及其接口的规则,包括高阶使用。


如何使用Candid?

Candid的主要目的是将以某种宿主语言(例如Motoko、Rust或JavaScript)编写的程序与互联网计算机连接。在大多数情况下,您不必将程序数据作为Candid值处理。

相反,您可以使用熟悉的JavaScript值使用JavaScript之类的宿主语言,然后依靠Candid将这些值透明地传输到用Rust或Motoko编写的容器中。容器接收这些值,并将其视为原始Rust或Motoko值。

在某些情况下,以人类可读的形式直接查看Candid值很有用-例如,在命令行上记录、调试或与服务交互时。在这些情况下,您可以将文本表示形式用于Candid值。

Candid是一个强类型化的系统,具有一组规范地涵盖大多数用途的类型(要查看列表,请参阅我们的SDK页面)。

这组类型背后的原理是,它们足以描述数据的结构,以便可以对信息进行编码、传递和解码,但是它们不尝试描述超出此范围的语义约束。

无论您是以Motoko、Rust、JavaScript还是其他语言编写代码,Candid都支持这组类型,以允许基于适用于每种宿主语言的合理、规范的选择来自然映射数据类型。

可以使用Candid类型通过Candid服务描述文件(.did文件)来描述服务,该文件可以手动编写,也可以从服务实现中生成。

例如,如果您在Motoko中编写一个容器,则编译器在编译程序时会自动生成一个Candid描述。

在其他语言中,例如Rust,您将必须手动编写Candid接口说明。在类型的帮助下,我们开发了工具来自动生成UI并根据服务描述文件执行随机测试。

Candid对服务升级也很有用,服务随着时间而发展,他们获得了新的方法,而现有的方法返回了更多的数据,或者期望有其他参数。通常,服务作者希望在不破坏现有客户的情况下做到这一点。

Candid通过定义精确的子类型化规则(在Coq!中正式化)来帮助服务安全地发展,这些子类型化规则指示何时新的服务类型仍将能够与使用先前接口描述的所有其他方进行通信。

有兴趣了解更多吗?以下是一些与Candid相关的材料,可帮助您入门……

Candid的教程和资源

  • Candid的讲解视频:您可以观看文章开始有关如何使用Candid的视频教程。


  • Candid的文档和教程:您可以访问我们SDK网站上有关Candid的文档:https://sdk.dfinity.org/docs/candid-guide/candid-intro.html


  • Candid Crate:Candid Crate是一个序列化/反序列化库,可用于在Rust中创建Candid服务或客户端:https://crates.io/crates/candid


  • JavaScript的互联网计算机代理库:该代理包括对Candid的支持。


  • 社区支持的Candid库:Haskell、Elm、AssemblyScript和Kotlin当前存在库。


  • Candid UI:此容器为互联网计算机上运行的任何容器生成一个前端UI,从而使开发人员能够与Web上的容器(而不是终端)进行交互,并提供调试功能。



作者:Jens Groth(DFINITY首席研究员)

翻译:Catherine



互联网计算机创世发布活动
估值253亿美元的明星公链Dfinity即将分发代币,将迎来陨落还是大放光彩?
DFINITY & Fleek & Capsule



进Dfinity交流社群,请添加小助手微信:

comiocn




长按关注

Dfinity微信公众号

给你第一手资讯和项目信息

更可随时答疑解惑



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存