当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Ruby Security模块用法及代码示例


本文简要介绍ruby语言中 Gem::Security模块 的用法。

签署 gems

Gem::Security 为 gem 实现加密签名。以下部分是step-by-step 指南,用于使用已签名的 gem 并生成您自己的。

演练

建立你的证书

为了开始签署您的 gem,您需要构建一个私钥和一个 self-signed 证书。就是这样:

# build a private key and certificate for yourself:
$ gem cert --build you@example.com

这可能需要几秒钟到一两分钟,具体取决于计算机的速度(公钥算法并不是世界上最快的加密算法)。完成后,您将在当前目录中看到文件 “gem-private_key.pem” 和 “gem-public_cert.pem”。

首先要做的事情:如果您在该目录中还没有 key 和证书,请将这两个文件移动到 ~/.gem。确保文件权限使其他人无法读取 key (默认情况下文件被安全保存)。

隐藏您的私钥;如果它被泄露,有人可以像你一样签署包(注意:PKI 有降低被盗 key 风险的方法;稍后会详细介绍)。

签名 gems

在 RubyGems 2 和更新版本中,无需额外工作即可签署 gem。 RubyGems 将自动在您的主目录中找到您的 key 和证书,并使用它们来签署新打包的 gem。

如果您的证书不是self-signed(由第三方签名),RubyGems 将尝试从受信任的证书加载证书链。使用 gem cert --add signing_cert.pem 将您的签名者添加为受信任的证书。有关证书链的更多信息,请参见下文。

如果您构建您的 gem,它将自动被签名。如果您查看您的 gem 文件,您会看到添加了几个新文件:

$ tar tf your-gem-1.0.gem
metadata.gz
metadata.gz.sig # metadata signature
data.tar.gz
data.tar.gz.sig # data signature
checksums.yaml.gz
checksums.yaml.gz.sig # checksums signature

手动签名 gem

如果您希望将 key 存储在单独的安全位置,则需要设置您的 gem 以进行手动签名。为此,请在打包 gem 之前在 gemspec 中设置 signing_keycert_chain

s.signing_key = '/secure/path/to/gem-private_key.pem'
s.cert_chain = %w[/secure/path/to/gem-public_cert.pem]

当您使用这些选项集打包 gem 时,RubyGems 将自动从安全路径加载您的 key 和证书。

签名的 gem 和安全策略

现在让我们验证签名。继续安装 gem,但添加以下选项:-P HighSecurity,如下所示:

# install the gem with using the security policy "HighSecurity"
$ sudo gem install your.gem -P HighSecurity

-P 选项设置您的安全策略 - 我们将在稍后讨论。诶,这是什么?

$ gem install -P HighSecurity your-gem-1.0.gem
ERROR:  While executing gem ... (Gem::Security::Exception)
    root cert /CN=you/DC=example is not trusted

这里的罪魁祸首是安全策略。 RubyGems 有几种不同的安全策略。让我们休息一下,看看安全策略。以下是可用安全策略的列表,以及每个安全策略的简要说明:

  • NoSecurity - 好吧,根本没有安全保障。签名包被视为未签名包。

  • LowSecurity - 几乎没有安全保障。如果一个包被签名,那么 RubyGems 将确保签名与签名证书匹配,并且签名证书没有过期,但就是这样。恶意用户可以轻松绕过这种安全措施。

  • MediumSecurity - 比 LowSecurity NoSecurity 好,但仍然容易出错。包内容根据签名证书进行验证,并检查签名证书的有效性,并检查证书链的其余部分(如果您不知道证书链是什么,请继续关注,我们会解决的) . LowSecurity 最大的改进是 MediumSecurity 不会安装由不受信任的来源签名的包。不幸的是, MediumSecurity 仍然不是完全安全的——恶意用户仍然可以解压 gem、剥离签名并分发未签名的 gem。

  • HighSecurity - 这是让我们陷入困境的虫子。 HighSecurity 策略与 MediumSecurity 策略相同,只是它不允许未签名的 gem。恶意用户在这里没有很多选择;他们不能在不使签名失效的情况下修改包内容,也不能修改或删除签名或签名证书链,或者RubyGems将简单地拒绝安装包。哦,好吧,也许他们会给 CPAN 用户带来更好的运气 :)。

RubyGems 拒绝安装闪亮的新签名 gem 的原因是它来自不受信任的来源。好吧,您的代码是可靠的(自然),因此您需要将自己添加为受信任的来源:

# add trusted certificate
gem cert --add ~/.gem/gem-public_cert.pem

您现在已将公共证书添加为可信来源。现在,您可以轻松安装由您的私钥签名的软件包。让我们再次尝试上面的安装命令:

# install the gem with using the HighSecurity policy (and this time
# without any shenanigans)
$ gem install -P HighSecurity your-gem-1.0.gem
Successfully installed your-gem-1.0
1 gem installed

这次RubyGems 将接受您签名的包并开始安装。

在等待 RubyGems 运行时,它很神奇,通过运行 gem help cert 查看其他一些安全命令:

Options:
  -a, --add CERT                   Add a trusted certificate.
  -l, --list [FILTER]              List trusted certificates where the
                                   subject contains FILTER
  -r, --remove FILTER              Remove trusted certificates where the
                                   subject contains FILTER
  -b, --build EMAIL_ADDR           Build private key and self-signed
                                   certificate for EMAIL_ADDR
  -C, --certificate CERT           Signing certificate for --sign
  -K, --private-key KEY            Key for --sign or --build
  -A, --key-algorithm ALGORITHM    Select key algorithm for --build from RSA, DSA, or EC. Defaults to RSA.
  -s, --sign CERT                  Signs CERT with the key from -K
                                   and the certificate from -C
  -d, --days NUMBER_OF_DAYS        Days before the certificate expires
  -R, --re-sign                    Re-signs the certificate from -C with the key from -K

我们已经介绍了 --build 选项,而 --add--list--remove 命令看起来相当简单;它们允许您添加、列出和删除受信任证书列表中的证书。但是这个 --sign 选项有什么用呢?

证书链

为了回答这个问题,让我们看一下我之前提到的概念“certificate chains”。 self-signed 证书有几个问题:首先,self-signed 证书不能提供很多安全性。当然,证书上写着 Yukihiro Matsumoto,但我怎么知道它实际上是由 matz 自己生成和签名的,除非他亲自给我证书?

第二个问题是可扩展性。当然,如果有 50 个 gem 作者,那么我就有 50 个受信任的证书,没问题。如果有 500 位 gem 作者怎么办? 1000?不得不不断地添加新的受信任证书是一件痛苦的事情,而且它实际上通过鼓励RubyGems 用户盲目信任新证书而降低了信任系统的安全性。

这就是证书链的用武之地。证书链在颁发证书和子证书之间建立了任意长的信任链。因此,我们不是在per-developer 基础上信任证书,而是使用证书链的 PKI 概念来构建信任的逻辑层次结构。这是基于(大致)地理的信任层次结构的假设示例:

                    --------------------------
                    | rubygems@rubygems.org |
                    --------------------------
                                |
              -----------------------------------
              |                                 |
  ----------------------------    -----------------------------
  |  seattlerb@seattlerb.org |    | dcrubyists@richkilmer.com |
  ----------------------------    -----------------------------
       |                |                 |             |
---------------   ----------------   -----------   --------------
|   drbrain   |   |   zenspider  |   | pabs@dc |   | tomcope@dc |
---------------   ----------------   -----------   --------------

现在,用户无需拥有 4 个受信任的证书(一个用于 drbrain、zenspider、pabs@dc 和 tomecope@dc),而实际上可以使用一个证书,即 “rubygems@rubygems.org” 证书。

这是它的工作原理:

我安装了“rdoc-3.12.gem”,这是一个由“drbrain” 签名的包。我从未听说过“drbrain”,但他的证书具有来自“seattle.rb@seattlerb.org” 证书的有效签名,而后者又具有来自“rubygems@rubygems.org” 证书的有效签名。瞧!在这一点上,我相信由“drbrain” 签名的包更合理,因为我可以建立到我确实信任的“rubygems@rubygems.org” 的链。

签署证书

--sign 选项允许这一切发生。开发人员使用 --build 选项创建他们的构建证书,然后通过将其带到他们的下一个区域 Ruby 聚会(在我们的假设示例中)来签署他们的证书,并由持有区域 RubyGems 签名的人在那里签名证书,由顶级 RubyGems 证书的持有者在下一个 RubyConf 签名。在每一点,发行者运行相同的命令:

# sign a certificate with the specified key and certificate
# (note that this modifies client_cert.pem!)
$ gem cert -K /mnt/floppy/issuer-priv_key.pem -C issuer-pub_cert.pem
   --sign client_cert.pem

然后颁发证书的持有者(在这种情况下,您的好友“drbrain”)可以开始使用此签名证书来签署 RubyGems。顺便说一句,为了让其他人知道他的新签名证书,“drbrain”会将他新签名的证书保存为~/.gem/gem-public_cert.pem

显然,这个RubyGems 信任基础设施还不存在。此外,在“real world” 中,颁发者实际上是根据证书请求生成子证书,而不是签署现有证书。我们假设的基础设施缺少证书撤销系统。这些是将来可以修复的……

在这一点上,您应该知道如何做所有这些新的和有趣的事情:

  • 构建 gem 签名 key 和证书

  • 调整您的安全策略

  • 修改您的信任证书列表

  • 签署证书

手动验证签名

如果您不信任RubyGems,您可以手动验证 gem 签名:

  1. 获取并解压 gem

    gem fetch some_signed_gem
    tar -xf some_signed_gem-1.0.gem
  2. 从 gemspec 中获取公钥

    gem spec some_signed_gem-1.0.gem cert_chain | \
      ruby -rpsych -e 'puts Psych.load($stdin)' > public_key.crt
  3. 生成 data.tar.gz 的 SHA1 哈希

    openssl dgst -sha1 < data.tar.gz > my.hash
  4. 验证签名

    openssl rsautl -verify -inkey public_key.crt -certin \
      -in data.tar.gz.sig > verified.hash
  5. 将您的哈希与经过验证的哈希进行比较

    diff -s verified.hash my.hash
  6. 使用 metadata.gz 重复 5 和 6

OpenSSL 参考

-build 和 -sign 生成的 .pem 文件是 PEM 文件。这里有几个有用的 OpenSSL 命令来操作它们:

# convert a PEM format X509 certificate into DER format:
# (note: Windows .cer files are X509 certificates in DER format)
$ openssl x509 -in input.pem -outform der -out output.der

# print out the certificate in a human-readable format:
$ openssl x509 -in input.pem -noout -text

你也可以对私钥文件做同样的事情:

# convert a PEM format RSA key into DER format:
$ openssl rsa -in input_key.pem -outform der -out output_key.der

# print out the key in a human readable format:
$ openssl rsa -in input_key.pem -noout -text

错误/待办事项

  • 无法定义 system-wide 信任列表。

  • 自定义安全策略(来自 YAML 文件等)

  • 生成签名证书请求的简单方法

  • 支持 OCSP、SCVP、CRL 或其他形式的证书状态检查(列表按优先顺序排列)

  • 支持加密私钥

  • 某种semi-formal 信任层次结构(参见上面的long-winded 解释)

  • 路径发现(对于没有 self-signed 根的 gem 证书链)- 顺便说一下,由于我们没有这个,如果 Policy#verify_root 为真(并且它适用于 MediumSecurity HighSecurity 策略)

  • 更好地解释 X509 命名(即,我们不必使用电子邮件地址)

  • 荣誉 AIA 领域(见上文关于 OCSP 的说明)

  • 荣誉延期限制

  • 将证书链存储为 PKCS#7 或 PKCS#12 文件而不是嵌入在元数据中的数组可能会更好。

原作者

保罗邓肯 <pabs@pablotron.org> pablotron.org /

相关用法


注:本文由纯净天空筛选整理自ruby-lang.org大神的英文原创作品 Security模块。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。