密钥生成
准备公开加密的第一步就是生成一个私钥。在生成之前,你需要决定几个事情:
密钥算法
openssl支持RSA,DSA和ECDSA密钥,但不是所有类型的算法都适用于所有的场景。比如,web服务器的密钥使用的就是RSA, 因为DSA密钥受限于1024位的长度限制(ie浏览器不支持更长的), 而ECDSA密钥还没有被各个证书签发机构(CA)广泛支持。对于ssh客户端来说,DSA和RSA都被广泛的使用,而ECDSA则违背所有客户端支持。
密钥长度
密钥的默认长度可能不够安全,所以你应该每次都配置密钥长度。比如,RSA密钥的默认长度是512位(bit),很不安全。如果你用一个512位的密钥在你的服务器上,入侵者可以拿到你的证书并用暴力破解你的私钥,并假冒成你的站点。如今,2048位RSA密钥长度被认为是安全的,所以你应该是2048位。
密码
给密钥加上一个密码,这不是必须项,但是被强烈推荐。受保护的密钥可以被安全保存,传输以及备份。 但是,每次使用密钥的时候也需要提供密码。比如每次你要重启服务的时候,可能会被要求输入密码。大部分情况下,这要么会很不方便,要么干脆是无法接受的。另外,在生产中,受保密的密钥并不会提高什么安全性。因为密钥一旦激活,会直接保存在程序内存中,攻击者可以很容易的获得。因此,密码应该被视为一个在非生产环境下使用的机制。在生产环境下,可以把密码和密钥一起保存。如果你需要更安全的生产环境保护措施,应该考虑使用硬件解决方案。
生成一个RSA密钥,使用genrsa命令
$ openssl genrsa -aes128 -out fd.key 2048
Generating RSA private key, 2048 bit long modulus
....+++
...................................................................................+++
e is 65537 (0x10001)
Enter pass phrase for fd.key: ****************
Verifying - Enter pass phrase for fd.key: ****************
以上命令中,指定用AES-128保护密钥。也可以用AES-192(-aes192)或者AES-256(-aes256),但是最好不要用其他的算法(DES,3DES和SEED).
命令行输出中的e的值表示公开指数(the public exponent?),默认是65537,也被称为短公开指数,它可以极大的提升RSA的验证性能。使用-3开关,你可以选择设置公开指数为3,使得验证性能更快。然而,使用3做为公开指数有着不愉快的历史弱点,所以通常你应该使用在过去被证明了有更大安全余地的65537作为公开指数。
私钥以所谓的PEM格式保存,就是文本:
`$ cat fd.key -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,01EC21976A463CE36E9DB59FF6AF689A
vERmFJzsLeAEDqWdXX4rNwogJp+y95uTnw+bOjWRw1+O1qgGqxQXPtH3LWDUz1Ym mkpxmIwlSidVSUuUrrUzIL+V21EJ1W9iQ71SJoPOyzX7dYX5GCAwQm9Tsb40FhV/ [省略21行...] 4phGTprEnEwrffRnYrt7khQwrJhNsw6TTtthMhx/UCJdpQdaLW/TuylaJMWL1JRW i321s5me5ej6Pr4fGccNOe7lZK+563d7v5znAx+Wo1C+F7YgF+g8LOQ8emC+6AVV -----END RSA PRIVATE KEY-----`
一个私钥不仅仅是咋眼一看的那样就是一个随机的数据块。使用rsa命令,你可以看到一个密钥的结构:
$ openssl rsa -text -in fd.key
Enter pass phrase for fd.key: ****************
Private-Key: (2048 bit)
modulus:
00:9e:57:1c:c1:0f:45:47:22:58:1c:cf:2c:14:db:
[...]
publicExponent: 65537 (0x10001)
privateExponent:
1a:12:ee:41:3c:6a:84:14:3b:be:42:bf:57:8f:dc:
[...]
prime1:
00:c9:7e:82:e4:74:69:20:ab:80:15:99:7d:5e:49:
[...]
prime2:
00:c9:2c:30:95:3e:cc:a4:07:88:33:32:a5:b1:d7:
[...]
exponent1:
68:f4:5e:07:d3:df:42:a6:32:84:8d:bb:f0:d6:36:
[...]
exponent2:
5e:b8:00:b3:f4:9a:93:cc:bc:13:27:10:9e:f8:7e:
[...]
coefficient:
34:28:cf:72:e5:3f:52:b2:dd:44:56:84:ac:19:00:
[...]
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
[...]
-----END RSA PRIVATE KEY-----
如果你需要分离出密钥中的公开部分, 用以下的rsa命令行:
$ openssl rsa -in fd.key -pubout -out fd-public.key
这个命令生成一个fd-public.key的公钥,用cat命令输出内容,你可以看到标记符清楚的表明了这是一个公钥信息:
$ cat fd-public.key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnlccwQ9FRyJYHM8sFNsY
PUHJHJzhJdwcS7kBptutf/L6OvoEAzCVHi/m0qAA4QM5BziZgnvv+FNnE3sgE5pz
iovEHJ3C959mNQmpvnedXwfcOIlbrNqdISJiP0js6mDCzYjSO1NCQoy3UpYwvwj7
0ryR1F+abARehlts/Xs/PtX3VamrljiJN6JNgFICy3ZvEhLZEKxR7oob7TnyZDrj
IHxBbqPNzeiqLCFLFPGgJPa0cH8DdovBTesvu7wr/ecsf8CYyUCdEwGkZh9DKtdU
HFa9H8tWW2mX6uwYeHCnf2HTw0E8vjtOb8oYQxlQxtL7dpFyMgrpPOoOVkZZW/P0
NQIDAQAB
-----END PUBLIC KEY-----
检查一下生成的是否是你想要的内容是个好习惯。比如,如果你忘了在命令行里加上-pubout开关,生成的文件里会包含你的私钥而不是公钥。
DSA密钥生成有两个步骤: 创建DSA参数;创建密钥。
比起一次执行一步,我倾向于一次同时运行两个命令:
$ openssl dsaparam -genkey 2048 | openssl dsa -out dsa.key -aes128
Generating DSA parameters, 2048 bit long prime
This could take some time
[...]
read DSA key
writing DSA key
Enter PEM pass phrase: ****************
Verifying - Enter PEM pass phrase: ****************
这种写法在生成带密码保护的密钥的同时不会留下临时文件(DSA参数)和临时的密钥。