密钥是时候更换到曲线 25519

有关 Curve25519/Ed25519/X25519 介绍的文章已经很多,分别指的椭圆曲线加密/签名/密钥交换算法。由于 NIST 系列的不透明以及来历不明参数,被广泛怀疑。棱镜门后,25519 系列开始逐渐被大众接受。直至当下的部署情况: Things that use Curve25519

具体介绍就不多说了,以下简单说一下常用场景使用 25519 算法的过程。

TLS 自签证书

以下 tls 自签证书,可以被 curl/links 等客户端支持,可以在私有场合使用。

Firefox/Chrome 等浏览器还未支持,因为浏览器供应商联合公共信任中心组成的行业联盟规定了 X.509/WebPKI 中的可用 ECC 大部分被限于 NIST 系列。如果是架设公共服务,那么请谨慎使用。

ED25519 需要 OpenSSL 1.1.1 以及之后的版本。

ED25519 key
$ openssl genpkey -algorithm ED25519 -out server.key
PKCS#10
$ openssl req -new -out server.csr -key server.key -subj '/C=US/ST=CA/L=San Francisco/O=Internet Widgits Pty Ltd/OU=IT/CN=Self-signed ECC/[email protected]'
Sign csr
$ openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
查看
$ openssl req -in server.csr -text -noout
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = US, ST = CA, L = San Francisco, O = Internet Widgits Pty Ltd, OU = IT, CN = Self-signed ECC, emailAddress = [email protected]
        Subject Public Key Info:
            Public Key Algorithm: ED25519
                ED25519 Public-Key:
                pub:
                    43:b5:f2:51:f0:33:df:7b:47:74:d4:b2:75:ef:77:
                    3a:cd:f0:c9:2c:ad:25:64:de:93:85:f5:bd:ad:5b:
                    2d:5f
        Attributes:
            a0:00
    Signature Algorithm: ED25519
         9a:53:53:fa:b6:d2:ca:a7:e3:db:86:5c:dc:04:78:c1:5c:ba:
         de:50:54:48:20:86:36:c3:76:64:0a:01:3e:59:49:8d:51:4c:
         46:ca:52:e9:0e:fa:18:4b:12:4d:63:b2:3d:de:f3:40:30:85:
         ec:75:2d:7e:03:b5:02:34:cd:0c

OpenSSH 密钥对

$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "[email protected]"
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/name/.ssh/id_ed25519.
Your public key has been saved in /Users/name/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:/IzQ36S2fWk549u16/8CmZEAJ+0Niv3C5QfhB+Tg/us [email protected]
The key's randomart image is:
+--[ED25519 256]--+
|        ++o      |
|       . =*      |
|       o.+.* .   |
|      .+o = =    |
|      ..S+ o.+   |
|       .o*o+=    |
|        ..B... o.|
|         . +  O.o|
|         .E .++OB|
+----[SHA256]-----+

你也可以添加 -a 100 参数增加求导函数的次数,注意:该数字越高 = 越慢的密码验证 = 更高的抗暴力密码破解。针对的是密码而非密钥本身。

GnuPG 密钥对

$ gpg --expert --full-gen-key
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
  (14) Existing key from card
Your selection? 9
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 2y
Key expires at Tue Jun 22 12:59:57 2023 CST
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Your Name
Email address: [email protected]
Comment: Your Comment
You selected this USER-ID:
    "Your Name (Your Comment) <[email protected]>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 0x8F75F10ABACF9D18 marked as ultimately trusted
gpg: revocation certificate stored as '/Users/name/.gnupg/openpgp-revocs.d/0C2DDA1BA5738976147F17F18F75F10ABACF9D18.rev'
public and secret key created and signed.

pub   ed25519/0x8F75F10ABACF9D18 2021-06-22 [SC] [expires: 2023-06-22]
      Key fingerprint = 0C2D DA1B A573 8976 147F  17F1 8F75 F10A BACF 9D18
      Keygrip = CA2F58C28CC8A23E8A87000482236C9DCB0EB7E7
uid                              Your Name (Your Comment) <[email protected]>
sub   cv25519/0xC63205BDCC95F10A 2021-06-22 [E] [expires: 2023-06-22]
      Keygrip = 08852924712C889AA1148A35F258CACCE511E908

事实上,gpg 也可以创建用于 ssh 的认证密钥对

$ gpg --expert --edit-key 0x8F75F10ABACF9D18
Secret key is available.

sec  ed25519/0x8F75F10ABACF9D18
     created: 2021-06-22  expires: 2023-06-22  usage: SC
     trust: ultimate      validity: ultimate
ssb  cv25519/0xC63205BDCC95F10A
     created: 2021-06-22  expires: 2023-06-22  usage: E
[ultimate] (1). Your Name (Your Comment) <[email protected]>

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 11

Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? A

Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign Authenticate

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 2y
Key expires at Tue Jun 22 13:14:54 2023 CST
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  ed25519/0x8F75F10ABACF9D18
     created: 2021-06-22  expires: 2023-06-22  usage: SC
     trust: ultimate      validity: ultimate
ssb  cv25519/0xC63205BDCC95F10A
     created: 2021-06-22  expires: 2023-06-22  usage: E
ssb  ed25519/0x6C1FDAA711647985
     created: 2021-06-22  expires: 2023-06-22  usage: SA
[ultimate] (1). Your Name (Your Comment) <[email protected]>

gpg> quit
Save changes? (y/N) y

最后按照 GnuPG 介绍作为 ssh 公钥 部分内容,配置下即可完成。