2018年4月

在本系列文章中,我们将深度探讨如何使用 PGP 以及为工作于自由软件项目的开发者提供实用指南。在前一篇文章中,我们介绍了基本工具和概念。在本文中,我们将展示如何生成和保护你的 PGP 主密钥。

清单

  1. 生成一个 4096 位的 RSA 主密钥 (必要)
  2. 使用 paperkey 备份你的 RSA 主密钥 (必要)
  3. 添加所有相关的身份 (必要)

考虑事项

理解“主”(认证)密钥

在本节和下一节中,我们将讨论“主密钥”和“子密钥”。理解以下内容很重要:

  1. 在“主密钥”和“子密钥”之间没有技术上的区别。
  2. 在创建时,我们赋予每个密钥特定的能力来分配功能限制。
  3. 一个 PGP 密钥有四项能力

    • [S] 密钥可以用于签名
    • [E] 密钥可以用于加密
    • [A] 密钥可以用于身份认证
    • [C] 密钥可以用于认证其他密钥
  4. 一个密钥可能有多种能力

带有 [C] (认证)能力的密钥被认为是“主”密钥,因为它是唯一可以用来表明与其他密钥关系的密钥。只有 [C] 密钥可以被用于:

  • 添加或撤销其他密钥(子密钥)的 S/E/A 能力
  • 添加、更改或撤销密钥关联的身份(uid)
  • 添加或更改本身或其他子密钥的到期时间
  • 为了网络信任目的为其它密钥签名

在自由软件的世界里,[C] 密钥就是你的数字身份。一旦你创建该密钥,你应该格外小心地保护它并且防止它落入坏人的手中。

在你创建主密钥前

在你创建的你的主密钥前,你需要选择你的主要身份和主密码。

主要身份

身份使用邮件中发件人一栏相同格式的字符串:

Alice Engineer <[email protected]>

你可以在任何时候创建新的身份,取消旧的,并且更改你的“主要”身份。由于主要身份在所有 GnuPG 操作中都展示,你应该选择正式的和最有可能用于 PGP 保护通信的名字和邮件地址,比如你的工作地址或者用于在项目 提交 commit 时签名的地址。

密码

密码 passphrase 专用于私钥存储在磁盘上时使用对称加密算法对其进行加密。如果你的 .gnupg 目录的内容被泄露,那么一个好的密码就是小偷能够在线假冒你的最后一道防线,这就是为什么设置一个好的密码很重要的原因。

一个强密码最好使用丰富或混合的词典的 3-4 个词,而不引用自流行来源(歌曲、书籍、口号)。由于你将相当频繁地使用该密码,所以它应当易于输入和记忆。

算法和密钥强度

尽管现在 GnuPG 已经支持椭圆曲线加密一段时间了,但我们仍坚持使用 RSA 密钥,至少较长一段时间会这样。虽然现在就可以开始使用 ED25519 密钥,但你可能会碰到无法正确处理它们的工具和硬件设备。

在后续的指南中我们说 2048 位的密钥对 RSA 公钥加密的生命周期已经足够,你可能也会好奇主密钥为什么是 4096 位。 原因很大程度是由于社会因素而非技术上的:主密钥在密钥链上是最显眼的,如果你的主密钥位数比一些和你交互的开发者的少,他们肯定会鄙视你。

生成主密钥

为了生成你的主密钥,请使用以下命令,并且将 “Alice Engineer” 替换为正确值。

$ gpg --quick-generate-key 'Alice Engineer <[email protected]>' rsa4096 cert

这将弹出一个要求输入密码的对话框。然后,你可能需要移动鼠标或随便按一些键才能生成足够的熵,直到该命令完成。

查看命令输出,它就像这样:

pub rsa4096 2017-12-06 [C] [expires: 2019-12-06]
 111122223333444455556666AAAABBBBCCCCDDDD
uid Alice Engineer <[email protected]>

注意第二行的长字符串 —— 它是你新生成的密钥的完整指纹。密钥 ID(Key ID)可以用以下三种不同形式表达:

  • 指纹 Fingerprint ,一个完整的 40 个字符的密钥标识符
  • 长密钥 ID Long ,指纹的最后 16 个字符(AAAABBBBCCCCDDDD)
  • 短密钥 ID Short ,指纹的最后 8 个字符(CCCCDDDD)

你应该避免使用 8 个字符的短密钥 ID,因为它们不足够唯一。

这里,我建议你打开一个文本编辑器,复制你新密钥的指纹并粘贴。你需要在接下来几步中用到它,所以将它放在旁边会很方便。

备份你的主密钥

出于灾后恢复的目的 —— 同时特别的如果你试图使用 Web of Trust 并且收集来自其他项目开发者的密钥签名 —— 你应该创建你的私钥的硬拷贝备份。万一所有其它的备份机制都失败了,这应当是最后的补救措施。

创建一个你的私钥的可打印的硬拷贝的最好方法是使用为此而写的软件 paperkeypaperkey 在所有 Linux 发行版上可用,在 Mac 上也可以通过 brew 安装 paperkey

运行以下命令,用你密钥的完整指纹替换 [fpr]

$ gpg --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt

输出将采用易于 OCR 或手动输入的格式,以防如果你需要恢复它的话。打印出该文件,然后拿支笔,并在纸的边缘写下密钥的密码。这是必要的一步,因为密钥输出仍然使用密码加密,并且如果你更改了密钥的密码,你不会记得第一次创建的密钥是什么 —— 我保证。

将打印结果和手写密码放入信封中,并存放在一个安全且保护好的地方,最好远离你家,例如银行保险库。

打印机注意事项 打印机连接到计算机的并行端口的时代已经过去了。现在他们拥有完整的操作系统,硬盘驱动器和云集成。由于我们发送给打印机的关键内容将使用密码进行加密,因此这是一项相当安全的操作,但请使用您最好的偏执判断。

添加相关身份

如果你有多个相关的邮件地址(个人、工作、开源项目等),你应该将其添加到主密钥中。你不需要为任何你不希望用于 PGP 的地址(例如,可能不是你的校友地址)这样做。

该命令是(用你完整的密钥指纹替换 [fpr]):

$ gpg --quick-add-uid [fpr] 'Alice Engineer <[email protected]>'

你可以查看你已经使用的 UID:

$ gpg --list-key [fpr] | grep ^uid

选择主 UID

GnuPG 将会把你最近添加的 UID 作为你的主 UID,如果这与你想的不同,你应该改回来:

$ gpg --quick-set-primary-uid [fpr] 'Alice Engineer <[email protected]>'

下次,我们将介绍如何生成 PGP 子密钥,它是你实际用于日常工作的密钥。

通过 Linux 基金会和 edX 的免费“Introduction to Linux” 课程了解关于 Linux 的更多信息。


via: https://www.linux.com/blog/learn/PGP/2018/2/protecting-code-integrity-pgp-part-2-generating-and-protecting-your-master-pgp-key

作者:KONSTANTIN RYABITSEV 译者:kimii 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

上一篇文章中我们学习了内核怎么为一个用户进程 管理虚拟内存,而没有提及文件和 I/O。这一篇文章我们将专门去讲这个重要的主题 —— 页面缓存。文件和内存之间的关系常常很不好去理解,而它们对系统性能的影响却是非常大的。

在面对文件时,有两个很重要的问题需要操作系统去解决。第一个是相对内存而言,慢的让人发狂的硬盘驱动器,尤其是磁盘寻道。第二个是需要将文件内容一次性地加载到物理内存中,以便程序间共享文件内容。如果你在 Windows 中使用 进程浏览器 去查看它的进程,你将会看到每个进程中加载了大约 ~15MB 的公共 DLL。我的 Windows 机器上现在大约运行着 100 个进程,因此,如果不共享的话,仅这些公共的 DLL 就要使用高达 ~1.5 GB 的物理内存。如果是那样的话,那就太糟糕了。同样的,几乎所有的 Linux 进程都需要 ld.so 和 libc,加上其它的公共库,它们占用的内存数量也不是一个小数目。

幸运的是,这两个问题都用一个办法解决了:页面缓存 —— 保存在内存中的页面大小的文件块。为了用图去说明页面缓存,我捏造出一个名为 render 的 Linux 程序,它打开了文件 scene.dat,并且一次读取 512 字节,并将文件内容存储到一个分配到堆中的块上。第一次读取的过程如下:

Reading and the page cache

  1. render 请求 scene.dat 从位移 0 开始的 512 字节。
  2. 内核搜寻页面缓存中 scene.dat 的 4kb 块,以满足该请求。假设该数据没有缓存。
  3. 内核分配页面帧,初始化 I/O 请求,将 scend.dat 从位移 0 开始的 4kb 复制到分配的页面帧。
  4. 内核从页面缓存复制请求的 512 字节到用户缓冲区,系统调用 read() 结束。

读取完 12KB 的文件内容以后,render 程序的堆和相关的页面帧如下图所示:

Non-mapped file read

它看起来很简单,其实这一过程做了很多的事情。首先,虽然这个程序使用了普通的读取(read)调用,但是,已经有三个 4KB 的页面帧将文件 scene.dat 的一部分内容保存在了页面缓存中。虽然有时让人觉得很惊奇,但是,普通的文件 I/O 就是这样通过页面缓存来进行的。在 x86 架构的 Linux 中,内核将文件认为是一系列的 4KB 大小的块。如果你从文件中读取单个字节,包含这个字节的整个 4KB 块将被从磁盘中读入到页面缓存中。这是可以理解的,因为磁盘通常是持续吞吐的,并且程序一般也不会从磁盘区域仅仅读取几个字节。页面缓存知道文件中的每个 4KB 块的位置,在上图中用 #0#1 等等来描述。Windows 使用 256KB 大小的 视图 view ,类似于 Linux 的页面缓存中的 页面 page

不幸的是,在一个普通的文件读取中,内核必须拷贝页面缓存中的内容到用户缓冲区中,它不仅花费 CPU 时间和影响 CPU 缓存在复制数据时也浪费物理内存。如前面的图示,scene.dat 的内存被存储了两次,并且,程序中的每个实例都用另外的时间去存储内容。我们虽然解决了从磁盘中读取文件缓慢的问题,但是在其它的方面带来了更痛苦的问题。内存映射文件是解决这种痛苦的一个方法:

Mapped file read

当你使用文件映射时,内核直接在页面缓存上映射你的程序的虚拟页面。这样可以显著提升性能:Windows 系统编程 报告指出,在相关的普通文件读取上运行时性能提升多达 30% ,在 Unix 环境中的高级编程 的报告中,文件映射在 Linux 和 Solaris 也有类似的效果。这取决于你的应用程序类型的不同,通过使用文件映射,可以节约大量的物理内存。

对高性能的追求是永恒不变的目标,测量是很重要的事情,内存映射应该是程序员始终要使用的工具。这个 API 提供了非常好用的实现方式,它允许你在内存中按字节去访问一个文件,而不需要为了这种好处而牺牲代码可读性。在一个类 Unix 的系统中,可以使用 mmap 查看你的 地址空间,在 Windows 中,可以使用 CreateFileMapping.aspx),或者在高级编程语言中还有更多的可用封装。当你映射一个文件内容时,它并不是一次性将全部内容都映射到内存中,而是通过 页面故障 来按需映射的。在 获取 需要的文件内容的页面帧后,页面故障句柄 映射你的虚拟页面 到页面缓存上。如果一开始文件内容没有缓存,这还将涉及到磁盘 I/O。

现在出现一个突发的状况,假设我们的 render 程序的最后一个实例退出了。在页面缓存中保存着 scene.dat 内容的页面要立刻释放掉吗?人们通常会如此考虑,但是,那样做并不是个好主意。你应该想到,我们经常在一个程序中创建一个文件,退出程序,然后,在第二个程序去使用这个文件。页面缓存正好可以处理这种情况。如果考虑更多的情况,内核为什么要清除页面缓存的内容?请记住,磁盘读取的速度要慢于内存 5 个数量级,因此,命中一个页面缓存是一件有非常大收益的事情。因此,只要有足够大的物理内存,缓存就应该保持全满。并且,这一原则适用于所有的进程。如果你现在运行 render 一周后, scene.dat 的内容还在缓存中,那么应该恭喜你!这就是什么内核缓存越来越大,直至达到最大限制的原因。它并不是因为操作系统设计的太“垃圾”而浪费你的内存,其实这是一个非常好的行为,因为,释放物理内存才是一种“浪费”。(LCTT 译注:释放物理内存会导致页面缓存被清除,下次运行程序需要的相关数据,需要再次从磁盘上进行读取,会“浪费” CPU 和 I/O 资源)最好的做法是尽可能多的使用缓存。

由于页面缓存架构的原因,当程序调用 write() 时,字节只是被简单地拷贝到页面缓存中,并将这个页面标记为“脏”页面。磁盘 I/O 通常并不会立即发生,因此,你的程序并不会被阻塞在等待磁盘写入上。副作用是,如果这时候发生了电脑死机,你的写入将不会完成,因此,对于至关重要的文件,像数据库事务日志,要求必须进行 fsync()(仍然还需要去担心磁盘控制器的缓存失败问题),另一方面,读取将被你的程序阻塞,直到数据可用为止。内核采取预加载的方式来缓解这个矛盾,它一般提前预读取几个页面并将它加载到页面缓存中,以备你后来的读取。在你计划进行一个顺序或者随机读取时(请查看 madvise()readahead()Windows 缓存提示.aspx#caching_behavior) ),你可以通过 提示 hint 帮助内核去调整这个预加载行为。Linux 会对内存映射的文件进行 预读取,但是我不确定 Windows 的行为。当然,在 Linux 中它可能会使用 O\_DIRECT 跳过预读取,或者,在 Windows 中使用 NO\_BUFFERING.aspx) 去跳过预读,一些数据库软件就经常这么做。

一个文件映射可以是私有的,也可以是共享的。当然,这只是针对内存中内容的更新而言:在一个私有的内存映射上,更新并不会提交到磁盘或者被其它进程可见,然而,共享的内存映射,则正好相反,它的任何更新都会提交到磁盘上,并且对其它的进程可见。内核使用 写时复制 copy on write (CoW)机制,这是通过 页面表条目 page table entry (PTE)来实现这种私有的映射。在下面的例子中,render 和另一个被称为 render3d 的程序都私有映射到 scene.dat 上。然后 render 去写入映射的文件的虚拟内存区域:

The Copy-On-Write mechanism

  1. 两个程序私有地映射 scene.dat,内核误导它们并将它们映射到页面缓存,但是使该页面表条目只读。
  2. render 试图写入到映射 scene.dat 的虚拟页面,处理器发生页面故障。
  3. 内核分配页面帧,复制 scene.dat 的第二块内容到其中,并映射故障的页面到新的页面帧。
  4. 继续执行。程序就当做什么都没发生。

上面展示的只读页面表条目并不意味着映射是只读的,它只是内核的一个用于共享物理内存的技巧,直到尽可能的最后一刻之前。你可以认为“私有”一词用的有点不太恰当,你只需要记住,这个“私有”仅用于更新的情况。这种设计的重要性在于,要想看到被映射的文件的变化,其它程序只能读取它的虚拟页面。一旦“写时复制”发生,从其它地方是看不到这种变化的。但是,内核并不能保证这种行为,因为它是在 x86 中实现的,从 API 的角度来看,这是有意义的。相比之下,一个共享的映射只是将它简单地映射到页面缓存上。更新会被所有的进程看到并被写入到磁盘上。最终,如果上面的映射是只读的,页面故障将触发一个内存段失败而不是写到一个副本。

动态加载库是通过文件映射融入到你的程序的地址空间中的。这没有什么可奇怪的,它通过普通的 API 为你提供与私有文件映射相同的效果。下面的示例展示了映射文件的 render 程序的两个实例运行的地址空间的一部分,以及物理内存,尝试将我们看到的许多概念综合到一起。

Mapping virtual memory to physical memory

这是内存架构系列的第三部分的结论。我希望这个系列文章对你有帮助,对理解操作系统的这些主题提供一个很好的思维模型。


via:https://manybutfinite.com/post/page-cache-the-affair-between-memory-and-files/

作者:Gustavo Duarte 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在我们之前的 Ansible 教程中,我们讨论了 Ansible 的安装和配置。在这个 Ansible 教程中,我们将学习一些基本的 Ansible 命令的例子,我们将用它来管理基础设施。所以让我们先看看一个完整的 Ansible 命令的语法:

$ ansible <group> -m <module> -a <arguments>

在这里,我们可以用单个主机或用 <group> 代替一组主机,<arguments> 是可选的参数。现在我们来看看一些 Ansible 的基本命令。

检查主机的连通性

我们在之前的教程中也使用了这个命令。检查主机连接的命令是:

$ ansible <group> -m ping

重启主机

$ ansible <group> -a "/sbin/reboot"

检查主机的系统信息

Ansible 收集所有连接到它主机的信息。要显示主机的信息,请运行:

$ ansible <group> -m setup | less

其次,通过传递参数来从收集的信息中检查特定的信息:

$ ansible <group> -m setup -a "filter=ansible_distribution"

传输文件

对于传输文件,我们使用模块 copy ,完整的命令是这样的:

$ ansible <group> -m copy -a "src=/home/dan dest=/tmp/home"

管理用户

要管理已连接主机上的用户,我们使用一个名为 user 的模块,并如下使用它。

创建新用户

$ ansible <group> -m user -a "name=testuser password=<encrypted password>"

删除用户

$ ansible <group> -m user -a "name=testuser state=absent"

注意: 要创建加密密码,请使用 "mkpasswd -method=sha-512"

更改权限和所有者

要改变已连接主机文件的所有者,我们使用名为 file 的模块,使用如下。

更改文件权限

$ ansible <group> -m file -a "dest=/home/dan/file1.txt mode=777"

更改文件的所有者

$ ansible <group> -m file -a "dest=/home/dan/file1.txt mode=777 owner=dan group=dan"

管理软件包

我们可以通过使用 yumapt 模块来管理所有已连接主机的软件包,完整的命令如下:

检查包是否已安装并更新

$ ansible <group> -m yum -a "name=ntp state=latest"

检查包是否已安装,但不更新

$ ansible <group> -m yum -a "name=ntp state=present"

检查包是否是特定的版本

$ ansible <group> -m yum -a "name= ntp-1.8 state=present"

检查包是否没有安装

$ ansible <group> -m yum -a "name=ntp state=absent"

管理服务

要管理服务,我们使用模块 service ,完整命令如下:

启动服务

$ansible <group> -m service -a "name=httpd state=started"

停止服务

$ ansible <group> -m service -a "name=httpd state=stopped"

重启服务

$ ansible <group> -m service -a "name=httpd state=restarted"

这样我们简单的、单行 Ansible 命令的教程就完成了。此外,在未来的教程中,我们将学习创建 playbook,来帮助我们更轻松高效地管理主机。


via: http://linuxtechlab.com/ansible-tutorial-simple-commands/

作者:SHUSAIN 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

让我们了解一下如何使国外读者更容易理解你的技术文章。

英语是开源社区的通用语言。为了减少翻译成本,很多团队都改成用英语来写他们的文档。 但奇怪的是,为国际读者写英语并不一定就意味着以英语为母语的人就占据更多的优势。 相反, 他们往往忘记了该文档用的语言可能并不是读者的母语。

我们以下面这个简单的句子为例: “Encrypt the password using the foo bar command。”语法上来说,这个句子是正确的。 鉴于动名词的 “-ing” 形式在英语中很常见,大多数的母语人士都认为这是一种优雅的表达方式, 他们通常会很自然的写出这样的句子。 但是仔细观察, 这个句子存在歧义因为 “using” 可能指的宾语(“the password”)也可能指的动词(“encrypt”)。 因此这个句子有两种解读方式:

  • “加密使用了 foo bar 命令的密码。”
  • “使用命令 foo bar 来加密密码。”

如果你有相关的先验知识(密码加密或者 foo bar 命令),你可以消除这种不确定性并且明白第二种方式才是真正的意思。 但是若你没有足够深入的知识怎么办呢? 如果你并不是这方面的专家,而只是一个拥有泛泛相关知识的翻译者而已怎么办呢? 再或者,如果你只是个非母语人士且对像动名词这种高级语法不熟悉怎么办呢?

即使是英语为母语的人也需要经过训练才能写出清晰直接的技术文档。训练的第一步就是提高对文本可用性以及潜在问题的警觉性, 下面让我们来看一下可以帮助避免常见陷阱的 7 条规则。

1、了解你的目标读者并代入其中。

如果你是一名开发者,而写作的对象是最终用户, 那么你需要站在他们的角度来看这个产品。 文档的结构是否反映了用户的目标? 人格面具 persona 技术) 能帮你专注于目标受众并为你的读者提供合适层次的细节。

2、遵循 KISS 原则——保持文档简短而简单

这个原则适用于多个层次,从语法,句子到单词。 比如:

  • 使用合适的最简单时态。比如, 当提到一个动作的结果时使用现在时:

    • " Click 'OK.' The 'Printer Options' dialog will appear. " -> "Click 'OK.' The 'Printer Options' dialog appears."
  • 按经验来说,一个句子表达一个主题;然而, 短句子并不一定就容易理解(尤其当这些句子都是由名词组成时)。 有时, 将句子裁剪过度可能会引起歧义,而反过来太多单词则又难以理解。
  • 不常用的以及很长的单词会降低阅读速度,而且可能成为非母语人士的障碍。 使用更简单的替代词语:

    • " utilize " -> "use"
    • " indicate " -> "show","tell" 或 "say"
    • " prerequisite " -> "requirement"

3、不要干扰阅读流

将虚词和较长的插入语移到句子的首部或者尾部:

  • " They are not, however, marked as installed. " -> "However, they are not marked as installed."

将长命令放在句子的末尾可以让自动/半自动的翻译拥有更好的断句。

4、区别对待两种基本的信息类型

描述型信息以及任务导向型信息有必要区分开来。描述型信息的一个典型例子就是命令行参考, 而 HOWTO 则是属于基于任务的信息;(LCTT 译注:HOWTO 文档是 Linux 文档中的一种)然而, 技术写作中都会涉及这两种类型的信息。 仔细观察, 就会发现许多文本都同时包含了两种类型的信息。 然而如果能够清晰地划分这两种类型的信息那必是极好的。 为了更好地区分它们,可以对它们进行分别标记。 标题应该能够反映章节的内容以及信息的类型。 对描述性章节使用基于名词的标题(比如“Types of Frobnicators”),而对基于任务的章节使用口头表达式的标题(例如“Installing Frobnicators”)。 这可以让读者快速定位感兴趣的章节而跳过对他无用的章节。

5、考虑不同的阅读场景和阅读模式

有些读者在阅读产品文档时会由于自己搞不定而感到十分的沮丧。他们在一个嘈杂的环境中工作,也很难专注于阅读。 同时,不要期望你的读者会一页一页的进行阅读,很多人都是快速浏览文本,搜索关键字或者通过表格、索引以及全文搜索的方式来查找主题。 请牢记这一点, 从不同的角度来看待你的文字。 通常需要折中才能找到一种适合多种情况的文本结构。

6、将复杂的信息分成小块

这会让读者更容易记住和吸收信息。例如, 过程不应该超过 7 到 10 个步骤(根据认知心理学中的 米勒法则)。 如果需要更多的步骤, 那么就将任务分拆成不同的过程。

7、形式遵循功能

根据以下问题检查你的文字:某句话/段落/章节的 目的(功能)是什么?比如,它是一个指令呢?还是一个结果呢?还是一个警告呢?如果是指令, 使用主动语气: “Configure the system.” 被动语气可能适合于进行描述: “The system is configured automatically.” 将警告放在危险操作的 前面 。 专注于目的还有助于发现冗余的内容,可以清除类似 “basically” 或者 “easily” 这一类的填充词,类似 “already existing ” 或“ completely new” 这一类的不必要的修饰, 以及任何与你的目标大众无关的内容。

你现在可能已经猜到了,写作就是一个不断重写的过程。 好的写作需要付出努力和练习。 即使你只是偶尔写点东西, 你也可以通过关注目标大众并遵循上述规则来显著地改善你的文字。 文字的可读性越好, 理解就越容易, 这一点对不同语言能力的读者来说都是适合的。 尤其是当进行本地化时, 高质量的原始文本至关重要:“垃圾进, 垃圾出”。 如果原始文本就有缺陷, 翻译所需要的时间就会变长, 从而导致更高的成本。 最坏的情况下, 翻译会导致缺陷成倍增加,需要在不同的语言版本中修正这个缺陷。


via: https://opensource.com/article/17/12/7-rules

作者:Tanja Roth 译者:lujun9972 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Facebook 开发人员 Christine Abernathy 讨论了开源如何帮助公司分享见解并推动创新。

开源逐年变得无处不在,从政府直辖市大学都有。各种规模的公司也越来越多地转向开源软件。事实上,一些公司正在通过财务支持项目或与开发人员合作进一步推进开源。

例如,Facebook 的开源计划鼓励其他人开源发布他们的代码,同时与社区合作支持开源项目。 Christine Abernathy,是一名 Facebook 开发者、开源支持者,也是该公司开源团队成员,去年 11 月访问了罗切斯特理工学院,在 11 月 的 FOSS 系列演讲中发表了演讲。在她的演讲中,Abernathy 解释了 Facebook 如何开源以及为什么它是公司所做工作的重要组成部分。

Facebook 和开源

Abernathy 说,开源在 Facebook 创建社区并使世界更加紧密的使命中扮演着重要的角色。这种意识形态的匹配是 Facebook 参与开源的一个激励因素。此外,Facebook 面临着独特的基础设施和开发挑战,而开源则为公司提供了一个平台,以共享可帮助他人的解决方案。开源还提供了一种加速创新和创建更好软件的方法,帮助工程团队生产更好的软件并更透明地工作。今天,Facebook 在 GitHub 的 443 个项目有 122,000 个分支、292,000 个提交和 732,000 个关注。

 title=

一些以开源方式发布的 Facebook 项目包括 React、GraphQL、Caffe2 等等。(图片提供:Christine Abernathy 图片,经许可使用)

得到的教训

Abernathy 强调说 Facebook 已经从开源社区吸取了很多教训,并期待学到更多。她明确了三个最重要的:

  • 分享有用的东西
  • 突出你的英雄
  • 修复常见的痛点

Christine Abernathy 作为 FOSS 演讲系列的嘉宾一员参观了 RIT。每个月,来自开源世界的演讲嘉宾都会与对自由和开源软件感兴趣的学生分享关于开源世界智慧、见解、建议。 FOSS @MAGIC社区感谢 Abernathy 作为演讲嘉宾出席。

关于作者

Justin 是罗切斯特理工学院主修网络与系统管理的学生。他目前是 Fedora Project 的贡献者。在 Fedora 中,Justin 是 Fedora Magazine 的主编,社区的领导...


via: https://opensource.com/article/18/1/inside-facebooks-open-source-program

作者:Justin W. Flory 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在本系列文章中,我们将深度探讨如何使用 PGP 确保软件完整性。这些文章将为工作于自由软件项目的开发者提供实用指南,并且将包含以下主题:

  1. PGP 基础和最佳实践
  2. 如何用 Git 使用 PGP
  3. 如何保护你的开发者账户

我们使用与“Freedom”含义相同的词项 “Free”,但这个系列中列出的指南也可以被任何其它类型的依赖于分布式团队开发者贡献的软件中。如果你编写进入公共源仓库的代码,你可以从了解和遵循这篇指南中受益。

结构

每节分为两个部分:

  • 适用于你项目需求的清单
  • 形式自由的考虑事项的列表,解释这些决定取决于什么,并伴随着配置指令

清单优先级

每个清单中各项包含着优先级,用来帮助指导你的决定:

  • (必要)该项一定要排在考虑事项列表的前面。如果没有这样做,它们将给提交到开源项目中的代码带来高风险。
  • (推荐)包含该项将提升整体安全性,但会影响你与工作环境的交互方式,并且可能需要学习新的习惯或者放弃旧的习惯。

记住,这些只是指导。如果你感到这些优先级不能反映你项目提交的安全,你应该根据自己的需要调整它们。

PGP 基本概念和工具

清单

  1. 理解 PGP 在自由软件开发中的作用 (必要)
  2. 理解 公钥密码学 Public Key Cryptography 的基础知识 (必要)
  3. 理解 PGP 加密和签名的不同 (必要)
  4. 理解 PGP 密钥身份 key identities (必要)
  5. 理解 PGP 密钥有效性 key validity (必要)
  6. 安装 GnuPG 工具(版本 2.x) (必要)

考虑事项

自由软件社区长期依赖于 PGP 确保它生产的软件产品的真实性和完整性。你可能没有注意到,但无论你是一个 Linux 、Mac 和 Windowas 用户,你都曾依赖 PGP 来确保你电脑环境的完整性:

  • Linux 发行版依赖 PGP 来确保当二进制或者原代码包从被生产出来到被终端用户安装之间没被更改过
  • 自由软件项目通常会伴随发行软件的存档提供分离的 PGP 签名,使得下游的项目可以在把下载的版本集成到自己的分布式下载之前,验证下载版本的完整性。
  • 自由软件项目通常依赖代码本身的 PGP 签名来跟踪起源,并验证项目开发者提交的代码的完整性

这与工作于专有平台的程序员使用的开发者证书或代码签名机制非常相似。实际上,这两种技术背后的核心概念非常相似 —— 尽管它们在实现的技术层面和它们委托信任方式的大多不同。PGP 不依赖于集中式认证机构,而是让每个用户为每个证书赋予自己的信任。

我们的目标是使你的项目通过使用 PGP 来进行代码起源和完整性追踪,遵循最佳实践并遵守基本的安全预防措施。

极其基本的 PGP 操作概括

你不需要知道 PGP 如何工作的具体细节 —— 理解核心概念足以成功地达到我们的目的。PGP 依赖于公钥密码学来将明文转换为密文。这个过程需要两种不同的密钥:

  • 公钥,被所有人知道
  • 私钥,只被拥有者知道
加密

对加密来说,PGP 使用拥有者的公钥创造一条只能通过拥有者私钥解密的消息:

  1. 发送者生成一个随机的加密密钥(“会话密钥”)
  2. 发送者使用该会话密钥(使用对称算法)加密内容
  3. 发送者使用接收者的 PGP 公钥加密会话密钥
  4. 发送者向接收者发送加密后的内容和加密后的会话密钥

要解密:

  1. 接收者使用他们的 PGP 私钥解密会话密钥
  2. 接收者使用会话密钥解密消息的内容
签名

为了创建签名,PGP 私钥或公钥会以相反的方式使用:

  1. 签名者生成内容的校检和哈希
  2. 签名者使用自己的 PGP 私钥来加密该校检和
  3. 签名者伴随内容提供加密后的校检和

要验证签名:

  1. 验证者生成自己的内容校检和哈希
  2. 验证者使用签名者的 PGP 公钥来解密提供的校检和
  3. 如果校检和匹配,就验证了内容的完整性
结合使用

通常,加密消息也被发送者自己的 PGP 密钥签名。无论何时使用加密消息,这应当是默认的,因为没有认证的加密没有很大意义(除非你是一个告密者或秘密代理并且需要可行的可否认性)

理解密钥身份

每个 PGP 密钥必须有一个或多个与之关联的身份。通常,“ 身份 Identity ”指的是以下格式中的人物全名和邮件地址:

Alice Engineer <[email protected]>

有时也会在括号中包含说明,来告诉终端用户关于该特定密钥的更多信息:

Bob Designer (obsolete 1024-bit key) <[email protected]>

由于人们可以和多个职业和个人实体相关联,因此在同一密钥上可以有多个身份:

Alice Engineer <[email protected]>
Alice Engineer <[email protected]>
Alice Engineer <[email protected]>

当使用多个身份时,其中之一将被标记为“ primary identity 主要身份 ”来让检索更简单。

理解密钥有效性

为了能使用其他人的公钥来加密或验证,你需要确保它确实属于正确的人(Alice)而不属于冒牌的(Eve)。在 PGP 中,这被称为“密钥有效性”:

  • 有效性: 完全 full -- 意味着非常确认该密钥属于 Alice
  • 有效性: 临界 marginal -- 意味着大致确认该密钥属于 Alice
  • 有效性: 未知 unknown -- 意味着不确认该密钥是否属于 Alice

Web of Trust (WOT) 与 Trust on First Use (TOFU)

PGP 使用了一种信任委托机制叫“Web of Trust”。它的核心是尝试替代 HTTPS/TLS 世界中对集中式认证机构的需求。PGP 把这个责任交给了每个用户,而不是各种软件开发商来决定谁应该是你的可信认证实体。

不幸的是,很少有人理解 Web of Trust 的是如何工作的,能使用它的人更少。它仍然是 OpenPGP 规范的一个重要方面,但 GnuPG 的近期版本(2.2 及以上)已经实现了一种替代机制叫“Trust on First Use”(TOFU)。

你可以把 TOFU 当作类似 SSH 的信任方式。使用 SSH,当你第一次连接到远程系统,它的密钥指纹会被记录和保存。如果将来密钥改变,SSH 客户端将会提醒你并拒绝连接,迫使你决定是否信任已改变的的密钥。

同样,当你第一次导入某人的 PGP 密钥,它被假定可信。如果在将来的任何时候,GnuPG 碰巧发现另一同样身份的密钥,过去导入的密钥和新密钥都将被标记为无效,并且你需要手动指出保留哪个。

安装 OpenPGP 软件

首先,理解 PGP、OpenPGP、GnuPG 和 gpg 之间的不同很重要:

  • PGP (“Pretty Good Privacy”) 是最初商业软件的名字
  • OpenPGP 是与最初 PGP 工具兼容的 IETF 标准
  • GnuPG (“Gnu Privacy Guard”)是实现了 OpenPGP 标准的自由软件
  • GnuPG 的命令行工具称为 “gpg”

今天,“PGP”这个词几乎被普遍用来表示开放的 OpenPGP 标准,而不是最初的商业软件,因此“PGP”和“OpenPGP”是可以互换的。“GnuPG”和“pgp”这两个词应该仅在提及工具时使用,而不用于它们产生的输出或它们实现的 OpenPGP 功能。举例:

  • PGP(而非 GnuPG 或 GPG)密钥
  • PGP(而非 GnuPG 或 GPG)签名
  • PGP(而非 GnuPG 或 GPG)密钥服务器

理解这一点应该可以保护你免受来自你遇到的其他 PGP 用户“实际上”不可避免的迂腐。

安装 GnuPG

如果你正在使用 Linux,你应该已经安装过了 GnuPG。在 Mac 上,你应该安装 GPG-Suite,或者使用 brew 安装 gnupg2。在 Windows 上,你应该安装 GPG4Win,并且为了可以工作,你可能需要调整指南中的部分命令,除非你设置了类似 Unix 的环境。对其他平台来说,你需要自行查找正确的地址来下载和安装 GnuPG。

GnuPG 1 vs. 2

GnuPG v.1 和 GnuPG v.2 都实现了同样的标准,但它们提供不兼容的库和命令行工具,所以许多发行版都带有了旧的版本 1 和最新的版本 2。你需要确保你总是使用 GnuPG v.2。

首先,运行:

$ gpg --version | head -n1

如果你看到 gpg (GnuPG) 1.4.x,说明你正使用 GnuPG v.1。尝试下 gpg2 命令:

$ gpg2 --version | head -n1

如果你看到 gpg (GnuPG) 2.x.x,说明你可以继续了。这篇指南将假设你使用 GnuPG 2.2 版本(或更新)。如果你正使用 GnuPG 的 2.0 版本,本指南中某些命令可能无效,你应该考虑安装 GnuPG 最新的 2.2 版本

确保你总是使用 GnuPG v.2

如果你 gpggpg2 命令都有,你应该确保总是使用 GnuPG v.2,而不是旧的版本。你可以通过设置别名来确保这一点:

$ alias gpg=gpg2

你可以把它放在你的 .bashrc 中,以确保它在你使用 gpg 命令时总是被加载。

在本系列的第 2 部分中,我们将介绍生成和保护你的 PGP 主密钥的基本步骤。

通过 Linux 基金会和 edX 的免费“Introduction to Linux” 课程了解关于 Linux 的更多信息。


via: https://www.linux.com/blog/learn/2018/2/protecting-code-integrity-pgp-part-1-basic-pgp-concepts-and-tools

作者:Konstantin Ryabitsev 译者:kimii 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出