<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>~iany/ RSA</title><link>https://blog.iany.me/zh/tags/rsa/</link><description>RSA的最新内容 «~iany/»</description><language>zh-CN</language><managingEditor>me@iany.me (Ian Yang)</managingEditor><webMaster>me@iany.me (Ian Yang)</webMaster><copyright>CC-BY-SA 4.0</copyright><lastBuildDate>Sat, 18 Nov 2017 02:46:10 +0000</lastBuildDate><atom:link href="https://blog.iany.me/zh/tags/rsa/index.xml" rel="self" type="application/rss+xml"/><item><title>Ruby 中读取各种 RSA Keys</title><link>https://blog.iany.me/zh/2017/11/read-various-rsa-keys-in-ruby/</link><pubDate>Sat, 18 Nov 2017 02:46:10 +0000</pubDate><author>me@iany.me (Ian Yang)</author><guid>https://blog.iany.me/zh/2017/11/read-various-rsa-keys-in-ruby/</guid><description>&lt;p&gt;最近在一个 Ruby on Rails 项目中需要集成各种支付系统。这些系统多使用 RSA 进行加密和签名验证。不过提供的 RSA Key 格式公式个样，所以把各种格式和如何在 Ruby 中读取整理了一下。&lt;/p&gt;
&lt;p&gt;RSA 是非对称加密算法，需要 2 个 Keys, 私钥和公钥。Key 本身就是二进制字符串，不过会被编码成各种格式。&lt;/p&gt;
&lt;h1 id="derpem"&gt;DER/PEM&lt;/h1&gt;
&lt;p&gt;DER 是一种二进制编码方案，如果用编辑器查看就是乱码。文件后缀一般是 &lt;code&gt;.cer&lt;/code&gt;, &lt;code&gt;.crt&lt;/code&gt;, 或者 &lt;code&gt;.der&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;PEM 使用 base64 编码，然后在前后添加 PEM 头和尾。比如&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx4c0F2TEoSe7wMBnn4WA
CSWQZL82eJJG3g128dE1BAMPAcSx0yaLWAEZJ0iZh9q14YND4kh7Or1hkV+beJfo
1c7DjO+VA31l9Nzdps/jGzkxa926VlFoXlLHngBn+zglfmXrhlVNVle/6asDrW49
p8LlLBZHqi/P72f9WUlAa7q45XXY48OqgsJ4ok2Xo0ZbLL9EHAu1GyfGFkBOsnOz
pqJe/aE0gltk+O7dKlVS1bGwm9cwx2eo+mEbH7NgbUm/by/OJKFx1SDbMIJRFcUj
WlosuKfzzkafH4i+z7n07s+StQ6kW5TcZbVVeQPjyzPdWeKvTRZMIvHV3ANVll+i
YQIDAQAB
-----END PUBLIC KEY-----
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种格式很常见，比如 &lt;code&gt;ssh-keygen&lt;/code&gt; 生成的私钥就是 PEM 格式。PEM 文件后缀一般是 &lt;code&gt;.pem&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;DER 和 PEM 都可以使用下面的方法读取&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-ruby"&gt;k = OpenSSL::PKey::RSA.new(File.read(&amp;quot;/path/to/keyfile&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果 Key 设置了 passphrase，可以通过第二个参数指定。&lt;/p&gt;
&lt;p&gt;通过方法 &lt;code&gt;k.private?&lt;/code&gt; 可以知道是否是私钥。公钥始终是可用的，因为可以通过私钥计算出公钥。&lt;/p&gt;
&lt;p&gt;有时候，提供的 Key 只是使用 base64 编码，但是没有加 PEM 头和尾。这种情况有俩种处理方案：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;先 Base64 解码，然后作为 Key 内容读取&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-ruby"&gt;k = OpenSSL::PKey::RSA.new(Base64.decode64(key_content))
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;格式化成 PEM 格式再读取&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-ruby"&gt;pem = key_content.gsub(&amp;quot;\r\n&amp;quot;, &amp;quot;&amp;quot;).scan(/.{1,64}/).join(&amp;quot;\n&amp;quot;)
# or use BEGIN PRIVATE KEY
pem = &amp;quot;-----BEGIN PUBLIC KEY-----\n#{pem}\n-----END PUBLIC KEY-----\n&amp;quot;
k = OpenSSL::PKey::RSA.new(pem)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="pkcs12"&gt;PKCS12&lt;/h1&gt;
&lt;p&gt;PKCS12 文件后缀一般是 &lt;code&gt;.p12&lt;/code&gt; 或者 &lt;code&gt;.pfx&lt;/code&gt;. 浏览器导出证书一般会提供该格式。大部分 PKCS12 文件都加了密码保护，可以通过第二个可选参数指定。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-ruby"&gt;pkcs12 = OpenSSL::PKCS12.new(key_content, certificate_password)
k = pkcs12.key
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="x509-certificate"&gt;X509 Certificate&lt;/h1&gt;
&lt;p&gt;X509 Certificate 编码 Key 的同时添加了很多信息，比如证书签发者，过期时间等。X509 一般使用 PEM 或 DER 编码，后缀一般是 &lt;code&gt;.cer&lt;/code&gt;。如果使用 PEM 格式，头一般是 &lt;code&gt;BEGIN CERTIFICATE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;X509 Certificate 可以使用下面代码读取&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-ruby"&gt;cert = OpenSSL::X509::Certificate.new(File.read(&amp;quot;/path/to/certfile&amp;quot;))
k = cert.public_key
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;因为容易和 PEM/DER 直接编码的 Key 搞混，如果出现 &lt;code&gt;asn1 error&lt;/code&gt; 的异常，可以尝试在 &lt;code&gt;OpenSSL::X509::Certificate&lt;/code&gt; 和 &lt;code&gt;OpenSSL::PKey::RSA&lt;/code&gt; 之间切换。&lt;/p&gt;</description><category domain="https://blog.iany.me/zh/">~iany/</category><category domain="https://blog.iany.me/zh/tags/cryptography/">Cryptography</category><category domain="https://blog.iany.me/zh/tags/openssl/">OpenSSL</category><category domain="https://blog.iany.me/zh/tags/rsa/">RSA</category><category domain="https://blog.iany.me/zh/tags/ruby/">Ruby</category></item></channel></rss>