2020年1月

告诉我们你最喜欢的终端技巧,无论是提高生产率的快捷方式还是有趣的彩蛋。

新年伊始始终是评估提高效率的新方法的好时机。许多人尝试使用新的生产力工具,或者想找出如何优化其最常用的流程。终端是一个需要评估的领域,尤其是在开源世界中,有无数种方法可以通过快捷键和命令使终端上的生活更加高效(又有趣!)。

我们向作者们询问了他们最喜欢的终端技巧。他们分享了一些节省时间的技巧,甚至还有一个有趣的终端彩蛋。你会采用这些键盘快捷键或命令行技巧吗?你有喜欢分享的最爱吗?请发表评论来告诉我们。

“我找不出哪个是我最喜欢的;每天我都会使用这三个:

  • Ctrl + L 来清除屏幕(而不是键入 clear)。
  • sudo !!sudo 特权运行先前的命令。
  • grep -Ev '^#|^$' <file> 将显示文件内容,不带注释或空行。” —Mars Toktonaliev

“对我来说,如果我正在使用终端文本编辑器,并且希望将其丢开,以便可以快速执行其他操作,则可以使用 Ctrl + Z 将其放到后台,接着执行我需要做的一切,然后用 fg 将其带回前台。有时我也会对 tophtop 做同样的事情。我可以将其丢到后台,并在我想检查当前性能时随时将其带回前台。我不会将通常很快能完成的任务在前后台之间切换,它确实可以增强终端上的多任务处理能力。” —Jay LaCroix

“我经常在某一天在终端中做很多相同的事情,有两件事是每天都不变的:

  • Ctrl + R 反向搜索我的 Bash 历史记录以查找我已经运行并且希望再次执行的命令。
  • 插入号(^)替换是最好的,因为我经常做诸如 sudo dnf search <package name> 之类的事情,然后,如果我以这种方式找到合适的软件包,则执行 ^search^install 来重新运行该命令,以 install 替换 search

这些东西肯定是很基本的,但是对我来说却节省了时间。” —Steve Morris

“我的炫酷终端技巧不是我在终端上执行的操作,而是我使用的终端。有时候我只是想要使用 Apple II 或旧式琥珀色终端的感觉,那我就启动了 Cool-Retro-Term。它的截屏可以在这个网站上找到。” —Jim Hall

“可能是用 ssh -X 来在其他计算机上运行图形程序。(在某些终端仿真器上,例如 gnome-terminal)用 C-S cC-S v 复制/粘贴。我不确定这是否有价值(因为它有趣的是以 ssh 启动的图形化)。最近,我需要登录另一台计算机,但是我的孩子们可以在笔记本电脑的大屏幕上看到它。这个链接向我展示了一些我从未见过的内容:通过局域网从我的笔记本电脑上镜像来自另一台计算机屏幕上的活动会话(x11vnc -desktop),并能够同时从两台计算机上进行控制。” —Kyle R. Conway

“你可以安装 sl$ sudo apt install sl$ sudo dnf install sl),并且当在 Bash 中输入命令 sl 时,一个基于文本的蒸汽机车就会在显示屏上移动。” —Don Watkins


via: https://opensource.com/article/20/1/linux-terminal-trick

作者:Opensource.com 选题:lujun9972 译者:wxy 校对:wxy

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

请阅读我们的热门文章,这些文章着重讨论了敏捷的过去、现在和未来。

对于 Opensource.com 上的敏捷主题来说,2019 年是非常棒的一年。随着 2020 年的到来,我们回顾了我们读者所读的与敏捷相关的热门文章。

小规模 Scrum 指南

Opensource.com 关于小规模 Scrum 的指南(我曾参与合著)由六部分组成,为小型团队提供了关于如何将敏捷引入到他们的工作中的建议。在官方的 Scrum 指南的概述中,传统的 Scrum 框架推荐至少三个人来实现,以充分发挥其潜力。但是,它并没有为一两个人的团队如何成功遵循 Scrum 提供指导。我们的六部分系列旨在规范化小规模的 Scrum,并检验我们在现实世界中使用它的经验。该系列受到了读者的热烈欢迎,以至于这六篇文章占据了前 10 名文章的 60%。因此,如果你还没有阅读的话,一定要从我们的小规模 Scrum 介绍页面下载。

全面的敏捷项目管理指南

遵循传统项目管理方法的团队最初对敏捷持怀疑态度,现在已经热衷于敏捷的工作方式。目前,敏捷已被接受,并且一种更加灵活的混合风格已经找到了归宿。Matt Shealy 撰写的有关敏捷项目管理的综合指南涵盖了敏捷项目管理的 12 条指导原则,对于希望为其项目带来敏捷性的传统项目经理而言,它是完美的选择。

成为出色的敏捷开发人员的 4 个步骤

DevOps 文化已经出现在许多现代软件团队中,这些团队采用了敏捷软件开发原则,利用了最先进的工具和自动化技术。但是,这种机械的敏捷方法并不能保证开发人员在日常工作中遵循敏捷实践。Daniel Oh 在成为出色的敏捷开发人员的 4 个步骤中给出了一些很棒的技巧,通过关注设计思维,使用可预测的方法,以质量为中心并不断学习和探索来提高你的敏捷性。用你的敏捷工具补充这些方法将形成非常灵活和强大的敏捷开发人员。

Scrum 和 kanban:哪种敏捷框架更好?

对于以敏捷方式运行的团队来说,Scrum 和 kanban 是两种最流行的方法。在 “Scrum 与 kanban:哪种敏捷框架更好?” 中,Taz Brown 探索了两者的历史和目的。在阅读本文时,我想起一句名言:“如果你的工具箱里只有锤子,那么所有问题看起来都像钉子。”知道何时使用 kanban 以及何时使用 Scrum 非常重要,本文有助于说明两者都有一席之地,这取决于你的团队、挑战和目标。

开发人员对敏捷发表意见的 4 种方式

当采用敏捷的话题出现时,开发人员常常会担心自己会被强加上一种工作风格。在“开发人员对敏捷发表意见的 4 种方式”中,Clément Verna 着眼于开发人员通过帮助确定敏捷在其团队中的表现形式来颠覆这种说法的方法。检查敏捷的起源和基础是一个很好的起点,但是真正的价值在于拥有可帮助指导你的过程的指标。知道你将面临什么样的挑战会给你的前进提供坚实的基础。根据经验进行决策不仅可以增强团队的能力,还可以使他们对整个过程有一种主人翁意识。Verna 的文章还探讨了将人置于过程之上并作为一个团队来实现目标的重要性。

敏捷的现在和未来

今年,Opensource.com 的作者围绕敏捷的过去、现在以及未来可能会是什么样子进行了大量的讨论。感谢他们所有人,请一定于 2020 年在这里分享你自己的敏捷故事


via: https://opensource.com/article/19/12/agile-resources

作者:Leigh Griffin 选题:lujun9972 译者:algzjh 校对:wxy

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

我们让社区讲述他们在终端仿真器方面的经验。以下是我们收到的一些回复。

终端仿真器的偏好可以说明一个人的工作流程。无鼠标操作能力是否必须具备?你想要标签页还是窗口?对于终端仿真器你还有什么选择的原因?是否有酷的因素?欢迎参加调查或给我们留下评论,告诉我们你最喜欢的终端模拟器。你尝试过多少种终端仿真器呢?

我们让社区讲述他们在终端仿真器方面的经验。以下是我们收到的一些回复。

“我最喜欢的终端仿真器是用 Powerline 定制的 Tilix。我喜欢它支持在一个窗口中打开多个终端。” —Dan Arel

urxvt。它可以通过文件简单配置,轻巧,并且在大多数程序包管理器存储库中都很容易找到。” —Brian Tomlinson

“即使我不再使用 GNOME,gnome-terminal 仍然是我的首选。:)” —Justin W. Flory

“现在 FC31 上的 Terminator。我刚刚开始使用它,我喜欢它的分屏功能,对我来说感觉很轻巧。我正在研究它的插件。” —Marc Maxwell

“不久前,我切换到了 Tilix,它完成了我需要终端执行的所有工作。:) 多个窗格、通知,很精简,用来运行我的 tmux 会话很棒。” —Kevin Fenzi

“alacritty。它针对速度进行了优化,是用 Rust 实现的,并且具有很多常规功能,但是老实说,我只关心一个功能:可配置的字形间距,使我可以进一步压缩字体。” —Alexander Sosedkin “我是个老古板:KDE Konsole。如果是远程会话,请使用 tmux。” —Marcin Juszkiewicz

“在 macOS 上用 iTerm2。是的,它是开源的。:-) 在 Linux 上是 Terminator。” —Patrick Mullins

“我现在已经使用 alacritty 一两年了,但是最近我在全屏模式下使用 cool-retro-term,因为我必须运行一个输出内容有很多的脚本,而它看起来很酷,让我感觉很酷。这对我很重要。” —Nick Childers

“我喜欢 Tilix,部分是因为它擅长免打扰(我通常全屏运行它,里面是 tmux),而且还提供自定义热链接支持:在我的终端中,像 ‘rhbz#1234’ 之类的文本是将我带到 Bugzilla 的热链接。类似的还有 LaunchPad 提案,OpenStack 的 Gerrit 更改 ID 等。” —Lars Kellogg-Stedman

“Eterm,在使用 Vintage 配置文件的 cool-retro-term 中,演示效果也最好。” —Ivan Horvath

“Tilix +1。这是 GNOME 用户最好的选择,我是这么觉得的!” —Eric Rich

“urxvt。快速、小型、可配置、可通过 Perl 插件扩展,这使其可以无鼠标操作。” —Roman Dobosz

“Konsole 是最好的,也是 KDE 项目中我唯一使用的应用程序。所有搜索结果都高亮显示是一个杀手级功能,据我所知没有任何其它 Linux 终端有这个功能(如果能证明我错了,那我也很高兴)。最适合搜索编译错误和输出日志。” —Jan Horak

“我过去经常使用 Terminator。现在我在 Tilix 中克隆了它的主题(深色主题),而感受一样好。它可以在选项卡之间轻松移动。就是这样。” —Alberto Fanjul Alonso

“我开始使用的是 Terminator,自从差不多过去这三年,我已经完全切换到 Tilix。” —Mike Harris

“我使用下拉式终端 X。这是 GNOME 3 的一个非常简单的扩展,使我始终可以通过一个按键(对于我来说是F12)拉出一个终端。它还支持制表符,这正是我所需要的。 ” —Germán Pulido

“xfce4-terminal:支持 Wayland、缩放、无边框、无标题栏、无滚动条 —— 这就是我在 tmux 之外全部想要的终端仿真器的功能。我希望我的终端仿真器可以尽可能多地使用屏幕空间,我通常在 tmux 窗格中并排放着编辑器(Vim)和 repl。” —Martin Kourim

“别问,问就是 Fish ! ;-)” —Eric Schabell


via: https://opensource.com/article/19/12/favorite-terminal-emulator

作者:Opensource.com 选题:lujun9972 译者:wxy 校对:wxy

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

总有这样的时候:有时你需要禁用某位 Linux 用户的账号,有时你还需要反过来解禁用户的账号。 本文将介绍一些管理用户访问的命令,并介绍它们背后的原理。

假如你正管理着一台 Linux 系统,那么很有可能将遇到需要禁用一个账号的情况。可能是某人已经换了职位,他们是否还需要该账号仍是个问题;或许有理由相信再次使用该账号并没有大碍。不管上述哪种情况,知晓如何禁用账号并解禁账号都是你需要知道的知识。

需要你记住的一件重要的事是尽管有多种方法来禁用账号,但它们并不都达到相同的效果。假如用户使用公钥/私钥来使用该账号而不是使用密码来访问,那么你使用的某些命令来阻止用户获取该账号或许将不会生效。

使用 passwd 来禁用一个账号

最为简单的用来禁用一个账号的方法是使用 passwd -l 命令。例如:

$ sudo passwd -l tadpole

上面这个命令的效果是在加密后的密码文件 /etc/shadow 中,用户对应的那一行的最前面加上一个 ! 符号。这样就足够阻止用户使用密码来访问账号了。

在没有使用上述命令前,加密后的密码行如下所示(请注意第一个字符):

$6$IC6icrWlNhndMFj6$Jj14Regv3b2EdK.8iLjSeO893fFig75f32rpWpbKPNz7g/eqeaPCnXl3iQ7RFIN0BGC0E91sghFdX2eWTe2ET0:18184:0:99999:7:::

而禁用该账号后,这一行将变为:

!$6$IC6icrWlNhndMFj6$Jj14Regv3b2EdK.8iLjSeO893fFig75f32rpWpbKPNz7g/eqeaPCnXl3iQ7RFIN0BGC0E91sghFdX2eWTe2ET0:18184:0:99999:7:::

在 tadpole 下一次尝试登录时,他可能会使用他原有的密码来尝试多次登录,但就是无法再登录成功了。另一方面,你则可以使用下面的命令来查看他这个账号的状态(-S = status):

$ sudo passwd -S tadpole
tadpole L 10/15/2019 0 99999 7 -1

第二项的 L 告诉你这个账号已经被禁用了。在该账号被禁用前,这一项应该是 P。如果显示的是 NP 则意味着该账号还没有设置密码。

命令 usermod -L 也具有相同的效果(添加 ! 来禁用账号的使用)。

使用这种方法来禁用某个账号的一个好处是当需要解禁某个账号时非常容易。只需要使用一个文本编辑器或者使用 passwd -u 命令来执行相反的操作,即将添加的 ! 移除即可。

$ sudo passwd -u tadpole
passwd: password expiry information changed.

但使用这种方式的问题是如果用户使用公钥/私钥对的方式来访问他/她的账号,这种方式将不能阻止他们使用该账号。

使用 chage 命令来禁用账号

另一种禁用用户账号的方法是使用 chage 命令,它可以帮助管理用户账号的过期日期。

$ sudu chage -E0 tadpole
$ sudo passwd -S tadpole
tadpole P 10/15/2019 0 99999 7 -1

chage 命令将会稍微修改 /etc/shadow 文件。在这个使用 : 来分隔的文件(下面将进行展示)中,某行的第 8 项将被设置为 0(先前为空),这就意味着这个账号已经过期了。chage 命令会追踪密码更改期间的天数,通过选项也可以提供账号过期信息。第 8 项如果是 0 则意味着这个账号在 1970 年 1 月 1 日后的一天过期,当使用上面显示的那个命令时可以用来禁用账号。

$ sudo grep tadpole /etc/shadow | fold
tadpole:$6$IC6icrWlNhndMFj6$Jj14Regv3b2EdK.8iLjSeO893fFig75f32rpWpbKPNz7g/eqeaPC
nXl3iQ7RFIN0BGC0E91sghFdX2eWTe2ET0:18184:0:99999:7::0:
                                                    ^
                                                    |
                                                    +--- days until expiration

为了执行相反的操作,你可以简单地使用下面的命令将放置在 /etc/shadow 文件中的 0 移除掉:

% sudo chage -E-1 tadpole

一旦一个账号使用这种方式被禁用,即便是无密码的 SSH 登录也不能再访问该账号了。


via: https://www.networkworld.com/article/3513982/locking-and-unlocking-accounts-on-linux-systems.html

作者:Sandra Henry-Stocker 选题:lujun9972 译者:FSSlc 校对:wxy

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

保存和共享日历可能会有点麻烦。在我们的 20 个使用开源提升生产力的系列的第五篇文章中了解如何让它更简单。

去年,我在 19 天里给你介绍了 19 个新(对你而言)的生产力工具。今年,我换了一种方式:使用你在使用或者还没使用的工具,构建一个使你可以在新一年更加高效的环境。

使用 khal 和 vdirsyncer 跟踪你的日程

处理日历很麻烦,要找到好的工具总是很困难的。但是自从我去年将日历列为我的“失败"之一以来,我已经取得了一些进步。

目前使用日历最困难的是一直需要以某种方式在线共享。两种最受欢迎的在线日历是 Google Calendar 和 Microsoft Outlook/Exchange。两者都在公司环境中大量使用,这意味着我的日历必须支持其中之一或者两个。

 title=

Khal 是基于控制台的日历,可以读取和写入 VCalendar 文件。它配置相当容易,但是不支持与其他应用同步。

幸运的是,khal 能与 vdirsyncer 一起使用,它是一个漂亮的命令行程序,可以将在线日历(和联系人,我将在另一篇文章中讨论)同步到本地磁盘。是的,它还可以上传新事件。

 title=

Vdirsyncer 是个 Python 3 程序,可以通过软件包管理器或 pip 安装。它可以同步 CalDAV、VCalendar/iCalendar、Google Calendar 和目录中的本地文件。由于我使用 Google Calendar,尽管这不是最简单的设置,我也将以它为例。

在 vdirsyncer 中设置 Google Calendar 是有文档参考的,所以这里我不再赘述。重要的是确保设置你的同步对,将 Google Calendar 设置为冲突解决的“赢家”。也就是说,如果同一事件有两个更新,那么需要知道哪个更新优先。类似这样做:

[general]
status_path = "~/.calendars/status"

[pair personal_sync]
a = "personal"
b = "personallocal"
collections = ["from a", "from b"]
conflict_resolution = "a wins"
metadata = ["color"]

[storage personal]
type = "google_calendar"
token_file = "~/.vdirsyncer/google_calendar_token"
client_id = "google_client_id"
client_secret = "google_client_secret"

[storage personallocal]
type = "filesystem"
path = "~/.calendars/Personal"
fileext = ".ics"

在第一次 vdirsyncer 同步之后,你将在存储路径中看到一系列目录。每个文件夹都将包含多个文件,日历中的每个事件都是一个文件。下一步是导入 khal。首先运行 khal configure 进行初始设置。

 title=

现在,运行 khal interactive 将显示本文开头的界面。输入 n 将打开“新事件”对话框。这里要注意的一件事:日历的名称与 vdirsyncer 创建的目录匹配,但是你可以更改 khal 配置文件来指定更清晰的名称。根据条目所在的日历,向条目添加颜色还可以帮助你确定日历内容:

[calendars]
[[personal]]
path = ~/.calendars/Personal/[email protected]/
color = light magenta
[[holidays]]
path = ~/.calendars/Personal/cln2stbjc4hmgrrcd5i62ua0ctp6utbg5pr2sor1dhimsp31e8n6errfctm6abj3dtmg@virtual/
color = light blue
[[birthdays]]
path = ~/.calendars/Personal/c5i68sj5edpm4rrfdchm6rreehgm6t3j81jn4rrle0n7cbj3c5m6arj4c5p2sprfdtjmop9ecdnmq@virtual/
color = brown

现在,当你运行 khal interactive 时,每个日历将被着色以区别于其他日历,并且当你添加新条目时,它将有更具描述性的名称。

Adding a new calendar entry

设置有些麻烦,但是完成后,khal 和 vdirsyncer 可以一起为你提供一种简便的方法来管理日历事件并使它们与你的在线服务保持同步。


via: https://opensource.com/article/20/1/open-source-calendar

作者:Kevin Sonney 选题:lujun9972 译者:geekpi 校对:wxy

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

想要入门密码学的基础知识,尤其是有关 OpenSSL 的入门知识吗?继续阅读。

本文是使用 OpenSSL 的密码学基础知识的两篇文章中的第一篇,OpenSSL 是在 Linux 和其他系统上流行的生产级库和工具包。(要安装 OpenSSL 的最新版本,请参阅这里。)OpenSSL 实用程序可在命令行使用,程序也可以调用 OpenSSL 库中的函数。本文的示例程序使用的是 C 语言,即 OpenSSL 库的源语言。

本系列的两篇文章涵盖了加密哈希、数字签名、加密和解密以及数字证书。你可以从我的网站的 ZIP 文件中找到这些代码和命令行示例。

让我们首先回顾一下 OpenSSL 名称中的 SSL。

OpenSSL 简史

安全套接字层 Secure Socket Layer (SSL)是 Netscape 在 1995 年发布的一种加密协议。该协议层可以位于 HTTP 之上,从而为 HTTPS 提供了 S: 安全 secure 。SSL 协议提供了各种安全服务,其中包括两项在 HTTPS 中至关重要的服务:

  • 对等身份验证 Peer authentication (也称为相互质询):连接的每一边都对另一边的身份进行身份验证。如果 Alice 和 Bob 要通过 SSL 交换消息,则每个人首先验证彼此的身份。
  • 机密性 Confidentiality :发送者在通过通道发送消息之前先对其进行加密。然后,接收者解密每个接收到的消息。此过程可保护网络对话。即使窃听者 Eve 截获了从 Alice 到 Bob 的加密消息(即中间人攻击),Eve 会发现他无法在计算上解密此消息。

反过来,这两个关键 SSL 服务与其他不太受关注的服务相关联。例如,SSL 支持消息完整性,从而确保接收到的消息与发送的消息相同。此功能是通过哈希函数实现的,哈希函数也随 OpenSSL 工具箱一起提供。

SSL 有多个版本(例如 SSLv2 和 SSLv3),并且在 1999 年出现了一个基于 SSLv3 的类似协议 传输层安全性 Transport Layer Security (TLS)。TLSv1 和 SSLv3 相似,但不足以相互配合工作。不过,通常将 SSL/TLS 称为同一协议。例如,即使正在使用的是 TLS(而非 SSL),OpenSSL 函数也经常在名称中包含 SSL。此外,调用 OpenSSL 命令行实用程序以 openssl 开始。

除了 man 页面之外,OpenSSL 的文档是零零散散的,鉴于 OpenSSL 工具包很大,这些页面很难以查找使用。命令行和代码示例可以将主要主题集中起来。让我们从一个熟悉的示例开始(使用 HTTPS 访问网站),然后使用该示例来选出我们感兴趣的加密部分进行讲述。

一个 HTTPS 客户端

此处显示的 client 程序通过 HTTPS 连接到 Google:

/* compilation: gcc -o client client.c -lssl -lcrypto */
#include <stdio.h>
#include <stdlib.h>
#include <openssl/bio.h> /* BasicInput/Output streams */
#include <openssl/err.h> /* errors */
#include <openssl/ssl.h> /* core library */
#define BuffSize 1024

void report_and_exit(const char* msg) {
  perror(msg);
  ERR_print_errors_fp(stderr);
  exit(-1);
}

void init_ssl() {
  SSL_load_error_strings();
  SSL_library_init();
}

void cleanup(SSL_CTX* ctx, BIO* bio) {
  SSL_CTX_free(ctx);
  BIO_free_all(bio);
}

void secure_connect(const char* hostname) {
  char name[BuffSize];
  char request[BuffSize];
  char response[BuffSize];

  const SSL_METHOD* method = TLSv1_2_client_method();
  if (NULL == method) report_and_exit("TLSv1_2_client_method...");

  SSL_CTX* ctx = SSL_CTX_new(method);
  if (NULL == ctx) report_and_exit("SSL_CTX_new...");

  BIO* bio = BIO_new_ssl_connect(ctx);
  if (NULL == bio) report_and_exit("BIO_new_ssl_connect...");

  SSL* ssl = NULL;

  /* 链路 bio 通道,SSL 会话和服务器端点 */

  sprintf(name, "%s:%s", hostname, "https");
  BIO_get_ssl(bio, &ssl); /* 会话 */
  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* 鲁棒性 */
  BIO_set_conn_hostname(bio, name); /* 准备连接 */

  /* 尝试连接 */
  if (BIO_do_connect(bio) <= 0) {
    cleanup(ctx, bio);
    report_and_exit("BIO_do_connect...");
  }

  /* 验证信任库,检查证书 */
  if (!SSL_CTX_load_verify_locations(ctx,
                                      "/etc/ssl/certs/ca-certificates.crt", /* 信任库 */
                                      "/etc/ssl/certs/")) /* 其它信任库 */
    report_and_exit("SSL_CTX_load_verify_locations...");

  long verify_flag = SSL_get_verify_result(ssl);
  if (verify_flag != X509_V_OK)
    fprintf(stderr,
            "##### Certificate verification error (%i) but continuing...\n",
            (int) verify_flag);

  /* 获取主页作为示例数据 */
  sprintf(request,
          "GET / HTTP/1.1\x0D\x0AHost: %s\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A",
          hostname);
  BIO_puts(bio, request);

  /* 从服务器读取 HTTP 响应并打印到输出 */
  while (1) {
    memset(response, '\0', sizeof(response));
    int n = BIO_read(bio, response, BuffSize);
    if (n <= 0) break; /* 0 代表流结束,< 0 代表有错误 */
  puts(response);
  }

  cleanup(ctx, bio);
}

int main() {
  init_ssl();

  const char* hostname = "www.google.com:443";
  fprintf(stderr, "Trying an HTTPS connection to %s...\n", hostname);
  secure_connect(hostname);

return 0;
}

可以从命令行编译和执行该程序(请注意 -lssl-lcrypto 中的小写字母 L):

gcc -o client client.c -lssl -lcrypto

该程序尝试打开与网站 www.google.com 的安全连接。在与 Google Web 服务器的 TLS 握手过程中,client 程序会收到一个或多个数字证书,该程序会尝试对其进行验证(但在我的系统上失败了)。尽管如此,client 程序仍继续通过安全通道获取 Google 主页。该程序取决于前面提到的安全工件,尽管在上述代码中只着重突出了数字证书。但其它工件仍在幕后发挥作用,稍后将对它们进行详细说明。

通常,打开 HTTP(非安全)通道的 C 或 C++ 的客户端程序将使用诸如文件描述符网络套接字之类的结构,它们是两个进程(例如,这个 client 程序和 Google Web 服务器)之间连接的端点。另一方面,文件描述符是一个非负整数值,用于在程序中标识该程序打开的任何文件类的结构。这样的程序还将使用一种结构来指定有关 Web 服务器地址的详细信息。

这些相对较低级别的结构不会出现在客户端程序中,因为 OpenSSL 库会将套接字基础设施和地址规范等封装在更高层面的安全结构中。其结果是一个简单的 API。下面首先看一下 client 程序示例中的安全性详细信息。

  • 该程序首先加载相关的 OpenSSL 库,我的函数 init_ssl 中对 OpenSSL 进行了两次调用:
SSL_load_error_strings();
SSL_library_init(); 
  • 下一个初始化步骤尝试获取安全上下文,这是建立和维护通往 Web 服务器的安全通道所需的信息框架。如对 OpenSSL 库函数的调用所示,在示例中使用了 TLS 1.2:
const SSL_METHOD* method = TLSv1_2_client_method(); /* TLS 1.2 */

如果调用成功,则将 method 指针被传递给库函数,该函数创建类型为 SSL_CTX 的上下文:

SSL_CTX* ctx = SSL_CTX_new(method);

client 程序会检查每个关键的库调用的错误,如果其中一个调用失败,则程序终止。

  • 现在还有另外两个 OpenSSL 工件也在发挥作用:SSL 类型的安全会话,从头到尾管理安全连接;以及类型为 BIO( 基本输入/输出 Basic Input/Output )的安全流,用于与 Web 服务器进行通信。BIO 流是通过以下调用生成的:
BIO* bio = BIO_new_ssl_connect(ctx);

请注意,这个最重要的上下文是其参数。BIO 类型是 C 语言中 FILE 类型的 OpenSSL 封装器。此封装器可保护 client 程序与 Google 的网络服务器之间的输入和输出流的安全。

  • 有了 SSL_CTXBIO,然后程序在 SSL 会话中将它们组合在一起。三个库调用可以完成工作:
BIO_get_ssl(bio, &ssl); /* 会话 */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* 鲁棒性 */
BIO_set_conn_hostname(bio, name); /* 准备连接 */

安全连接本身是通过以下调用建立的:

BIO_do_connect(bio);

如果最后一个调用不成功,则 client 程序终止;否则,该连接已准备就绪,可以支持 client 程序与 Google Web 服务器之间的机密对话。

在与 Web 服务器握手期间,client 程序会接收一个或多个数字证书,以认证服务器的身份。但是,client 程序不会发送自己的证书,这意味着这个身份验证是单向的。(Web 服务器通常配置为需要客户端证书)尽管对 Web 服务器证书的验证失败,但 client 程序仍通过了连接到 Web 服务器的安全通道继续获取 Google 主页。

为什么验证 Google 证书的尝试会失败?典型的 OpenSSL 安装目录为 /etc/ssl/certs,其中包含 ca-certificates.crt 文件。该目录和文件包含着 OpenSSL 自带的数字证书,以此构成 信任库 truststore 。可以根据需要更新信任库,尤其是可以包括新信任的证书,并删除不再受信任的证书。

client 程序从 Google Web 服务器收到了三个证书,但是我的计算机上的 OpenSSL 信任库并不包含完全匹配的证书。如目前所写,client 程序不会通过例如验证 Google 证书上的数字签名(一个用来证明该证书的签名)来解决此问题。如果该签名是受信任的,则包含该签名的证书也应受信任。尽管如此,client 程序仍继续获取页面,然后打印出 Google 的主页。下一节将更详细地介绍这些。

客户端程序中隐藏的安全性

让我们从客户端示例中可见的安全工件(数字证书)开始,然后考虑其他安全工件如何与之相关。数字证书的主要格式标准是 X509,生产级的证书由诸如 Verisign 证书颁发机构 Certificate Authority (CA)颁发。

数字证书中包含各种信息(例如,激活日期和失效日期以及所有者的域名),也包括发行者的身份和数字签名(这是加密过的加密哈希值)。证书还具有未加密的哈希值,用作其标识指纹

哈希值来自将任意数量的二进制位映射到固定长度的摘要。这些位代表什么(会计报告、小说或数字电影)无关紧要。例如, 消息摘要版本 5 Message Digest version 5 (MD5)哈希算法将任意长度的输入位映射到 128 位哈希值,而 SHA1( 安全哈希算法版本 1 Secure Hash Algorithm version 1 )算法将输入位映射到 160 位哈希值。不同的输入位会导致不同的(实际上在统计学上是唯一的)哈希值。下一篇文章将会进行更详细的介绍,并着重介绍什么使哈希函数具有加密功能。

数字证书的类型有所不同(例如根证书、中间证书和最终实体证书),并形成了反映这些证书类型的层次结构。顾名思义,证书位于层次结构的顶部,其下的证书继承了根证书所具有的信任。OpenSSL 库和大多数现代编程语言都具有 X509 数据类型以及处理此类证书的函数。来自 Google 的证书具有 X509 格式,client 程序会检查该证书是否为 X509_V_OK

X509 证书基于 公共密钥基础结构 public-key infrastructure (PKI),其中包括的算法(RSA 是占主导地位的算法)用于生成密钥对:公共密钥及其配对的私有密钥。公钥是一种身份:Amazon 的公钥对其进行标识,而我的公钥对我进行标识。私钥应由其所有者负责保密。

成对出现的密钥具有标准用途。可以使用公钥对消息进行加密,然后可以使用同一个密钥对中的私钥对消息进行解密。私钥也可以用于对文档或其他电子工件(例如程序或电子邮件)进行签名,然后可以使用该对密钥中的公钥来验证签名。以下两个示例补充了一些细节。

在第一个示例中,Alice 将她的公钥分发给全世界,包括 Bob。然后,Bob 用 Alice 的公钥加密邮件,然后将加密的邮件发送给 Alice。用 Alice 的公钥加密的邮件将可以用她的私钥解密(假设是她自己的私钥),如下所示:

             +------------------+ encrypted msg  +-------------------+
Bob's msg--->|Alice's public key|--------------->|Alice's private key|---> Bob's msg
             +------------------+                +-------------------+

理论上可以在没有 Alice 的私钥的情况下解密消息,但在实际情况中,如果使用像 RSA 这样的加密密钥对系统,则在计算上做不到。

现在,第二个示例,请对文档签名以证明其真实性。签名算法使用密钥对中的私钥来处理要签名的文档的加密哈希:

                    +-------------------+
Hash of document--->|Alice's private key|--->Alice's digital signature of the document
                    +-------------------+

假设 Alice 以数字方式签署了发送给 Bob 的合同。然后,Bob 可以使用 Alice 密钥对中的公钥来验证签名:

                                             +------------------+
Alice's digital signature of the document--->|Alice's public key|--->verified or not
                                             +------------------+

假若没有 Alice 的私钥,就无法轻松伪造 Alice 的签名:因此,Alice 有必要保密她的私钥。

client 程序中,除了数字证书以外,这些安全性都没有明确展示。下一篇文章使用使用 OpenSSL 实用程序和库函数的示例填充更多详细的信息。

命令行的 OpenSSL

同时,让我们看一下 OpenSSL 命令行实用程序:特别是在 TLS 握手期间检查来自 Web 服务器的证书的实用程序。调用 OpenSSL 实用程序可以使用 openssl 命令,然后添加参数和标志的组合以指定所需的操作。

看看以下命令:

openssl list-cipher-algorithms

该输出是组成 加密算法套件 cipher suite 的相关算法的列表。下面是列表的开头,加了澄清首字母缩写词的注释:

AES-128-CBC ## Advanced Encryption Standard, Cipher Block Chaining
AES-128-CBC-HMAC-SHA1 ## Hash-based Message Authentication Code with SHA1 hashes
AES-128-CBC-HMAC-SHA256 ## ditto, but SHA256 rather than SHA1
...

下一条命令使用参数 s_client 将打开到 www.google.com 的安全连接,并在屏幕上显示有关此连接的所有信息:

openssl s_client -connect www.google.com:443 -showcerts

端口号 443 是 Web 服务器用于接收 HTTPS(而不是 HTTP 连接)的标准端口号。(对于 HTTP,标准端口为 80)Web 地址 www.google.com:443 也出现在 client 程序的代码中。如果尝试连接成功,则将显示来自 Google 的三个数字证书以及有关安全会话、正在使用的加密算法套件以及相关项目的信息。例如,这是开头的部分输出,它声明证书链即将到来。证书的编码为 base64:

Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
 i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
-----BEGIN CERTIFICATE-----
MIIEijCCA3KgAwIBAgIQdCea9tmy/T6rK/dDD1isujANBgkqhkiG9w0BAQsFADBU
MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMSUw
...

诸如 Google 之类的主要网站通常会发送多个证书进行身份验证。

输出以有关 TLS 会话的摘要信息结尾,包括加密算法套件的详细信息:

SSL-Session:
    Protocol : TLSv1.2
    Cipher : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: A2BBF0E4991E6BBBC318774EEE37CFCB23095CC7640FFC752448D07C7F438573
...

client 程序中使用了协议 TLS 1.2,Session-ID 唯一地标识了 openssl 实用程序和 Google Web 服务器之间的连接。Cipher 条目可以按以下方式进行解析:

  • ECDHE 椭圆曲线 Diffie-Hellman(临时) Elliptic Curve Diffie Hellman Ephemeral )是一种用于管理 TLS 握手的高效的有效算法。尤其是,ECDHE 通过确保连接双方(例如,client 程序和 Google Web 服务器)使用相同的加密/解密密钥(称为会话密钥)来解决“密钥分发问题”。后续文章会深入探讨该细节。
  • RSA(Rivest Shamir Adleman)是主要的公共密钥密码系统,并以 1970 年代末首次描述了该系统的三位学者的名字命名。这个正在使用的密钥对是使用 RSA 算法生成的。
  • AES128 高级加密标准 Advanced Encryption Standard )是一种 块式加密算法 block cipher ,用于加密和解密 位块 blocks of bits 。(另一种算法是 流式加密算法 stream cipher ,它一次加密和解密一个位。)这个加密算法是对称加密算法,因为使用同一个密钥进行加密和解密,这首先引起了密钥分发问题。AES 支持 128(此处使用)、192 和 256 位的密钥大小:密钥越大,安全性越好。

通常,像 AES 这样的对称加密系统的密钥大小要小于像 RSA 这样的非对称(基于密钥对)系统的密钥大小。例如,1024 位 RSA 密钥相对较小,而 256 位密钥则当前是 AES 最大的密钥。

  • GCM 伽罗瓦计数器模式 Galois Counter Mode )处理在安全对话期间重复应用的加密算法(在这种情况下为 AES128)。AES128 块的大小仅为 128 位,安全对话很可能包含从一侧到另一侧的多个 AES128 块。GCM 非常有效,通常与 AES128 搭配使用。
  • SHA256 256 位安全哈希算法 Secure Hash Algorithm 256 bits )是我们正在使用的加密哈希算法。生成的哈希值的大小为 256 位,尽管使用 SHA 甚至可以更大。

加密算法套件正在不断发展中。例如,不久前,Google 使用 RC4 流加密算法(RSA 的 Ron Rivest 后来开发的 Ron’s Cipher 版本 4)。 RC4 现在有已知的漏洞,这大概部分导致了 Google 转换为 AES128。

总结

我们通过安全的 C Web 客户端和各种命令行示例对 OpenSSL 做了首次了解,使一些需要进一步阐明的主题脱颖而出。下一篇文章会详细介绍,从加密散列开始,到对数字证书如何应对密钥分发挑战为结束的更全面讨论。


via: https://opensource.com/article/19/6/cryptography-basics-openssl-part-1

作者:Marty Kalin 选题:lujun9972 译者:wxy 校对:wxy

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