Showing posts with label 译文. Show all posts
Showing posts with label 译文. Show all posts

Sunday, June 17, 2007

[近期译文] GIT 简要教程

git 简要教程 (适用于 1.5.1 或更新版本)

原文链接: http://www.kernel.org/pub/software/scm/git/docs/tutorial.html


这个教程将介绍如何将一个新的项目导入到 git 之中,如何修改项目并如何将这些变更与其他开发者分享。

如果你更感兴趣如何用 git 取出一个项目,比如,测试软件的最新版本,你可能更应该看看 The Git User's Manual 的前两章。

首先,记住你可以用 man 来获取 git 的文档,比如 "git diff" 的文档可以用如下命令察看:

$ man git-diff

在做任何改动之前,最好把自己的名字和 email 地址介绍给大家,最简单的方法就是:

$ git config --global user.name "Your Name Comes Here"
$ git config --global user.email you@yourdomain.example.com

导入一个新项目

假设你有一个名为 project.tar.gz 的 tarball 作为项目的初始内容。你可以如下操作来把它至于 git 版本控制之下。

$ tar xzf project.tar.gz
$ cd project
$ git init

Git 将会如下回复:

Initialized empty Git repository in .git/

现在,你已经初始化了工作目录——你可能已经注意到了名为 ".git" 的一个新目录了。下一步就是使用 git-add(1) 命令告诉 git 当前目录的所有文件全是项目的一个快照:

$ git add .

这个快照目前存放在一个临时区域之中,在 git 中称为 "index"。使用 git-commit 命令,你可以把 index 的所有内容永久性地存放到软件仓库之中:

$ git commit

这条命令会向你提示输入版本变更信息。这样,你的项目的第一个版本就已经存入 git 之中了。

进行修改

修改一些文件之后,你可以将

更新这些内容到 index 之中:

$ git add file1 file2 file3

现在,你已经准备就绪,可以提交了。现在你可以使用 git-diff(1) 命令的 --cache 参数

来查看都有哪些内容将会被提交:

$ git diff --cached

(如果不使用 --cached 参数,git-diff(1) 会显示所有还没添加进 index 的已经做出的改动。) 你也可以使用 git-status (1) 来获得一些当前状况的概要信息:

$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: file1
# modified: file2
# modified: file3
#

如果你需要进行更多改动,现在就可以进行,然后可以添加到 index 之中。最后,使用如下命令提交改动:

$ git commit

这将再次要求你输入关于这次改动内容的描述性信息,之后记录下

的项目新版本。此外,如果想省掉提交之前的 git add 命令,你可以直接用

$ git commit -a

这样会自动检测所有修改过的文件 (不包括新文件) ,并一气呵成地将它们添到 index 之中,并提交。

关于提交的描述信息: 虽然这个信息不是必须的,但提交信息描述最好以一行不超过50个字符的概要性信息来开头,在一个空行之后再进行更多的描述。比如那些将 commit 转化为 email 的工具就会把这个第一行作为邮件标题,其余的提交内容则放在邮件内部。

Git 跟踪内容而不是文件

很多版本控制系统提供了一个 "add" 命令用来记录一个新文件。而 git 的 "add" 命令更加简单也更加强大: git-add 既用于新文件也用于新近改动的文件,在所有这些情况下,它在 index 中对所有的文件与状态进行一次快照,这样就可以在下一次 commit 命令中进行提交。

查看项目历史

在任何时候,你都可以如下查看所有你进行过的改动

$ git log

你可能还想看到每一步改进中的所有完整的 diff ,这可以使用如下命令

$ git log -p

浏览改动的概要对于获得每一步修改的情况常常是比较有用的,可以使用如下命令

$ git log --stat --summary

管理分支

一个 git 仓库可以包含多个开发分支。使用如下命令可以建立一个称为 "experimental" 的新分支

$ git branch experimental

如果你运行命令

$ git branch

你将可以得到类似下面的已有分支的列表

  experimental
* master

"experimental" 就是你刚刚建立的那个分支,而 "master" 分支则是建立仓库的时候自动创建的缺省分支,里面的星号表示你当前所在的分支;输入命令

$ git checkout experimental

就可以切换到 experimental 分支。现在修改一个文件,并提交改变,然后重新回到 master 分支:

(edit file)
$ git commit -a
$ git checkout master

你会发现,刚才的变更已经不可见了,这是因为这个改变是发生于 experimental 分支的,而你现在已经回到 master 分支了。

(edit file)
$ git commit -a

这里,两个分支已经产生不同了,每个分支上都发生了不同的改动。要把 experimental 中的改变也合并到 master 之中,运行命令

$ git merge experimental

如果两者的改变并不冲突,那么就算是完成了。而如果这里有冲突,有问题的文件左边会显示出标记,以表明这个文件发生了冲突;

$ git diff

上述命令将会列出具体的冲突。一旦你编辑文件解决了冲突,

$ git commit -a

这个命令将把合并的结果提交。最终,

$ gitk

会显示出漂亮的图标以展示历史变革。



这里你可以使用如下命令删除 experimental 分支。

$ git branch -d experimental

这个命令会确定 experimental 中的所有改动已经在当前分支当中了。


如果你在 crazy-idea 分支中进行开发,然后又后悔了,你可以用如下命令删除分支
$ git branch -D crazy-idea

分支操作十分简单而且代价低廉,所以适合于尝试一些东西。

使用 git 进行协作

假设 Alice 在 /home/alice/project 中的 git 仓库启动了一个新项目,而在本机中也拥有 home 目录的 Bob 想要贡献一些代码。


他可以以如下工作开始:

$ git clone /home/alice/project myrepo

这会新建一个名为 "myrepo" 的目录,里面包含了 Alice 的仓库的一份克隆。这份克隆与原始项目完全一致,可以处理自己的一份原始项目历史。


之后,Bob 进行了一些变更并提交了这些变动:

(edit files)
$ git commit -a
(repeat as necessary)

当他完成的时候,他告诉 Alice 将 /home/bob/myrepo 之中的变动导入到原始仓库之中。她使用如下命令来完成这一工作:

$ cd /home/alice/project
$ git pull /home/bob/myrepo master

这回合并 Bob 的 "master" 分支到 Alice 的当前分支。如果 Alice 也已经修改了某些内容,她需要手工修复冲突。(注意,"master" 参数实际上并不是必要的,因为这是缺省分支。) "pull" 命令包括两个操作: 从远端分支中取出改动,然后合并到当前分支之中。


当你只在一个很小的小组里工作的时候,通常不会频繁地访问同一个仓库。通过定义仓库的快捷方式,可以让访问远程仓库更方便一些:

$ git remote add bob /home/bob/myrepo

这样,你可以如下用 "git fetch" 命令仅取出改动,而不把它们合并到当前分支之中:

$ git fetch bob

和长格式不同,当 Alice 使用 git remote 设置的快捷方式从 Bob 的仓库中获取内容的时候,取出的内容存储在一个 remote tracking 分支之中,在本例中是 bob/master。所以,如下操作

$ git log -p master..bob/master

将会列出从 Bob 从 Alice 的主分支中分支出去以后的所有改动。

$ git merge bob/master

这个合并也可以通过从自己的 remote tracking 分支中 pull 来做到,如

$ git pull . remotes/bob/master

注意,git pull 总是合并进当前的分支,不论命令行给出的是什么。


之后,Bob 可以如下使用 Alice 的最近改动更新自己的仓库

$ git pull

这里,他不需要给出 Alice 的仓库的位置;当 Bob 克隆了 Alice 的仓库的时候,git 在仓库设置中保存了她的仓库的位置,即 pull 所使用的位置:

$ git config --get remote.origin.url
/home/bob/myrepo

(git-clone 创建的完整配置信息可以用 "git config -l" 获得,git-config(1) 的 man page 解释了所有选项的含义。)


Git 也在 "origin/master" 分支保存了一份 Alice 的主分支的原始拷贝:

$ git branch -r
origin/master

如果其后 Bob 决定转到另一台主机上工作,他还可以通过 ssh 来克隆原始仓库:

$ git clone alice.org:/home/alice/project myrepo

此外,git 本身也有远程协议,并且可以使用 rsync 或 http,详细情况可以查看 git-pull(1) 的 man page。


Git 也可以使用类似 CVS 的工作方式,使用一个中心仓库,所有用户将改动推送到仓库之中,相关内容可以查阅 git-push(1) 的手册页或 git for CVS users

浏览历史

Git 的历史是通过一系列相互关联的 commit 构成的。我们已经通过 git log 命令看到了这些提交的列表。注意,每个 git log 条目的第一行是那次提交的名称:

$ git log
commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
Author: Junio C Hamano <junkio@cox.net>
Date: Tue May 16 17:18:22 2006 -0700

merge-base: Clarify the comments on post processing.

把这个名称用于 git show 命令,可以得到提交的详情。

$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7

不过还有其他办法来指代这次提交。你可以只使用名称的开始部分,只要它足够长,保证在所有提交中是惟一的就行了:

$ git show c82a22c39c   # the first few characters of the name are
# usually enough
$ git show HEAD # the tip of the current branch
$ git show experimental # the tip of the "experimental" branch

每一次提交通常都有一次提交作为 "parent" ,它是项目的前一个状态:

$ git show HEAD^  # to see the parent of HEAD
$ git show HEAD^^ # to see the grandparent of HEAD
$ git show HEAD~4 # to see the great-great grandparent of HEAD

Note that merge commits may have more than one parent:

要注意,合并提交可能会有多个 "parent":

$ git show HEAD^1 # show the first parent of HEAD (same as HEAD^)
$ git show HEAD^2 # show the second parent of HEAD

你还可以给你的提交一个名字; 命令

$ git-tag v2.5 1b2e1d63ff

让你可以使用 "v2.5" 来指代 1b2e1d63ff。如果你想把这个名字与他人共享 (比如标记一个发布版本),你应该建立一个 "tag" 对象,可能还需要签署它; 详情请查看 git-tag(1) 的 man page。


任何 git 命令都可以使用上述任何一种名字。比如:

$ git diff v2.5 HEAD     # compare the current HEAD to v2.5
$ git branch stable v2.5 # start a new branch named "stable" based
# at v2.5
$ git reset --hard HEAD^ # reset your current branch and working
# directory to its state at HEAD^

小心使用上述最后一个命令: 这将丢失工作目录中的所有改动,他还会清除本分支内随后的所有提交。如果这个分支是包含这些提交的惟一分支,它们将永远地丢失了。此外,不要对一个公众可见的、有其他开发者从中 pull 内容的分支使用 "git reset" 命令,这将导致一些不必要的合并来清除其他开发者的历史信息。如果你需要取消已经推送的改动,可以使用 git-revert(1) 命令。


git grep 可以在项目的所有版本历史中寻找字符串,而如下命令

$ git grep "hello" v2.5

会在版本 v2.5 中寻找所有 "hello" 的踪迹。


如果你不提供 commit 名称,git grep 会在你当前的目录中搜索所有由 git 管理的文件。于是,如下命令

$ git grep "hello"

是搜索 git 跟踪的所有文件的便捷的方式。


很多 git 命令可以处理一组提交,可以通过多种方式来指定版本。这里是一些 git log 的例子:

$ git log v2.5..v2.6            # commits between v2.5 and v2.6
$ git log v2.5.. # commits since v2.5
$ git log --since="2 weeks ago" # commits from the last 2 weeks
$ git log v2.5.. Makefile # commits since v2.5 which modify
# Makefile

你给出的范围的起始值不一定比终止值更老,比如,"stable-release" 分支可能会在 "master" 分支之后相当长一段时间才会引入同一个提交内容,这样

$ git log stable..experimental

将会列出 expermental 分支之中已经有的,而 stable 分支却还没有的提交,而命令

$ git log experimental..stable

将会列出 stable 中已有、但 experimental 却没有的提交。


"git log" 命令有一个弱点:必须将所有提交在一个列表中呈现出来。当项目历史中有多个不同开发分支并最终合并到一起时,"git log" 中呈现出来的顺序可能没什么意义。


大部分有大量开发者的项目 (比如 linux kernel 或 git 本身) 都经常合并分支,gitk 可以更好地将这些合并变化展示出来。比如,

$ gitk --since="2 weeks ago" drivers/

这个命令允许你浏览过去两个星期中在 "drivers" 目录之中的任意提交。(注意: 你可以按住 ctrl 键然后用 "-" 和 "+" 来调整 gitk 的字体大小。)


最后,大部分命令可以带有文件名,这可以用于指定某次提交中的某个文件,从而指定某个文件的某个版本:

$ git diff v2.5:Makefile HEAD:Makefile.in

你还可以用 "git show" 命令去查看任意文件的任意版本:

$ git show v2.5:Makefile

下一步学习

这个教程应该足够你的项目进行基本的项目发布版本管理。不过,要完全深入地理解 git 的强大功能可能还需要理解两个简单的概念:

  • 对象数据库是个相当阳春的系统,用于存储你的项目的历史,包括文件、目录以及各次提交。
  • 索引文件是目录树的状态的缓存,用于建立提交、取出工作目录并保存一次合并中包含的不同的目录树。

本教程的第二部分 解释了对象数据库、索引文件以及一些其他你在使用 git 中所需要了解的零七八碎的概念。


如果你不想在这条路上继续下去,还有一些细枝末节的东西可能十分有趣:

  • git-format-patch(1), git-am(1): 用于将一系列 git 提交转化成 email 发送的补丁或反之,对于 linux 内核这样的高度依赖于邮件发送的补丁的项目来说十分有用。

  • git-bisect(1): 当你的项目发生倒退的时候,一个跟踪发现错误的方法就是通过历史发现那个罪魁祸首的提交。Git bisect 可以帮助你进行二分查找发现那个提交。它能在一个有很多分支合并的具有复杂非线性历史的项目中十分灵巧地进行接近最优的搜索。
  • Everyday GIT with 20 Commands Or So

  • git for CVS users.


原文最后更新于: 11-Jun-2007 01:21:27 UTC

Friday, March 16, 2007

[译文] 使用 Cscope 和 SilentBob 分析源代码

Title
Using Cscope and SilentBob to analyze source code
Date
2007.03.09 4:01
Author
StoneLion
Topic

http://programming.linux.com/article.pl?sid=07/03/05/1715201

当你开始研究一个不熟悉的项目的源代码的时候,对源代码的结构、函数和类的名称的含义等都不甚了解。这时,虽然我们可以使用 tags 来查看他们的定义,但是却很难通过一个一个看这些定义来得到全句的信息。Cscope 和 SilentBob 就是两个可以帮助我们分析不熟悉的源代码的工具。他们可以帮助你查找符号的定义,判断某个函数在哪里被调用了,发现某个给定的函数调用了哪些其他函数,以及在源代码中进行字符串模式匹配。使用这两个工具,你可以通过高速、有目的性的阅读代码来节省大量的时间,而不需要去手工 grep 所有代码文件。

使用 Cscope

Cscope 是一个非常流行的实用工具,大部分现代发行版都包含它。虽然 Cscope 最初被设计用来分析 C 代码,不过实际上,它在分析其他语言,诸如 C++ 和 Java 的时候同样好用。Cscope 拥有一个基于 ncurses 的界面,不过,它同样支持命令行模式,以便和其他前端程序一同工作,这些前端包含很多主流编辑器,如 Emacs 和 Vim。

当你调用 Cscope 的时候,它自动扫描当前目录之中的源文件,并把收集到的信息存储在一个内部数据库里面。如果需要递归扫描子目录,可以使用 -R 开关。如果你不需要 Cscope 的界面,只想从其它程序里查询其数据库,可以使用 -b 参数。如果你需要在一个大型或系统相关项目中使用,可以通过参考链接中的指南来查询一些优化参数,以提高速度。

缺省情况下,生成数据库之后,前端界面会自动启动 (可以使用 -d 参数告知 Cscope 使用已经生成的数据库,而不是重新生成一个)。这事一个两个面板的界面;在下面的面板中输入你希望查询的内容,结果会在上面的面板中显示出来。你可以使用 Tab 键在面板间切换,退出程序的快捷键是 Ctrl-D

在下面的面版上,可以使用方向键切换不同的查找域。使用这个面板,你可以:

  • 查找某特定符号的出现位置;
  • 查找全局定义 (如果找到的话,自动打开编辑器)
  • 查找特定函数调用过的函数
  • 查找调用某个特定函数的函数
  • 查找文本字符串
  • 替换字符串
  • 查找一个 egrep 正则表达式
  • 在编辑器里打开一个特定文件
  • 查找 #include 了某个文件的文件

每当你进行一次查询,Cscope 会把查找结果进行编号,和文件名、函数名 (如果有的话)、行号以及代码行本身一起显示出来。如果使用方向键选择了一个查询结果并敲回车或是直接敲对应的数字键,Cscope 会启动系统缺省的编辑器 (由 EDITOR 环境变量确定) 打开该文件,并把光标定位到该行 (某些编辑器可能不支持定位到行,不过至少 Emacs 和 Vim 没有问题)。

使用 (X)Emacs 作为前端

在 Emacs 中使用 Cscope 非常容易。如果你没有运行着 cscope 开头的程序,而 Emacs 中已经有 Cscope 菜单了,你可以通过安装 xcscope.el 在 Emacs 中集成 Cscope。xcscope.el 可以在 Cscope 源码包中的 contrib/xcscope 子目录中得到。安装的方法是把 cscope-indexer 脚本放到 $PATH 中的路径之中,并把 xcscope.el 放到 Emacs 的脚本路径 (路径相关帮助可以在 Emacs 里面运行 ``C-h v load-path`` 来查询 load-path 相关说明)。先在,把 (require 'xcscope') 这行放到 ~/.emace 或 ~/emacs.d/init.el 当中就可以了。xcscope.el 文件的开头部分的注释可以作为文档。


这个包把所有 Cscope 的查找命令添加导了 Emacs 菜单中的 Cscope 子菜单当中,并且可以在你编辑文件的时候使用快捷键调用。比如,如果你想查找一个符号,可以直接在菜单中选择 Cscope -> Symbol 或是输入 M-x cscope-find-this-symbol,或按快捷键 C-c s s,之后输入符号的名字 (如果什么都不输入,就使用光标下的名字)。搜索的结果会显示在 *cscope* buffer 之中, 按照文件名分组,并以 <函数名>[行号] <整行内容> 的形式显示。把光标移动到想查看的搜索结果上,按空格键,将会在另一个 buffer 中打开该文件,并定位光标到搜索的行。如果你按的是回车而不是空格,你将会直接从 *cscope* buffer 中跳到相应的 buffer (鼠标点击搜索结果也可以)。你可以使用 n 和 p 来选择下一个或上一个搜索结果 (当 *cscope* buffer 不是当前 buffer 的时候可以用 C-c s n 和 C-c s p)。N 或 P 可以用于选择下一个和上一个文件 (或 C-c s N 和 C-c s P)。

在 Vim 中使用 Cscope

如果你更喜欢用 Vim,你还是可以用 Cscope。首先,你的 Vim 应该是使用 --enable-cscope 开关编译的。大部分二进制形式的 Linux 发布版都打开了这个开关。Gentoo 的用户则应该打开 cscope USE 标志。这里假设你使用的是 Vim 6.x 或 7.x。Vim 参考手册里包含了一篇使用 Cscope 接口的文章,你可以在 /usr/share/vim/vim&version/doc/if_cscop.txt找到它。你还可以看另一个简短的教程 (参考链接)。


在 Vim 中,你可以使用如下形式调用 Cscope: :cscope find search type search string (可以用 :cs f 来代替 :cscope find),这里的 search type 包括:

  • symbol or s -- 所有引用这个符号的地方;
  • global or g --查找全局符号
  • calls or c --查找特定函数的所有调用
  • called or d --查找特定函数调用的所有函数
  • text or t --查找文本
  • file or f --打开文件
  • include or i --查找 #include 了指定文件的文件
查找结果会在 Vim 窗口的底部以菜单方式显示出来。你可以键入你希望进入的查找结果的编号并按回车。如果你用 :scscope 或 :scs 代替 :cscope 的话,Vim 窗口会水平拆分成两个,你选择的查找结果将会放在新的窗口之中。

在 Vim 之中,从 Cscope 查询中跳到一个结果和跳到任意的 tag 没有什么区别; 你可以用 Ctrl-T 条回到查找之前的地方,也可以用 :tnext 和 :tprevious 在查找结果间来回跳。


如果你想调对光标下的词进行查找,你应该安装 cscope_maps.vim 插件 (把这个文件放在 $HOME/.vim/plugin 目录即可)。这个文件里面的注释说明了它的用法。使用这个插件,你可以用 Ctrl- 代替 :cscope,用 Ctrl-space 代替 :scscope,搜索将意光标下的词作为搜索词 (比如,你把光标挪到 "initialize" 上面,输入 Ctrl- s,就可以找到所有引用 initialize 符号的地方了。


SilentBob

SilentBob 是一个用于分析源代码的新工具,目前支持 C/C++, Perl 以及 Python,不过它的插件框架 (目前尚无文档)允许用户方便地添加新语言和新功能。


你可以从该软件的官方网站获取源码包或 deb 包。安装之后,在源码目录运行三次 SilentBob:

  bob --make-ctags
bob --cfiles
bob -L cfiles --call-tags
这样会生成三个文件: tags, 一般标签表格; cfiles, C/C++ 文件列表; calltags, 调用标签表。 调用标签表用于函数调用,所以,如果你希望查找某个函数的所有调用,你可以让 Vim 使用 调用标签表 (:set tags=./call_tags) 并使用内建命令用于查找标签 (:tag function-name 以及用 :tnext:tprevious循环查找)。这三个索引文件可以被 SilentBob 用于构建调用树和反向调用树。


对于 Perl 和 Python,只支持标签表和文件列表:

  bob <--perl | --python> --make-ctags
bob <--perl | --python> --files
第二个命令会生成 generate a perl_filespython_files 文件。


一旦生成了一个标签表,SilentBob 可以显示出一个调用树:

  bob [--depth N] function 

--depth 选项允许你限制调用树的深度。如果你之希望知道哪些函数被给定函数调用了,使用 --depth 0 参数即可。否则,被调用的函数会被依次列出来。


注意,你可以对 SilentBob 为 Python 和 Perl 文件生成的标签表加上这个参数。不过,使用 Exuberant Ctags 生成的表是不被支持的。


调用标签表还可以用于生成反向调用树

  bob [--depth N] -u function 

这将依次显示调用给定函数的函数。这时,指定 --depth 1 则只显示调用此函数的函数。SilentBob 也可以使用创建的 cfiles 文件查找 C/C++代码种的文本。它检查操作符,字符串和注释会被省略掉。

  bob list of files --cgrep pieces of text, separated by comma 

你可以指定 -L ./cfiles 来使用生成的文件列表。几个文本应该来自于同一个操作符,所以,如果你要找检验 T 变量的地方,可以使用:

  bob -L ./cfiles --cgrep if,T
SilentBob 还包含一个 tags 工具,让你可以在一个控制台查看标签的定义。调用 tags tag1 tag2 ... tagN 可以从代码中取出你感兴趣的片段 -- 函数定义、全局变量声明等等 -- 你将会看到你需要的代码片段。

为什么使用 SilentBob 生成标签?

SilentBob 使用语法分析器来解析源文件,这使得它比使用正则表达式定位文件中的某行的工具,如 Exuberant Ctags 要快很多。在对 Linux 内核源文件 (2.6.19) 的测试中,Exuberant Ctags 生成标签表需要 90 秒,而 SilentBob 仅需 10 秒钟 (测试机使用 2.6GHz 的赛扬处理器)。SilentBob 还支持多线程优化。

另一个不同来自于标签表的格式: Exuberant Ctags 生成的表中,使用正则表达式定位特定行。这就意味着,如果你编辑该文件,某些定义的位置可能会改变,但你不需要重新生成标签表。这对于 Exuberant Ctags 来说很理想,因为这样你就不需要频繁地重新生成表格了,不过,这也意味着如果你在浏览一个大型文件,在标签定义之间的跳转相对于记录行号的方式会非常慢。这就是 SilentBob 为什么在标签表中使用行号; 不过,这就意味着你必须在较大的编辑之后重新生成标签表了。

参考链接

  1. "tags" - http://applications.linux.com/article.pl?sid=07/01/22/167212&tid=13
  2. "Cscope" - http://cscope.sourceforge.net/
  3. "在大型项目中使用 Cscope" - http://cscope.sourceforge.net/large_projects.html
  4. "关于在 Vim 里使用 Cscope 的简短教程" - http://cscope.sourceforge.net/cscope_vim_tutorial.html
  5. "cscope_maps.vim" - http://cscope.sourceforge.net/cscope_maps.vim
  6. "SilentBob" - http://silentbob.sourceforge.net/

Sunday, February 11, 2007

[译文] 使用加密工具提高系统安全性

http://security.linux.com/article.pl?sid=07/01/31/1539208&from=rss

我的 U 盘里总会放着一份 Bcrypt. 这是个极为简单易用的基本工具。一旦装上了 bcrypt, 你惟一要做的就是在命令行依次输入 bcrypt 和你要加密的文件名。之后,Bcrypt 会要求你提供一个密码,仅此而已。加密之后,Bcrypt 会给文件加上 .bfe 的扩展名。同样的命令也可以用于解密,bcrypt 仅仅通过文件的扩展名来决定是要加密还是解密。

Bcrypt 使用 Blowfish 。算法。密码通常要有 8 到 56 个字符,并被内部哈希为一个 448 位密钥以增强安全性。缺省条件下,加密文件的时候,原始文件将被删除并在原来存储文件的位置覆写 3 次,以避免通过反删除工具发现原始文件,你可以增加或减少重写的次数。

Bcrypt 缺乏灵活性和各种开关,所以可能不是你加密军火库中的首选武器,不过,简单是它的强项。根据 Bcrypt 的项目网站介绍,它可以用于 Linux 和 *BSD, 没有 Windows 版本; 不过,这个网站似乎有年头没更新过了。

Ncrypt

Ncrypt 是另一个简单的文件加密/解密程序。你可以选择三个 AES 加密标准候选加密算法: Rijndael, Twofish, 和 Serpent 中的任何一个。开发者特别注意了生成密码的安全性: 当一个文本密码被用于加密文件的时候,它首先被转换为 SHA-1 哈希值,而原文被立刻清除出内存。之后,这个哈希值被用于密钥,随后,也会被清除出内存。

Ncrypt 同时有 Unix 和 Windows 版本。它的用法很直接: 使用 ncrypt 命令,用开关选择加密算法,是要加密、解密、还是要清除文件,以及输入输出文件名。。原始文件将被从磁盘上彻底清除;Ncrypt 也有一个非常有用的文件清除功能,你可以用它安全删除文件。

Pad

与 Bcrypt 和 Ncrypt 不同,Pad 使用 on-time pad (OTP) 加密。一个文件会被分成两个乃至更多独立的"pads", 没一个都类似于白噪声。两个文件看起来只是混入了无害的随机数据,可以在用户喜欢的任何时候被重新组装起来。

OTP 有非常悠久的历史了。理论上讲,它是惟一真正不可破解的加密手段。不过,它有一些实际应用上的弱点: 每个 pad 尽可以被使用一次,而且必须是真正的随机数 (这实际上非常困难),并且它很容易受到中间人工具。这样,它不被推荐用于日常加密任务。不过,有一个场合下,OTP 被认为是有价值的: 自由语音加密。比如,如果有人希望自由分发一个机密文件,它可以将文件拆成不同的 pad,并将多个部分存放在不同的一同里,并告诉别人如何获取它们并组合成原始文件。(译注: 这段翻译的不怎么好,因为译者根本不懂什么是 OTP, 查了半天还是不怎么明白,欢迎解释。)

GnuPG

对于多数人来说,GnuPG 是开源文件加密的不二选择。一些发布版还把它随发布版预装。引用其 FAQ 中的原文,"GnuPG 代表 GNU 隐私卫士,是用于安全通信与数据存储的 GNU 工具。它可以被用于数据加密和创建数字签名。它包含一个先进的密钥管理工具并与 RFC 2440 所描述的 OpenPGP Internet 标准提案相兼容。因而,它的目标是兼容 NAI 公司的 PGP。."

Bcrypt, Ncrypt 和很多其它加密工具使用对称密钥加密文件。而 GnuPG 和 PGP 一样,使用公钥密钥加密,尽管它也支持对称加密。公钥加密使得加密和签名多个文件并和其他用户交换它们变得很容易。对于对称密钥和公钥密钥的综述以及它们的工作机制,可以参考 GnuPG 手册的第二章和 FAQ 的 7.1 节。

GnuPG 可以独自地作为命令行工具使用,它有很多功能,并可以满足各种挑剔的用户。不过,它也有各种不错的前端工具可用。其中,我所用的是 KGpg, 集成在 KDE 之中,这方便了我很多日常加密工作。比如,其它我提到的加密工具只能加密文件,而不能加密目录。你可以用 KGpg 加密目录中的所有文件,或者创建一个 .tar.gz 或是 .zip 文件,并对它进行加密 。使用 KGpg, 我只要双击一个目录并告诉程序打包加密之即可。KGpg 也允许你在桌面创建一个碎纸机,用于安全删除你放在里面的文件 (而不是目录)。这非常方便,尽管我建议你阅读作者的关于破碎文件的安全说明。KGpg 的易用性非常优秀;即使对新手来说,学习曲线也非常短。

GnuPG 的开发步伐非常文鼎,而且支持多种操作系统。它在多种 Unix 系统上都可以编译,而且通过 Gpg4Win 提供了 Windows 移植版本。对于 Unix 系统的邮件加密的支持性也非常可靠: 查询 GnuPG FAQ 的 4.15 节,可以看到提供 GnuPG 集成的邮件客户端的列表 (很遗憾,支持 OpenPGP 标准的 Windows 客户端十分少见)。关于更多的邮件工具,可以看看 Aegypten 项目。

关于加密的更多信息,两个不错的起点是对应的 Wikipedia 文章和 Cryptography FAQ.

Rui Lopes 是一个葡萄牙网页设计师和独立纸片人,在技术领域有广泛兴趣。