Rust已经在编程语言界掀起了一场风暴。自2015年发布1.0版本以来,它已经成为最受喜爱的编程语言之一,拥有一批忠实的开发者和贡献者。
为了了解为什么这种语言在开发者之间如此受宠,我们开始了一个关于Rust生产的新系列。在其中,我们将采访那些在重大项目中使用Rust的人:应用程序、服务、创业公司的MVP等等。
在该系列的第一篇中,我们采访了1Password的工程副总裁Michael Fey。请继续阅读,以了解他们为什么为自己的产品选择了Rust,Rust对于以安全为中心的应用程序的好处,以及如果你正在用Rust开发类似的东西,你应该关注哪些很酷的库。
你能告诉我们一些关于你的公司和你在那里的角色吗?
1Password是一个密码管理器,受到数百万人和7万家企业的信任,以保护他们的敏感数据。它能记住你所有的密码,这样你就不必记住了,它的应用程序适用于所有主要的浏览器,还有桌面和手机。
我是1Password公司的客户应用工程副总裁。如果你曾经有幸在你的Mac、Windows PC、iPhone、iPad、Android手机或平板电脑上,或者在你的浏览器中使用过1Password,那么你就很幸运地使用了我的团队建立的东西。我们自2004年以来就一直存在,我们对建立一个精心设计的体验和保护人们的网络安全感到非常自豪。
.jpg)
你能谈谈 1Password 的堆栈吗?你们的代码库中有多大一部分是用Rust编写的?
我们在 1Password 的生产中使用 Rust 已经有几年时间了。我们的 Windows 团队是这项工作的领头羊,以至于 Windows 版 1Password 7 中约有 70% 是用 Rust 编写的。我们还在2019年底将1Password Brain--为我们的浏览器填充逻辑提供动力的引擎--从Go移植到Rust,以便我们能够利用在浏览器扩展中部署Rust到WebAssembly的速度和性能优势。
在过去的几年里,这些产品一直在生产,我们已经看到了巨大的成功。以至于我们现在正在对几乎整个产品系列进行全面重写,而Rust是这个故事的一个主要部分。我们正在使用Rust来创建一个无头的1Password应用,它包含了所有的业务逻辑、密码学、数据库访问、服务器通信等,并被包裹在一个薄薄的UI层中,是我们部署的系统的本机。
Rust的任何优势,如速度或类型/内存安全,是否影响了1Password使用Rust的选择?
最初吸引我们使用Rust的主要原因之一是内存安全;知道Rust可以帮助我们最大限度地保证客户的秘密安全,这无疑让我们感到兴奋。不过,除了内存安全之外,我们对Rust生态系统的喜爱还有很多。没有传统的运行时在性能上有很大的好处;比如说,我们不必担心垃圾收集器的开销。Rust提供了一种 "程序正确性 "的形式,以及对运行时未定义行为的许多保证。强类型系统在编译时执行了这些规则。仔细调整应用逻辑与Rust的强类型规则,使得API难以被错误地使用,并导致更简单的代码,不需要在运行时检查约束和不变量;编译器可以保证没有无效的运行时代码路径,在执行之前就会把你的程序引入歧途。必须执行较少的运行时状态验证,这导致了更干净、更有效、更集中和更高质量的代码。与其他语言相比,Rust需要的运行时调试非常少。如果它能编译,你可以相当肯定它不会出现意外的行为。它可能不是你想要的,但它会是 "正确的"。 🙂
Rust的另一个非常强大的(也是经常被忽视的)特性是它的程序性宏系统,这使得我们能够编写一个工具,自动将Rust中定义的类型与我们的客户端语言(Swift、Kotlin和TypeScript)共享。这个工具的输出会自动处理序列化/反序列化过程,这意味着我们的客户端开发人员在与Rust库交互时,可以继续用他们选择的语言工作,并且可以摆脱通过外国函数接口(FFI)解析JSON的担忧。我们在获得这一切的同时,还能享受到我们每一种目标语言的编译时类型检查的好处。我们也将这个工具整合到了我们的持续集成服务器中,这意味着对Rust模型的修改可能会导致客户端应用程序的编译失败,而这些失败在我们的审查过程中会被发现。
这个工具在我们的开发过程中是一个不可或缺的组成部分,使我们能够比以前更快速地前进。一旦我们的类型在Rust中被定义,我们就能够立即在我们的客户端语言中生成等效的类型。这使得我们的开发人员能够专注于解决问题,而不需要手工编写模板代码来通过FFI进行通信。
Rust对开发像1Password这样以安全为中心的应用程序的支持(库和其他)有多好?
对于以安全为中心的应用程序来说,有足够的支持来建立大部分的基础。有两个大型的、著名的密码学平台*(ring*和Rust Crypto组),它们共同提供了丰富的功能。正如我在上面提到的,用Rust写作本身让你对内存的使用更有信心,并且更难意外地将与内存有关的漏洞引入你的应用程序。还有一个很好的系统,用于跟踪Rust crates中不时出现的漏洞:RustSec数据库,它是由其他Rust开发者提供的社区资源,并经常更新新的信息,可以在CI审核扫描中使用。Rust和Cargo还包括电池测试框架,这意味着你总是有一种简单的方法来编写单元测试套件,以确保关键代码的正确行为,如你编写的任何加密函数。
虽然安全的本地Rust库是我们的梦想(它们会及时出现),但我们总是可以选择在C语言或本地平台库中轻松消费一些东西。在我们的Rust代码中,这一点得到了很好的利用,比如调用生物识别解锁的本地实现(Touch ID、Face ID、Windows Hello)和平台特定的设置实现,如苹果平台的NSUserDefaults。
有什么特别的Rust库是你想要介绍的吗?
当然有。Tokio、Hyper/Reqwest、Ring和Neon都在1Password中占有一席之地,它们是我们能够处理这个雄心勃勃的项目的基础。你也应该看看我们在crates.io上的密码规则解析器,它是基于一个主要由苹果支持的规格。他们的工具和文档可以在这里找到。
Rust在哪些方面很好用,在你的堆栈中又有哪些不足之处?
Rust已经实现了我们开始这个项目时的90%的期望。我们已经能够以某种方式或形式将其部署到几乎所有的目标平台(Apple Watch除外)。该语言本身的设计具有现代感,并且每一个版本都在不断改进。它有很好的文档和一个活跃的社区。
虽然有无数的箱体可供使用,但我们确实不得不推出自己的日志和跟踪工具,以确保它们可以安全地用于1Password。此外,我们构建了一个实质性的本地化实施,以满足我们产品的要求。
在一个关键领域,它确实让我们感到不足。我们希望WebAssembly能在浏览器和我们的浏览器扩展中比它更进一步。WebAssembly作为一个函数库是很好的,但要在WASM中建立一个完整的运行时,却是一个挑战。然而,我们遇到的许多问题不是Rust的限制,而是WebAssembly作为部署平台的限制。
在用Rust开发1Password时,最大的挑战是什么?
我们团队中的许多人都是Rust的新手,他们经历了其内存管理和所有权模型带来的典型学习曲线。我们还发现,编译时间相当长;我们的CPU和风扇肯定会得到锻炼。😄
你对这个结果满意吗?
当然满意。
你有什么关键的收获想和我们的观众分享吗?
如果你是Rust的新手,从小事做起,在此基础上再做。在我们刚开始的时候,我们进行了大量的实验,试图找到基于Rust的解决方案所能提供的边缘。当你的实验结果出来后,试着重新想象你过去使用其他语言的工作方式,看看你的代码是否能从Rust的哲学中受益。