我写的《深入浅出HTTPS:从原理到实战》这个月快出版了,虽然书写完了,但是我对密码学和SSL的学习却没有停止,从5月份开始我就一直研究(主要是最新的密码学知识、以前没有接触的知识),并且将学习的内容发表在公众号(yudadanwx)和简书中,也就是说我在简书和公众号中所有相关的密码学文章不会和《深入浅出HTTPS:从原理到实战》书中的内容相重合,如果大家有兴趣,还请关注。
欢迎关注我的公众号(yudadanwx),了解我最新的博文。![](https://img.haomeiwen.com/i234392/0daea34f2b2ccaed.jpg)
本文介绍一个密码学和TLS的实现,这就是 NSS,由 Mozilla 维护,我们熟知的 Firefox 就基于它实现 TLS 协议,另外一个比较引人注目的就是它的可信任CA根证书列表,我全面的浏览了NSS的官方文档,做了一个简单的笔记。
NSS 是什么
NSS 是开源软件,和 OpenSSL 一样,是一个底层密码学库,包括 TLS 实现。NSS 并不是完全由 Mozilla 开发出来的,很多公司(包括 Google)和个人都贡献了代码,只是 Mozilla 提供了一些基础设施(比如代码仓库、bug 跟踪系统、邮件组、讨论组)。
NSS 是跨平台的,很多产品都使用了NSS 密码库,包括:
- Mozilla 的产品,比如 Firefox、Thunderbird、Firefox OS。
- 一些开源的软件,比如 Pidgin、Apache OpenOffice、LibreOffice。
- Red Hat 的服务器产品,比如 Red Hat Directory Server, Red Hat Certificate System。
- 其他服务器产品,比如 Apache 的 mod_nss模块,没有发现 Nginx 支持 NSS。
- SJES 的 Sun 服务器产品。
NSS 支持的密码学算法标准和应用如下:
- SSL&TLS,NSS 计划从 NSS 3.29 版本开始支持 TLS 1.3 协议。
- 各类 PKCS 公开密码学标准,详细信息可参考 Public Key Cryptography Standards
- Cryptographic Message Syntax,用于 S/MIME(对 MIME 数据进行加密和签名),关于 CMS 标准和 S/MIME 应用了解的不多,所以在《深入迁出HTTPS:从原理到实践》这本书中并没有阐述。
- X.509 v3 证书,这是 HTTPS 协议中非常重要的组成部分。
- OCSP,是证书非常有效的补充协议,用于在线校验证书的吊销状态(可扩展,还包括其他状态,比如可以包含证书透明度信息)。
- 各类密码学算法,包括 RSA、DH、ECC、AES、SHA、HMAC 等等。
- 符合 FIPS 186-2 标准的伪随机生成函数。
NSS 提供了完整的软件开发包,包括密码库、API、命令行工具、文档集(API references、man 帮助、示例代码)。NSS 3.14版本开始,升级到 GPL 兼容的 MPL 2.0 许可证。
NSS 符合 FIPS 140(1&2)标准,FIPS 标准是美国政府定义的一种标准,主要是数据编码的标准。NSS 库也通过了 NISCC TLS/SSL 和 S/MIME 的测试(160万输入数据的测试),NISCC 是英国政府提出的安全标准。
在使用 NSS 之前,Mozilla 建议你应该具备一些知识,否则会很晕乎,知识列表如下:
- 明白公开密钥密码学的概念和技术。
- PKCS #11 标准,相当于各类密码学算法和应用的使用标准。
- TLS 协议概念。
编译 NSS
NSS 最新的版本是 3.37.1,是今年 5 月 22号发布的,由于 NSS 依赖于 NSPR,所以该版本需要的 NSPR 版本必须大于 NSPR 4.19,3.37.1 版本详细信息见release。
(1)获取代码
你可以直接下载下载最新版本(包括 nspr),你也可以使用 hg(类似于git)获取最新的开发版本,比如运行下列命令:
$ mkdir nssproject && cd nssproject
$ hg clone https://hg.mozilla.org/projects/nspr
$ hg clone https://hg.mozilla.org/projects/nss
获取的代码分别保存在同级目录下,分别是 nss 和 nspr。在 nss/lib 目录下包含所有导出 api 的源文件,其中 .def 后缀的文件包含对应的 api 列表,比如可以查看 lib/ssl/ssl.def,了解 ssl 协议包含的各种 api。
(2)编译
编译过程还是比较麻烦的,因为 nss 不使用 configure 脚本,所以需要配置不同的环境变量,比如在 linux 使用 shell,在 windows 上使用 Mozilla 提供的构建包。
以下介绍在 Ubuntu(Ubuntu 14.04.5 LTS/x86_64,如果不知道查看操作系统版本和该系统是32位还是64位,可以使用 lsb_release -a 和 uname -a 命令行)下的编译过程:
$ BUILD_OPT=1
$ USE_64=1
$ export BUILD_OPT
$ export USE_64
$ cd nss
$ make nss_build_all
编译完成后,所有编译的文件全部保存在 dist 目录下(和 nss 目录同级),其中最主要的目录是 Linux3.13_x86_64_cc_glibc_PTH_64_OPT.OBJ#,这是根据操作系统动态命名的一个目录,包含了三个子目录:
- include,其他应用程序的需要的头文件包含在该目录下。
- lib,其他应用程序需要的 library 文件。
- bin,所有的命令行工具包。
如果你编译的时候遇到问题,可以参考additional information of interest
如果你想做一些开发工作,你可以运行脚本进行测试,比如运行下列命令:
# 测试 all.sh
$ cd nss/tests
$ ./all.sh
# 测试单个 sh
$ cd nss/tests/cert
$ ./cert.sh
测试的结果在 nssproject/tests_results 目录下,如果你想掌握命令行的使用,应该好好阅读 all.sh 文件的内容。
关于 NSS API
对于我来说,主要想法是根据 NSS API 手册使用库对应的功能(比如加密解密),但是了解代码的组织方式还是非常有必要的,我简单看了遍相关内容。
NSS 代码是分层(Layer)的,分为底层 API 和高层 API,底层 API 完成特定的工作,它不能调用上层的高层 API,而高层 API 主要是包装底层 API,然后给开发者调用。
分层结构如下图:
![](https://img.haomeiwen.com/i234392/1d6ee9d4b7ad5cfa.gif)
NSS API 对外的就是包,包包括一些头文件、包文件等信息,列举几个例子:
Library | 描述 | Layer | 目录 | 头文件 |
---|---|---|---|---|
certdb | 证书处理 | Low Cert | lib/certdb | cdbhdl.h 等 |
pkcs 12 | PKCS #12 数据处理 | PKCS #12 | lib/pkcs12 | pkcs12t.h 等 |
NSS 服务提供静态库和动态库,开发者如果想使用静态库,那么只能调用开发者导出的 API,而且这些 API 都能和新版本兼容。
不同的操作系统,NSS 的静态库和动态库有不同的命名约定,见下列表格:
库类型 | Windows | Unix |
---|---|---|
静态库 | .lib | .a |
动态库 | .dll | .so 或者 .sl |
NSS 整个架构图如下:
![](https://img.haomeiwen.com/i234392/eee0b066fed5420d.gif)
- NSPR:一个跨平台的底层次函数库,主要作用是为了尽量多的支持各类操作系统,NSS 3.x 版本目前支持 18 个平台,提供 I/O 操作,网络操作函数等基础库。NSPR 是 Mozilla 独立的一个工程。
- NSS:主要包含各类密码学库,它包含了一个框架,通过这个框架,开发者和 OEMs 能够提供很多补丁,比如优化密码学操作性能(SSL accelerators、指令集)。
- SSL&S/MIME:基于 NSS 实现的应用层协议,最主要的就是 SSL 了。
API 的概要说明见NSS Public Functions,API 详细的调用说明见NSS Reference。
NSS API 都是 C 语言调用的(NSS 本身也是 C 语言开发的),我个人对 Python 比较熟悉,可以使用 python-nss 模块进行开发,后续也会介绍一下。
NSS 命令行工具
NSS 编译后,除了包,还包含很多命令行工具,不过这些工具的功能和 OpenSSL 还没发比,关于工具使用,可以参考NSS Security Tools。
编译后,直接运行命令行会报错的,需要 export 一些目录,比如运行下列的命令:
$ export LD_LIBRARY_PATH='/root/nssproject/dist/Linux3.13_x86_64_cc_glibc_PTH_64_OPT.OBJ/lib:'
$ nssproject/dist/Linux3.13_x86_64_cc_glibc_PTH_64_OPT.OBJ/bin/certutil
那么如果不编译 nss,如何使用这些命令行工具呢?在各个发行版中其实都有专门的安装包,比如在 Ubuntu 下安装 libnss3-tools 工具:
$ apt-get install libnss3-tools
需要指出的是 Mozilla NSS 最让人知晓的是可信任根证书列表(关于其后面还会专门写博文介绍,包括 Curl 命令行工具如何使用 NSS 的根证书列表),但是在编译 NSS 的时候,并没有发现根证书列表文件(后续再研究下),不过可以使用 certutil 创建和管理证书,包括导入到可信任根证书文件中。
The Certificate Database Tool is a command-line utility that can create and modify the Netscape > Communicator cert8.db and key3.db database files. It can also list, generate, modify, or delete > certificates within the cert8.db file and create or change the password, generate new public
and private key pairs, display the contents of the key database
接下去介绍简单的用法:
生成新的 cert 文件:
$ export LD_LIBRARY_PATH='/root/nssproject/dist/Linux3.13_x86_64_cc_glibc_PTH_64_OPT.OBJ/lib:'
$ mkdir /root/nssdbnew
$ bin/certutil -L -d /root/nssdbnew
在 /root/nssdbnew 目录下会生成三个文件,分别是 cert9.db、key4.db、pkcs11.txt,如果使用系统的 certutil(libnss3-tools 包安装的)运行,生成的文件是 cer8.db。
然后生成一个 CSR 文件(证书申请请求):
$ bin/certutil -R -s "CN=John Smith, O=Netscape, L=Mountain View, ST=California, C=US" -p "650-555-8888" -o mycert.req -d /root/nssdbnew/
奇怪的是,要不停的按回车键和空格键才能最终运行完成,生成的 csr 文件就是 mycert.req 。
接下去根据 csr 文件生成证书文件:
$ certutil -S -s "CN=My Issuer" -n myissuer -x -t "C,C,C" -1 -2 -5 -m 1234 -d /root/nssdbnew/
$ certutil -C -m 2345 -i mycert.req -o mycert.crt -c myissuer -d /root/nssdbnew/
不过最后一直卡着,到最后也没完成(相比 OpenSSL 还得加把劲啊)。
最后我将自己网站的一个证书加入到 cert9.db 中,命令如下:
$ certutil -A -n ywdblog@outlook.com -t "p,p,p" -i cert.pem -d /root/nssdbnew
$ certutil -L -n ywdblog@outlook.com -d /root/nssdbnew
以上两个命令是将一个证书加入到根证书列表文件中,然后再从 cert9.db 文件中读取相应的证书。
关于 NSS 其实还有很多内容,后续想分享以下一些内容:
- Mozilla CA certificate 策略。
- 如何导入根证书到 Firefox(Chrome)和其他应用软件。
- CURL 工具如何使用 NSS。
- python-nss 模块的使用。
网友评论