ed25519, rsa ref done

This commit is contained in:
2022-03-07 02:34:27 -05:00
parent adb807dcb8
commit 2b6be62d56
18 changed files with 3013 additions and 33 deletions

View File

@@ -0,0 +1,7 @@
===== Legacy
[NOTE]
====
ED25519 has no legacy format, as it was introduced *after* the introduction of the new key format.
====

View File

@@ -0,0 +1,5 @@
==== Private
include::legacy/main.adoc[]
include::v1/main.adoc[]

View File

@@ -0,0 +1,146 @@
===== v1 (Encrypted)
[TIP]
====
Currently, the only supported KDF is *bcrypt_pbkdf* (`bcrypt`).
See the following for more details:
* https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf
* http://www.tedunangst.com/flak/post/bcrypt-pbkdf
* https://www.usenix.org/legacy/events/usenix99/provos/provos_html/node1.html
* https://datatracker.ietf.org/doc/html/rfc2898
====
[TIP]
====
You can get a list of supported ciphers (*1.0.0*) via `ssh -Q cipher` on most systems.
Note that *1.0.0* has nothing to do with SSH connections themselves; it's *only* for the encryption of *4.0.1*.
This is likely going to be:
* `3des-cbc`
* `aes128-cbc`
* `aes192-cbc`
* `aes256-cbc`
* `rijndael-cbc@lysator.liu.se` _(may not be present on all systems)_
* `aes128-ctr`
* `aes192-ctr`
* `aes256-ctr`
* `aes128-gcm@openssh.com`
* `aes256-gcm@openssh.com`
* `chacha20-poly1305@openssh.com`
The author recommends using `aes256-ctr`. It is currently the upstream default.
====
[id=struct_ed25519_crypt]
====== Structure
[source,text,linenums]
----
0.0 "openssh-key-v1" string plus terminating nullbyte (15 bytes)
1.0 uint32 allocator for 1.0.0 (4 bytes)
1.0.0 cipher name string (ASCII bytes)
2.0 uint32 allocator for 2.0.0 (4 bytes)
2.0.0 KDF name string (ASCII bytes)
3.0 uint32 allocator for KDF options (3.0.0 to 3.0.1) (4 bytes)
3.0.0 uint32 allocator for 3.0.0.0 (4 bytes)
3.0.0.0 Salt/IV (bytes)
3.0.1 uint32 for number of rounds/"work factor" (4 bytes)
4.0 uint32 counter for # of keys (4 bytes)
4.0.0 uint32 allocator for public key #n (4.0.0.0 to 4.0.0.1) (4 bytes)
4.0.0.0 uint32 allocator for 4.0.0.0.0 (4 bytes)
4.0.0.0.0 public key #n keytype string (ASCII bytes)
4.0.0.1 uint32 allocator for 4.0.0.1.0 (4 bytes)
4.0.0.1.0 public key #n payload (bytes)
4.0.1 uint32 allocator for encrypted private key structure blob #n (4.0.1.0) (4 bytes)
4.0.1.0 <ENCRYPTED BLOB>
----
[NOTE]
====
*Chunk 4.0:* This is technically currently unused; upstream hardcodes to 1 (left zero-padded `0x01`).
*Chunk 4.0.1.0:* When decrypted, this is equivalent to the <<struct_ed25519_plain, plaintext>> *4.0.1.0* to *4.0.1.6*. It uses a padded size appropriate to the encryption cipher used.
====
[id=bytes_ed25519_crypt]
====== Example
The following example, being encrypted, is protected with a passphrase. The passphrase used in this example key is *`test`*.
.`id_ed25519` Format
[source,text,linenums]
----
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBQEy9ykA
1o4KMfnXW28KW8AAAAZAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIL+iAxqlRjET5A4W
iWr1A8Upnq12sJy2OEb0HMTeF0D2AAAAoMSXd80NGn0323ehgUmRJ4+M6Z1XLixma5O5mG
dCXGDaRlL924VVCYUytRvu7ilZ+dtc9aCQUFJyDF3iXyxN2H68x7teo9e8vqzGtzLkw5KV
2Zkal+8/CDj4qb/UPts0AxiWSQiPbPt4lG+5FONYrGq8ZGkQcvXyeIU02dQtf0BrxQkLMN
8jy33YxcuTjkH6zW446IRbgWC/+EBZgRjUR8I=
-----END OPENSSH PRIVATE KEY-----
----
.Structure Reference (Hex) (Decoded Base64)
[source,text,linenums]
----
0.0 6f70656e7373682d6b65792d763100 ("openssh-key-v1" + 0x00)
1.0 0000000a (10)
1.0.0 6165733235362d637472 ("aes256-ctr")
2.0 00000006 (6)
2.0.0 626372797074 ("bcrypt")
3.0 00000018 (24)
3.0.0 00000010 (16)
3.0.0.0 50132f72900d68e0a31f9d75b6f0a5bc (bytes)
3.0.1 00000064 (100)
4.0 00000001 (1)
4.0.0 00000033 (51)
4.0.0.0 0000000b (11)
4.0.0.0.0 7373682d65643235353139 ("ssh-ed25519")
4.0.0.1 00000020 (32)
4.0.0.1.0 bfa2031aa5463113e40e16896af503c5
299ead76b09cb63846f41cc4de1740f6 (bytes)
4.0.1 000000a0 (160)
4.0.1.0 c49777cd0d1a7d37db77a1814991278f
8ce99d572e2c666b93b99867425c60da
4652fddb8555098532b51beeee2959f9
db5cf5a0905052720c5de25f2c4dd87e
bcc7bb5ea3d7bcbeacc6b732e4c39295
d9991a97ef3f0838f8a9bfd43edb3403
189649088f6cfb78946fb914e358ac6a
bc64691072f5f2788534d9d42d7f406b
c5090b30df23cb7dd8c5cb938e41facd
6e38e8845b8160bff840598118d447c2 (AES256-CTR encrypted block) (bytes)
----
[NOTE]
====
The decrypted *4.0.1.0* should match the <<struct_ed25519_plain, plaintext key's structure>> for *4.0.1* through *4.0.1.6*. The padding length WILL change, however, between the two unless using a cipher with an 8-byte block size.
====
When *4.0.1.0* is decrypted, it yields:
.Decrypted *4.0.1.0*
[source,text,linenums]
----
4.0.1.0 f890d89a (4170242202)
4.0.1.1 f890d89a (4170242202)
4.0.1.2 0000000b (11)
4.0.1.2.0 7373682d65643235353139 ("ssh-ed25519")
4.0.1.3 00000020 (32)
4.0.1.3.0 bfa2031aa5463113e40e16896af503c5
299ead76b09cb63846f41cc4de1740f6 (bytes)
4.0.1.4 00000040 (64)
4.0.1.4.0 ce6e2b8d638c9d5219dff455af1a90d0
a5b72694cfcedfb93bc1e1b1816dee98
bfa2031aa5463113e40e16896af503c5
299ead76b09cb63846f41cc4de1740f6 (bytes)
4.0.1.5 00000012 (18)
4.0.1.5.0 5468697320697320612074657374206b6579 ("This is a test key")
4.0.1.6 0102030405060708090a0b ([1 2 3 4 5 6 7 8 9 10 11], 11 bytes)
----
See the <<struct_ed25519_plain, plaintext structure>> for details.

View File

@@ -0,0 +1,3 @@
include::plain.adoc[]
include::encrypted.adoc[]

View File

@@ -0,0 +1,98 @@
===== v1 (Plain)
[TIP]
====
Since plaintext/unencrypted keys do not have a cipher or KDF (as there's no encryption key or algorithm used), they use the string "none" to identify these (and entirely leave out the KDF options).
====
[id=struct_ed25519_plain]
====== Structure
[source,text,linenums]
----
0.0 "openssh-key-v1" string plus terminating nullbyte (15 bytes)
1.0 uint32 allocator for 1.0.0 (4 bytes)
1.0.0 cipher name string (ASCII bytes)
2.0 uint32 allocator for 2.0.0 (4 bytes)
2.0.0 KDF name string (ASCII bytes)
3.0 uint32 allocator for KDF options (3.0.0 to 3.0.1) (4 bytes) (ALWAYS 0 for unencrypted keys, so no following substructure)
4.0 uint32 counter for # of keys (4 bytes)
4.0.0 uint32 allocator for public key #n (4.0.0.0 to 4.0.0.1) (4 bytes)
4.0.0.0 uint32 allocator for 4.0.0.0.0 (4 bytes)
4.0.0.0.0 public key #n keytype string (ASCII bytes)
4.0.0.1 uint32 allocator for 4.0.0.1.0 (4 bytes)
4.0.0.1.0 public key #n payload (bytes)
4.0.1 uint32 allocator for private key structure #n (4.0.1.0 to 4.0.1.5) (4 bytes)
4.0.1.0 uint32 decryption "checksum" #1 (should match 4.0.1.1) (4 bytes)
4.0.1.1 uint32 decryption "checksum" #2 (should match 4.0.1.0) (4 bytes)
4.0.1.2 Copy of 4.0.0.0; allocator for 4.0.1.2.0 (4 bytes)
4.0.1.2.0 Copy of 4.0.0.0.0 (ASCII bytes)
4.0.1.3 Copy of 4.0.0.1; allocator for 4.0.1.3.0 (4 bytes)
4.0.1.3.0 Copy of 4.0.0.1.0 (bytes)
4.0.1.4 uint32 allocator for 4.0.1.4.0 (4 bytes)
4.0.1.4.0 Private key #n (bytes)
4.0.1.5 uint32 allocator for 4.0.1.5.0 (4 bytes)
4.0.1.5.0 comment for key #n string (ASCII bytes)
4.0.1.6 sequential padding
----
[NOTE]
====
*Chunk 3.0.0 to 3.0.1:* These blocks are not present in unencrypted keys (see the <<struct_ed25519_crypt, encrypted key structure>> for what these look like). *3.0* reflects this, as it's always going to be `00000000` (0).
*Chunk 4.0:* This is technically currently unused; upstream hardcodes to 1 (left zero-padded `0x01`).
*Chunk 4.0.1.4.0:* This is a 64-byte block for ED25519, but the second half of the private key (`[32:]`) is always the same as the public key.
*Chunk 4.0.1.6:* The padding used aligns the private key (*4.0.1.0* to *4.0.1.5.0*) to the cipher blocksize. For plaintext keys, a blocksize of 8 is used.
====
[id=bytes_ed25519_plain]
====== Example
.`id_ed25519` Format
[source,text,linenums]
----
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBEOIvJc2hN1mhXExEiv/ISyYO7prFixOl80R9zw52XsAAAAJjPbUqwz21K
sAAAAAtzc2gtZWQyNTUxOQAAACBEOIvJc2hN1mhXExEiv/ISyYO7prFixOl80R9zw52XsA
AAAEBqSF+KwoLTOqI6+TnpcaZY4ckcamLrBF8CvtJbNZflJ0Q4i8lzaE3WaFcTESK/8hLJ
g7umsWLE6XzRH3PDnZewAAAAElRoaXMgaXMgYSB0ZXN0IGtleQECAw==
-----END OPENSSH PRIVATE KEY-----
----
.Structure Reference (Hex) (Decoded Base64)
[source,text,linenums]
----
0.0 6f70656e7373682d6b65792d763100 ("openssh-key-v1" + 0x00)
1.0 00000004 (4)
1.0.0 6e6f6e65 ("none")
2.0 00000004
2.0.0 6e6f6e65 ("none")
3.0 00000000 (0)
4.0 00000001 (1)
4.0.0 00000033 (51)
4.0.0.0 0000000b (11)
4.0.0.0.0 7373682d65643235353139 ("ssh-ed25519")
4.0.0.1 00000020 (32)
4.0.0.1.0 44388bc973684dd66857131122bff212
c983bba6b162c4e97cd11f73c39d97b0 (bytes)
4.0.1 00000098 (141)
4.0.1.0 cf6d4ab0 (3480046256)
4.0.1.1 cf6d4ab0 (3480046256)
4.0.1.2 0000000b (11)
4.0.1.2.0 7373682d65643235353139 ("ssh-ed25519")
4.0.1.3 00000020 (32)
4.0.1.3.0 44388bc973684dd66857131122bff212
c983bba6b162c4e97cd11f73c39d97b0 (bytes)
4.0.1.4 00000040 (64)
4.0.1.4.0 6a485f8ac282d33aa23af939e971a658
e1c91c6a62eb045f02bed25b3597e527
44388bc973684dd66857131122bff212
c983bba6b162c4e97cd11f73c39d97b0 (bytes)
4.0.1.5 00000012 (18)
4.0.1.5.0 5468697320697320612074657374206b6579 ("This is a test key")
4.0.1.6 010203 ([1 2 3], 3 bytes)
----