我下面的答案有点冗长,但希望它提供了以前答案中缺少的一些细节。我将从一些相关的陈述开始,最后回答最初的问题。
要使用 RSA 算法加密某些内容,您需要模数和加密(公共)指数对(n,e)。那是你的公钥。要使用 RSA 算法解密某些内容,您需要模数和解密(私有)指数对(n,d)。那是你的私钥。
要使用 RSA 公钥加密某些内容,您将明文视为一个数字并将其提升到 e 模数 n 的幂:
ciphertext = ( plaintext^e ) mod n
要使用 RSA 私钥解密某些内容,您将密文视为一个数字并将其提升到 d 模数 n 的幂:
plaintext = ( ciphertext^d ) mod n
要使用 openssl 生成私有 (d,n) 密钥,您可以使用以下命令:
openssl genrsa -out private.pem 1024
要使用 openssl 从私钥生成公钥 (e,n) 密钥,您可以使用以下命令:
openssl rsa -in private.pem -out public.pem -pubout
要剖析上述 openssl 命令生成的 private.pem RSA 私钥的内容,请运行以下命令(此处的输出截断为标签):
openssl rsa -in private.pem -text -noout | less
modulus - n
privateExponent - d
publicExponent - e
prime1 - p
prime2 - q
exponent1 - d mod (p-1)
exponent2 - d mod (q-1)
coefficient - (q^-1) mod p
私钥不应该只由 (n, d) 对组成吗?为什么有 6 个额外的组件?它包含 e(公共指数),以便可以从 private.pem 私有 RSA 密钥生成/提取/派生公共 RSA 密钥。其余 5 个组件用于加速解密过程。事实证明,通过预先计算和存储这 5 个值,可以将 RSA 解密速度提高 4 倍。没有这 5 个组件,解密也可以工作,但如果你手边有它们,它可以更快地完成。加速算法基于Chinese Remainder Theorem。
是的,private.pem RSA 私钥实际上包含所有这 8 个值;当您运行上一个命令时,它们都不会即时生成。尝试运行以下命令并比较输出:
# Convert the key from PEM to DER (binary) format
openssl rsa -in private.pem -outform der -out private.der
# Print private.der private key contents as binary stream
xxd -p private.der
# Now compare the output of the above command with output
# of the earlier openssl command that outputs private key
# components. If you stare at both outputs long enough
# you should be able to confirm that all components are
# indeed lurking somewhere in the binary stream
openssl rsa -in private.pem -text -noout | less
PKCS#1 v1.5 推荐这种 RSA 私钥结构作为替代 (second) 表示。 PKCS#1 v2.0 标准从替代表示中完全排除了 e 和 d 指数。 PKCS#1 v2.1 和 v2.2 建议通过可选地包括更多与 CRT 相关的组件来进一步更改替代表示。
要查看 public.pem 公共 RSA 密钥的内容,请运行以下命令(此处的输出被截断为标签):
openssl rsa -in public.pem -text -pubin -noout
Modulus - n
Exponent (public) - e
这里没有惊喜。正如承诺的那样,它只是 (n, e) 对。
现在终于回答了最初的问题:如上所示,使用 openssl 生成的私有 RSA 密钥包含公钥和私钥的组成部分等等。当您从私钥生成/提取/派生公钥时,openssl 会将其中两个组件 (e,n) 复制到一个单独的文件中,该文件将成为您的公钥。