RFC 4253

The Secure Shell (SSH) Transport Layer Protocol

๐Ÿ“… published January 2006, from ietf

1. Introduction โœจ

okay so the SSH transport layer is a secure, low level transport protocol ๐Ÿ” it gives you strong encryption, cryptographic host authentication, and integrity protection. it's the foundation under everything else, so it's giving infrastructure ๐Ÿ’…

authentication at this layer is host-based. this protocol does not do user authentication ๐Ÿ™ˆ that's a job for a higher level protocol that can be built on top of this one, and honestly that split is so iconic.

the protocol is built to be simple and flexible. it lets the two sides negotiate parameters and it's designed to minimize round-trips ๐Ÿƒโ€โ™€๏ธ the key exchange method, public key algorithm, symmetric encryption algorithm, message authentication algorithm, and hash algorithm are all negotiated. in most environments only 2 round-trips are expected for the full key exchange, server authentication, service request, and acceptance notification of the service request. the worst case is 3 round-trips. not bad at all ๐Ÿฆ‹

2. Contributors ๐Ÿซถ

the major original contributors to this set of documents are Tatu Ylonen, Tero Kivinen, Timo J. Rinne, and Sami Lehtinen (all of SSH Communications Security Corp), plus Markku-Juhani O. Saarinen (University of Jyvaskyla). Darren Moffat was the original editor of this set of documents and also made very substantial contributions ๐Ÿ‘‘

so many people helped shape this over the years. the people who should be acknowledged include Mats Andersson, Ben Harris, Bill Sommerfeld, Brent McClure, Niels Moller, Damien Miller, Derek Fawcus, Frank Cusack, Heikki Nousiainen, Jakob Schlyter, Jeff Van Dyke, Jeffrey Altman, Jeffrey Hutzelman, Jon Bright, Joseph Galbraith, Ken Hornstein, Markus Friedl, Martin Forssen, Nicolas Williams, Niels Provos, Perry Metzger, Peter Gutmann, Simon Josefsson, Simon Tatham, Wei Dai, Denis Bider, der Mouse, and Tadayoshi Kohno ๐ŸŒˆ listing them does not mean they endorse this document, only that they contributed to it. no cap, that's a real legend list.

3. Conventions Used in This Document ๐Ÿ“–

all documents related to the SSH protocols shall use the keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" to describe requirements. these keywords are to be interpreted as described in [RFC2119] ๐ŸŽ€

the keywords "PRIVATE USE", "HIERARCHICAL ALLOCATION", "FIRST COME FIRST SERVED", "EXPERT REVIEW", "SPECIFICATION REQUIRED", "IESG APPROVAL", "IETF CONSENSUS", and "STANDARDS ACTION" that appear in this document when used to describe namespace allocation are to be interpreted as described in [RFC2434] ๐Ÿ—‚๏ธ

protocol fields and the possible values to fill them are defined in this set of documents. the fields get defined inside the message definitions. for example, SSH_MSG_CHANNEL_DATA is defined like this ๐Ÿ‘‡

byte      SSH_MSG_CHANNEL_DATA
uint32    recipient channel
string    data

when fields are referenced in these documents they show up in single quotes, and when values for those fields are referenced they show up in double quotes. using the example above, possible values for 'data' are "foo" and "bar" ๐Ÿ“


4. Connection Setup ๐Ÿ”Œ

SSH works over any 8-bit clean, binary-transparent transport. the underlying transport SHOULD protect against transmission errors, because those errors cause the SSH connection to terminate ๐Ÿ’€

the client is the one who initiates the connection ๐Ÿ“ž

4.1. Use over TCP/IP ๐ŸŒ

when SSH is used over TCP/IP, the server normally listens for connections on port 22. this port number has been registered with the IANA and officially assigned for SSH ๐Ÿฆ‹

4.2. Protocol Version Exchange ๐Ÿงš

once the connection is established, both sides MUST send an identification string. the identification string MUST look like this:

SSH-protoversion-softwareversion SP comments CR LF

since the protocol defined in this set of documents is version 2.0, the 'protoversion' MUST be "2.0". the 'comments' string is OPTIONAL. if you include the 'comments' string, a space character (SP, ASCII 32) MUST separate the 'softwareversion' and 'comments' strings. the identification MUST be terminated by a single Carriage Return (CR) and a single Line Feed (LF) character (ASCII 13 and 10, respectively) โœจ

implementers who want to stay compatible with older, undocumented versions of this protocol may want to process the identification string without expecting the carriage return character. the reasons for that are in Section 5 of this document, so go check it out ๐Ÿ‘€ also, the null character MUST NOT be sent. the maximum length of the string is 255 characters, including the Carriage Return and Line Feed. strict, but it's giving clean ๐Ÿ’…

the part of the identification string before the Carriage Return and Line Feed is used in the Diffie-Hellman key exchange (see Section 8) ๐Ÿ”‘

the server MAY send other lines of data before it sends the version string. each of those lines SHOULD be terminated by a Carriage Return and Line Feed. those lines MUST NOT begin with "SSH-", and they SHOULD be encoded in ISO-10646 UTF-8 [RFC3629] (the language is not specified). clients MUST be able to process those lines. the lines MAY be silently ignored, or MAY be displayed to the client user. if they do get displayed, control character filtering, as discussed in [SSH-ARCH], SHOULD be used. the main reason for this feature is letting TCP-wrappers show an error message before disconnecting ๐Ÿ™

both the 'protoversion' and 'softwareversion' strings MUST consist of printable US-ASCII characters, with the exception of whitespace characters and the minus sign (-). the 'softwareversion' string is mainly used to trigger compatibility extensions and to show what an implementation can do. the 'comments' string SHOULD contain extra information that could help solve user problems. here's an example of a valid identification string ๐Ÿ‘‡

SSH-2.0-billsSSH_3.6.3q3<CR><LF>

this one doesn't have the optional 'comments' string, so it gets terminated by a CR and LF right after the 'softwareversion' string ๐ŸŒธ

key exchange begins immediately after you send this identifier. all packets that follow the identification string SHALL use the binary packet protocol, which is described in Section 6 ๐Ÿ’œ


5. Compatibility With Old SSH Versions ๐Ÿ•ฐ๏ธ

like we said earlier, the 'protoversion' for this protocol is "2.0". earlier versions of this protocol were never formally documented, but everyone knows they use a 'protoversion' of "1.x" (for example "1.5" or "1.3") ๐Ÿ“ผ at the time of writing, lots of SSH implementations are on protocol version 2.0, but devices still running the previous versions definitely exist. during the transition period it matters a lot to work in a way that stays compatible with the installed SSH clients and servers that use the older version of the protocol ๐Ÿซ 

the info in this section only matters for implementations that support compatibility with SSH versions 1.x. for anyone who's curious, the only known documentation of the 1.x protocol lives in README files shipped with the source code [ssh-1.2.30] ๐Ÿ“š

to be continued! part 2 is coming next, bestie ๐Ÿงš๐Ÿ’–

5.1. Old Client, New Server

Okay bestie, so server implementations MAY support a configurable compatibility flag ๐Ÿ’… that lets them talk to old versions. When that flag is on, the server SHOULD identify its 'protoversion' as "1.99" โœจ. Clients using protocol 2.0 MUST be able to read that as identical to "2.0" ๐Ÿซถ. In this mode, the server SHOULD NOT send the Carriage Return character (ASCII 13) after the identification string ๐ŸŒธ.

In compatibility mode, the server SHOULD NOT send any further data after its identification string until it has received an identification string from the client ๐Ÿฆ‹. That way the server can figure out whether the client is using an old protocol, and it can switch back to the old protocol if it needs to ๐Ÿ’–. Also, in compatibility mode the server MUST NOT send additional data before the identification string ๐Ÿ™ˆ.

When you don't need to support old clients, the server MAY send its initial key exchange data right after the identification string ๐ŸŽ€.

5.2. New Client, Old Server

The new client MAY immediately send extra data after its identification string, before it has received the server's identification string ๐Ÿ‘€. So the old protocol might already be corrupt by the time the client finds out the server is old ๐Ÿ˜ญ. When that happens, the client SHOULD close the connection to the server and reconnect using the old protocol ๐Ÿงš.

5.3. Packet Size and Overhead

Some readers will worry about packets getting bigger because of the new headers, padding, and the Message Authentication Code (MAC) ๐Ÿฅบ. The minimum packet size is in the order of 28 bytes (depending on negotiated algorithms) ๐Ÿ’œ. The increase is negligible for large packets, but it's very significant for one-byte packets, like telnet-type sessions ๐Ÿ“. There are, however, several factors that make this a non-issue in almost all cases ๐ŸŒˆ:

  • The minimum size of a TCP/IP header is 32 bytes. Thus, the increase is actually from 33 to 51 bytes (roughly) โœจ.
  • The minimum size of the data field of an Ethernet packet is 46 bytes [RFC0894]. Thus, the increase is no more than 5 bytes. When Ethernet headers are considered, the increase is less than 10 percent ๐Ÿ”ฅ.
  • The total fraction of telnet-type data in the Internet is negligible, even with increased packet sizes ๐Ÿ’….

The only environment where the packet size increase is likely to have a significant effect is PPP [RFC1661] over slow modem lines (PPP compresses the TCP/IP headers, which makes the increase in packet size stand out more) ๐Ÿข. But with modern modems, the transfer time is in the order of 2 milliseconds, which is a lot faster than people can type โšก.

There are also issues related to the maximum packet size ๐Ÿ“ฆ. To keep screen updates from lagging, you don't want excessively large packets for interactive sessions ๐Ÿ‘‘. The maximum packet size is negotiated separately for each channel ๐Ÿซง.

6. Binary Packet Protocol โœจ

Okay so every packet looks like this ๐ŸŽ€:

   uint32    packet_length
   byte      padding_length
   byte[n1]  payload; n1 = packet_length - padding_length - 1
   byte[n2]  random padding; n2 = padding_length
   byte[m]   mac (Message Authentication Code - MAC); m = mac_length
  • packet_length: the length of the packet in bytes, not counting 'mac' or the 'packet_length' field itself ๐Ÿ“.
  • padding_length: the length of 'random padding' in bytes ๐Ÿง.
  • payload: the useful stuff in the packet ๐Ÿ’Œ. If compression has been negotiated, this field gets compressed. At the start, compression MUST be "none" ๐Ÿ™…โ€โ™€๏ธ.
  • random padding: arbitrary-length padding, so that the total length of (packet_length || padding_length || payload || random padding) is a multiple of the cipher block size or 8, whichever is larger ๐ŸŒธ. There MUST be at least four bytes of padding ๐Ÿ’œ. The padding SHOULD consist of random bytes ๐ŸŽฒ. The maximum amount of padding is 255 bytes ๐Ÿซถ.
  • mac: the Message Authentication Code ๐Ÿ”. If message authentication has been negotiated, this field holds the MAC bytes. At the start, the MAC algorithm MUST be "none" ๐Ÿ’–.

Note that the length of the concatenation of 'packet_length', 'padding_length', 'payload', and 'random padding' MUST be a multiple of the cipher block size or 8, whichever is larger ๐Ÿงฉ. This constraint MUST be enforced, even when using stream ciphers ๐Ÿšจ. The 'packet_length' field is also encrypted, so handling it takes some special care when sending or receiving packets ๐Ÿง. Also, adding variable amounts of 'random padding' may help thwart traffic analysis ๐Ÿ•ต๏ธโ€โ™€๏ธ.

The minimum size of a packet is 16 bytes (or the cipher block size, whichever is larger), plus 'mac' ๐Ÿฆ‹. Implementations SHOULD decrypt the length after receiving the first 8 bytes (or the cipher block size, whichever is larger) of a packet ๐Ÿ”“.

6.1. Maximum Packet Length

All implementations MUST be able to process packets with an uncompressed payload length of 32768 bytes or less and a total packet size of 35000 bytes or less (including 'packet_length', 'padding_length', 'payload', 'random padding', and 'mac') ๐ŸŒˆ. The 35000-byte maximum is an arbitrarily chosen value that's bigger than the uncompressed length above ๐ŸŽ€. Implementations SHOULD support longer packets where they might be needed ๐Ÿš€. For example, if an implementation wants to send a huge number of certificates, larger packets MAY be sent if the identification string shows the other party can handle them ๐Ÿ“œ. However, implementations SHOULD check that the packet length is reasonable, so they can avoid denial of service and/or buffer overflow attacks ๐Ÿšจ๐Ÿ˜ญ.

6.2. Compression

If compression has been negotiated, only the 'payload' field gets compressed, using the negotiated algorithm ๐Ÿ—œ๏ธ. The 'packet_length' field and 'mac' are computed from the compressed payload ๐Ÿงฎ. Encryption happens after compression ๐Ÿ”.

Compression MAY be stateful, depending on the method ๐ŸŒ€. Compression MUST be independent for each direction, and implementations MUST allow independent choosing of the algorithm for each direction ๐Ÿ’…. In practice, though, it is RECOMMENDED that the compression method be the same in both directions ๐Ÿซถ.

The following compression methods are currently defined โœจ:

   none     REQUIRED        no compression
   zlib     OPTIONAL        ZLIB (LZ77) compression

The "zlib" compression is described in [RFC1950] and [RFC1951] ๐Ÿ“š. The compression context is initialized after each key exchange and gets passed from one packet to the next, with only a partial flush at the end of each packet ๐Ÿง . A partial flush means the current compressed block ends and all data gets output ๐Ÿ’จ. If the current block is not a stored block, one or more empty blocks are added after it so there are at least 8 bits, counting from the start of the end-of-block code of the current block to the end of the packet payload ๐Ÿงฉ.

Additional methods may be defined as specified in [SSH-ARCH] and [SSH-NUMBERS] ๐ŸŒธ.

6.3. Encryption โœจ

okay so, encryption gets negotiated during the key exchange, along with the actual key ๐Ÿ” once encryption is switched on, the packet length, padding length, payload, and padding fields of every packet MUST be encrypted with the chosen algorithm. no skipping fields, bestie ๐Ÿ’…

all the encrypted data going one way SHOULD be treated as one continuous stream ๐ŸŒŠ so for example, initialization vectors SHOULD carry over from the end of one packet into the start of the next. and all ciphers SHOULD use keys with an effective key length of 128 bits or more ๐Ÿ’œ

the two directions run completely separately ๐Ÿฆ‹ each direction MUST run independently, and if local policy allows more than one algorithm, implementations MUST let each direction pick its own. that said, it is RECOMMENDED that both directions use the same algorithm, because that's what happens in practice ๐Ÿซถ

here's the list of ciphers defined so far ๐ŸŽ€

      3des-cbc         REQUIRED          three-key 3DES in CBC mode
      blowfish-cbc     OPTIONAL          Blowfish in CBC mode
      twofish256-cbc   OPTIONAL          Twofish in CBC mode,
                                         with a 256-bit key
      twofish-cbc      OPTIONAL          alias for "twofish256-cbc"
                                         (this is being retained
                                         for historical reasons)
      twofish192-cbc   OPTIONAL          Twofish with a 192-bit key
      twofish128-cbc   OPTIONAL          Twofish with a 128-bit key
      aes256-cbc       OPTIONAL          AES in CBC mode,
                                         with a 256-bit key
      aes192-cbc       OPTIONAL          AES with a 192-bit key
      aes128-cbc       RECOMMENDED       AES with a 128-bit key
      serpent256-cbc   OPTIONAL          Serpent in CBC mode, with
                                         a 256-bit key
      serpent192-cbc   OPTIONAL          Serpent with a 192-bit key
      serpent128-cbc   OPTIONAL          Serpent with a 128-bit key
      arcfour          OPTIONAL          the ARCFOUR stream cipher
                                         with a 128-bit key
      idea-cbc         OPTIONAL          IDEA in CBC mode
      cast128-cbc      OPTIONAL          CAST-128 in CBC mode
      none             OPTIONAL          no encryption; NOT RECOMMENDED

the "3des-cbc" cipher is three-key triple-DES, run as encrypt, decrypt, then encrypt ๐Ÿ“ the first 8 bytes of the key do the first encryption, the next 8 bytes do the decryption, and the last 8 bytes do the final encryption. that means 24 bytes of key data, though only 168 bits of it are actually used. for CBC mode, outer chaining MUST be used, so there's only ONE initialization vector. it's a block cipher with 8-byte blocks, and it's defined in [FIPS-46-3]. ngl, this one is a little bit of a drama queen ๐Ÿ™ˆ it only has an effective key length of 112 bits ([SCHNEIER]), so it doesn't meet the rule that SSH encryption should use keys of 128 bits or more. BUT it's still REQUIRED for historical reasons! basically every implementation around when this was written supported it, and it's the fundamental interoperable algorithm everyone falls back on. someday another, stronger algorithm will be so prevalent and ubiquitous that "3des-cbc" gets deprecated by another STANDARDS ACTION ๐Ÿ‘‘

the "blowfish-cbc" cipher is Blowfish in CBC mode with 128-bit keys [SCHNEIER] ๐ŸŒธ it's a block cipher with 8-byte blocks.

the "twofish-cbc" or "twofish256-cbc" cipher is Twofish in CBC mode with 256-bit keys, as described in [TWOFISH] โœจ it's a block cipher with 16-byte blocks. "twofish192-cbc" is the same thing with a 192-bit key, and "twofish128-cbc" is the same with a 128-bit key ๐Ÿฆ‹

the "aes256-cbc" cipher is AES (Advanced Encryption Standard) from [FIPS-197], in CBC mode, using a 256-bit key ๐Ÿ’– "aes192-cbc" is the same with a 192-bit key, and "aes128-cbc" is the same with a 128-bit key. iconic consistency ๐Ÿ’…

the "serpent256-cbc" cipher is Serpent in CBC mode with a 256-bit key, as described in the Serpent AES submission ๐Ÿงš "serpent192-cbc" is the same with a 192-bit key, and "serpent128-cbc" is the same with a 128-bit key.

the "arcfour" cipher is the Arcfour stream cipher with 128-bit keys ๐ŸŒˆ it's believed to be compatible with RC4 [SCHNEIER]. but ARCFOUR (and RC4) has problems with weak keys, so it should be used with caution ๐Ÿ’€

the "idea-cbc" cipher is IDEA in CBC mode [SCHNEIER] โญ and "cast128-cbc" is CAST-128 in CBC mode with a 128-bit key [RFC2144] ๐ŸŽ€

and then there's "none" ๐Ÿ™ƒ it means no encryption at all, so it gives NO confidentiality protection, and it is NOT RECOMMENDED. if you pick this one, some stuff like password authentication might get turned off for security reasons. not me going "absolutely not" ๐Ÿ˜ญ

additional methods may be defined as specified in [SSH-ARCH] and [SSH-NUMBERS] ๐Ÿงš

6.4. Data Integrity ๐Ÿ”

okay, data integrity is protected by attaching a MAC to each packet ๐Ÿซถ the MAC is computed from a shared secret, the packet sequence number, and the contents of the packet. no cap, it's giving bodyguard energy ๐Ÿ’ช

the MAC algorithm and key get negotiated during the key exchange. at the very start no MAC is in effect, and its length MUST be zero ๐ŸŒธ once key exchange is done, the 'mac' for the selected algorithm gets computed before encryption, from the concatenation of the packet data:

   mac = MAC(key, sequence_number || unencrypted_packet)

here, unencrypted_packet is the entire packet minus the 'mac' (so the length fields, 'payload', and 'random padding'), and sequence_number is an implicit packet sequence number stored as a uint32 ๐Ÿ”ข it starts at zero for the first packet and goes up by one after EVERY packet, whether or not encryption or a MAC is on. it's never reset, not even if keys or algorithms get renegotiated later ๐Ÿ‘‘ it wraps back to zero after every 2^32 packets. and the sequence_number itself never goes over the wire, so it's a secret little sidekick ๐Ÿคซ

the MAC algorithms for each direction MUST run independently, and implementations MUST allow picking the algorithm separately for both directions. again, in practice it is RECOMMENDED that both directions use the same algorithm ๐Ÿฆ‹

the value of 'mac' MUST be sent unencrypted as the LAST part of the packet ๐ŸŒˆ how many 'mac' bytes you get depends on the algorithm you chose.

the MAC algorithms currently defined are ๐ŸŽ€

      hmac-sha1    REQUIRED        HMAC-SHA1 (digest length = key
                                   length = 20)
      hmac-sha1-96 RECOMMENDED     first 96 bits of HMAC-SHA1 (digest
                                   length = 12, key length = 20)
      hmac-md5     OPTIONAL        HMAC-MD5 (digest length = key
                                   length = 16)
      hmac-md5-96  OPTIONAL        first 96 bits of HMAC-MD5 (digest
                                   length = 12, key length = 16)
      none         OPTIONAL        no MAC; NOT RECOMMENDED

the "hmac-" algorithms are described in [RFC2104] โœจ and the "-n" MACs just use the first n bits of the result. SHA-1 is described in [FIPS-180-2], and MD5 is described in [RFC1321] ๐Ÿ“

additional methods may be defined, as specified in [SSH-ARCH] and [SSH-NUMBERS] ๐Ÿงš

6.5. Key Exchange Methods ๐Ÿ”‘

the key exchange method is how the one-time session keys get generated for encryption and authentication, and how server authentication happens ๐Ÿ’–

two key exchange methods are REQUIRED, and they're the must-haves ๐Ÿ‘‘

      diffie-hellman-group1-sha1 REQUIRED
      diffie-hellman-group14-sha1 REQUIRED

both of these are described in Section 8 ๐ŸŒธ

additional methods may be defined as specified in [SSH-NUMBERS] ๐Ÿงš the name "diffie-hellman-group1-sha1" is used for a key exchange method using an Oakley group, as defined in [RFC2409]. SSH keeps its own group identifier space, which is logically separate from Oakley [RFC2412] and IKE. but for one extra group, the Working Group adopted the number assigned by [RFC3526], and that group got the name diffie-hellman-group14-sha1 ๐Ÿซถ implementations should treat these names as opaque identifiers, and they should not assume any relationship between the groups used by SSH and the groups defined for IKE. no peeking, bestie ๐Ÿ™ˆ

6.6. Public Key Algorithms ๐Ÿ”‘โœจ

okay bestie, this protocol is built to work with almost any public key format, encoding, and algorithm (signing and/or encryption) ๐Ÿฆ‹ it's giving flexible!!

there are a few things that define a public key type:

  • Key format ๐ŸŽ€: how the key is encoded and how certificates are represented. The key blobs in this protocol MAY contain certificates in addition to keys.
  • Signature and/or encryption algorithms ๐Ÿ’…: some key types can't do both signing and encryption. Policy statements (like the ones in certificates) can also restrict how a key gets used. In that case, different key types SHOULD be defined for the different policy alternatives.
  • Encoding of signatures and/or encrypted data ๐ŸŒธ: this includes (but isn't limited to) padding, byte order, and data formats.

these public key and/or certificate formats are defined right now ๐Ÿ‘‘

ssh-dss           REQUIRED     sign   Raw DSS Key
ssh-rsa           RECOMMENDED  sign   Raw RSA Key
pgp-sign-rsa      OPTIONAL     sign   OpenPGP certificates (RSA key)
pgp-sign-dss      OPTIONAL     sign   OpenPGP certificates (DSS key)

more key types can be defined too, as specified in [SSH-ARCH] and in [SSH-NUMBERS] ๐ŸŒˆ

the key type MUST always be explicitly known (from algorithm negotiation or some other source) ๐Ÿ™ˆ it's normally not included in the key blob, so don't go looking for it there!

certificates and public keys are encoded like this ๐Ÿงš

string    certificate or public key format identifier
byte[n]   key/certificate data

the certificate part can be a zero length string, but a public key is required. That public key is the one used for authentication ๐Ÿ” the certificate sequence inside the certificate blob can be used to provide authorization โœจ

public key/certificate formats that don't explicitly specify a signature format identifier MUST use the public key/certificate format identifier as the signature identifier ๐Ÿ’œ

signatures are encoded like this ๐Ÿ“

string    signature format identifier (as specified by the
                public key/certificate format)
byte[n]   signature blob in format specific encoding.

the "ssh-dss" key format has this specific encoding ๐Ÿ’–

string    "ssh-dss"
mpint     p
mpint     q
mpint     g
mpint     y

here, the 'p', 'q', 'g', and 'y' parameters form the signature key blob ๐Ÿซถ

signing and verifying with this key format is done according to the Digital Signature Standard [FIPS-186-2], using the SHA-1 hash [FIPS-180-2] ๐Ÿ”ฅ

the resulting signature is encoded like this ๐ŸŒท

string    "ssh-dss"
string    dss_signature_blob

the value for 'dss_signature_blob' is encoded as a string containing r, followed by s. These are 160-bit integers, with no lengths or padding, unsigned, and in network byte order ๐Ÿงฎ

the "ssh-rsa" key format has this specific encoding ๐ŸŽ€

string    "ssh-rsa"
mpint     e
mpint     n

here the 'e' and 'n' parameters form the signature key blob ๐Ÿฆ‹

signing and verifying with this key format is done according to the RSASSA-PKCS1-v1_5 scheme in [RFC3447], using the SHA-1 hash ๐Ÿ’…

the resulting signature is encoded like this ๐ŸŒธ

string    "ssh-rsa"
string    rsa_signature_blob

the value for 'rsa_signature_blob' is encoded as a string containing s. This is an integer, with no lengths or padding, unsigned, and in network byte order ๐Ÿ‘‘

the "pgp-sign-rsa" method says the certificates, the public key, and the signature are all in OpenPGP compatible binary format ([RFC2440]) ๐ŸŒˆ it also tells you the key is an RSA key โญ

the "pgp-sign-dss" method works the same way, but tells you the key is a DSS key ๐Ÿ’€


7. Key Exchange โœจ

okay so key exchange (kex) kicks off with each side sending name-lists of the algorithms it supports ๐Ÿ’Œ each side has a preferred algorithm in every category, and it's assumed that most implementations will be using the same preferred algorithm at any given time ๐Ÿซถ each side MAY guess which algorithm the other side is using, and MAY send an initial key exchange packet that matches that algorithm, if that fits the preferred method ๐Ÿ”ฎ

the guess is considered wrong if:

  • the kex algorithm and/or the host key algorithm was guessed wrong (the server and client have different preferred algorithms), or
  • any of the other algorithms can't be agreed upon (the procedure is defined below in Section 7.1) ๐Ÿ˜ญ

otherwise, the guess is considered right, and the optimistically sent packet MUST be handled as the first key exchange packet ๐ŸŽ‰

but if the guess was wrong, and one or both parties optimistically sent a packet, those packets MUST be ignored (even if the error in the guess wouldn't change the contents of the initial packet(s)) ๐Ÿ™…โ€โ™€๏ธ and the appropriate side MUST send the correct initial packet ๐Ÿ’ซ

a key exchange method uses explicit server authentication if the key exchange messages include a signature or other proof of the server's authenticity ๐Ÿชช a key exchange method uses implicit server authentication if, to prove its authenticity, the server also has to prove that it knows the shared secret, K, by sending a message and a corresponding MAC that the client can verify ๐Ÿ•ต๏ธโ€โ™€๏ธ

the key exchange method defined by this document uses explicit server authentication ๐Ÿ’– however, key exchange methods with implicit server authentication MAY be used with this protocol ๐ŸŒ™ after a key exchange with implicit server authentication, the client MUST wait for a response to its service request message before sending any further data ๐Ÿ›‘ no skipping ahead, bestie!!

7.1. Algorithm Negotiation

okay so key exchange starts with each side sending this packet ๐Ÿ’Œ

   byte         SSH_MSG_KEXINIT
   byte[16]     cookie (random bytes)
   name-list    kex_algorithms
   name-list    server_host_key_algorithms
   name-list    encryption_algorithms_client_to_server
   name-list    encryption_algorithms_server_to_client
   name-list    mac_algorithms_client_to_server
   name-list    mac_algorithms_server_to_client
   name-list    compression_algorithms_client_to_server
   name-list    compression_algorithms_server_to_client
   name-list    languages_client_to_server
   name-list    languages_server_to_client
   boolean      first_kex_packet_follows
   uint32       0 (reserved for future extension)

Every algorithm name-list MUST be a comma-separated list of algorithm names ๐ŸŽ€ (check out Algorithm Naming in [SSH-ARCH] and the extra info in [SSH-NUMBERS]). Each supported (allowed) algorithm MUST be listed in order of preference, from most to least. Iconic behavior, honestly ๐Ÿ’…

The first algorithm in each name-list MUST be the preferred (guessed) algorithm, and each name-list MUST contain at least one algorithm name. No empty lists, bestie ๐Ÿ™ˆ

cookie

The 'cookie' MUST be a random value generated by the sender. Its whole purpose is to make it impossible for either side to fully determine the keys and the session identifier ๐Ÿ”โœจ

kex_algorithms

Key exchange algorithms were defined above. The first algorithm MUST be the preferred (and guessed) algorithm. If both sides make the same guess, that algorithm MUST be used. Otherwise, the following algorithm MUST be used to choose a key exchange method: iterate over the client's kex algorithms, one at a time, and choose the first algorithm that satisfies these conditions:

  • the server also supports the algorithm,
  • if the algorithm requires an encryption-capable host key, there is an encryption-capable algorithm on the server's server_host_key_algorithms that is also supported by the client, and
  • if the algorithm requires a signature-capable host key, there is a signature-capable algorithm on the server's server_host_key_algorithms that is also supported by the client.

If no algorithm satisfying all these conditions can be found, the connection fails, and both sides MUST disconnect. Rip, no vibes ๐Ÿ’€

server_host_key_algorithms

This is a name-list of the algorithms supported for the server host key. The server lists the algorithms it has host keys for, and the client lists the algorithms it's willing to accept. There MAY be multiple host keys for a host, possibly with different algorithms ๐Ÿ—๏ธ

Some host keys may not support both signatures and encryption (you can tell from the algorithm), so not every host key works for every key exchange method ๐Ÿ™ƒ

Algorithm selection depends on whether the chosen key exchange algorithm needs a signature or an encryption-capable host key. It MUST be possible to determine this from the public key algorithm name. The first algorithm on the client's name-list that meets the requirements and is also supported by the server MUST be chosen. If there is no such algorithm, both sides MUST disconnect.

encryption_algorithms

This is a name-list of acceptable symmetric encryption algorithms (also known as ciphers), in order of preference. The chosen encryption algorithm for each direction MUST be the first algorithm on the client's name-list that is also on the server's name-list. If there is no such algorithm, both sides MUST disconnect.

Note that "none" must be explicitly listed if it is to be acceptable. The defined algorithm names are listed in Section 6.3. ๐Ÿ‘€

mac_algorithms

This is a name-list of acceptable MAC algorithms in order of preference. The chosen MAC algorithm MUST be the first algorithm on the client's name-list that is also on the server's name-list. If there is no such algorithm, both sides MUST disconnect.

Note that "none" must be explicitly listed if it is to be acceptable. The MAC algorithm names are listed in Section 6.4. ๐Ÿ”

compression_algorithms

This is a name-list of acceptable compression algorithms in order of preference. The chosen compression algorithm MUST be the first algorithm on the client's name-list that is also on the server's name-list. If there is no such algorithm, both sides MUST disconnect.

Note that "none" must be explicitly listed if it is to be acceptable. The compression algorithm names are listed in Section 6.2. ๐Ÿ—œ๏ธ

languages

This is a name-list of language tags in order of preference [RFC3066]. Both parties MAY ignore this name-list. If there are no language preferences, this name-list SHOULD be empty, as defined in Section 5 of [SSH-ARCH]. Language tags SHOULD NOT be present unless the sending party knows they're needed ๐ŸŒ

first_kex_packet_follows

This indicates whether a guessed key exchange packet follows. If a guessed packet will be sent, this MUST be TRUE. If no guessed packet will be sent, this MUST be FALSE.

After receiving the SSH_MSG_KEXINIT packet from the other side, each party will know whether their guess was right. If the other party's guess was wrong and this field was TRUE, the next packet MUST be silently ignored, and both sides MUST then act as determined by the negotiated key exchange method. If the guess was right, key exchange MUST continue using the guessed packet. Main character plot twist energy ๐ŸŽญ

After the SSH_MSG_KEXINIT message exchange, the key exchange algorithm runs. It may involve several packet exchanges, as specified by the key exchange method.

Once a party has sent an SSH_MSG_KEXINIT message for key exchange or re-exchange, it MUST NOT send any messages other than the following until it has sent an SSH_MSG_NEWKEYS message (Section 7.3). โš ๏ธ
  • Transport layer generic messages (1 to 19) (but SSH_MSG_SERVICE_REQUEST and SSH_MSG_SERVICE_ACCEPT MUST NOT be sent);
  • Algorithm negotiation messages (20 to 29) (but further SSH_MSG_KEXINIT messages MUST NOT be sent);
  • Specific key exchange method messages (30 to 49).

The provisions of Section 11 apply to unrecognized messages.

Note, however, that during a key re-exchange, after sending an SSH_MSG_KEXINIT message, each party MUST be prepared to process an arbitrary number of messages that may be in-flight before receiving an SSH_MSG_KEXINIT message from the other party. Chaos but make it structured ๐ŸŒช๏ธ๐ŸŽ€

7.2. Output from Key Exchange

The key exchange produces two values: a shared secret K, and an exchange hash H. Encryption and authentication keys get derived from these ๐Ÿ”‘. The exchange hash H from the first key exchange is also used as the session identifier, which is a unique identifier for this connection. Authentication methods use it as part of the data that gets signed as proof of possession of a private key. Once computed, the session identifier does not change, even if keys are later re-exchanged. Iconic permanence ๐Ÿ’œ

Each key exchange method specifies a hash function that gets used in the key exchange. The same hash algorithm MUST be used in key derivation. Here, we'll call it HASH. ๐Ÿงฎ

Encryption keys MUST be computed as HASH, of a known value and K, as follows:

  • Initial IV client to server: HASH(K || H || "A" || session_id) (Here K is encoded as mpint and "A" as byte and session_id as raw data. "A" means the single character A, ASCII 65.)
  • Initial IV server to client: HASH(K || H || "B" || session_id)
  • Encryption key client to server: HASH(K || H || "C" || session_id)
  • Encryption key server to client: HASH(K || H || "D" || session_id)
  • Integrity key client to server: HASH(K || H || "E" || session_id)
  • Integrity key server to client: HASH(K || H || "F" || session_id)

Key data MUST be taken from the beginning of the hash output. As many bytes as needed are taken from the beginning of the hash value. If the key length needed is longer than the output of HASH, the key is extended by computing HASH of the concatenation of K, H, and the entire key so far, then appending the resulting bytes (as many as HASH generates) to the key. This repeats until there's enough key material, and the key is taken from the beginning of this value. In other words:

   K1 = HASH(K || H || X || session_id)   (X is e.g., "A")
   K2 = HASH(K || H || K1)
   K3 = HASH(K || H || K1 || K2)
   ...
   key = K1 || K2 || K3 || ...
This process will lose entropy if the amount of entropy in K is larger than the internal state size of HASH. ๐Ÿ˜ฌ

7.3. Taking Keys Into Use

Key exchange ends when each side sends an SSH_MSG_NEWKEYS message. This message is sent with the old keys and algorithms. All messages sent after it MUST use the new keys and algorithms. ๐Ÿ”„

When this message is received, the new keys and algorithms MUST be used for receiving.

The purpose of this message is to make sure a party can still respond with an SSH_MSG_DISCONNECT message that the other party understands if something goes wrong with the key exchange. Safety net, bestie ๐Ÿซถ

   byte      SSH_MSG_NEWKEYS

8. Diffie-Hellman Key Exchange โœจ

okay so the Diffie-Hellman (DH) key exchange gives you a shared secret that neither party could figure out alone ๐Ÿ” and it's combined with a signature made with the host key, so you get host authentication too. this method gives you explicit server authentication, as defined in Section 7. iconic โœจ

here's the setup. C is the client, S is the server, p is a large safe prime, g is a generator for a subgroup of GF(p), and q is the order of that subgroup. V_S is S's identification string and V_C is C's identification string. K_S is S's public host key. I_C is C's SSH_MSG_KEXINIT message and I_S is S's SSH_MSG_KEXINIT message, and both have already been exchanged before this part begins ๐Ÿฆ‹

  1. C picks a random number x (1 < x < q) and computes e = g^x mod p. then C sends e to S.
  2. S picks a random number y (0 < y < q) and computes f = g^y mod p. S receives e, then computes K = e^y mod p and H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K) (these elements are encoded according to their types, see below). S also makes a signature s on H with its private host key, and sends (K_S || f || s) to C. the signing operation may involve a second hashing operation ๐Ÿ’…
  3. C checks that K_S really is the host key for S (for example, with certificates or a local database). C is also allowed to accept the key without verifying it, but doing that will make the protocol insecure against active attacks. it might still be desirable for practical reasons in the short term in many environments, so sometimes people do it ๐Ÿ™ˆ then C computes K = f^x mod p and H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K), and verifies the signature s on H.
values of 'e' or 'f' that are not in the range [1, p-1] MUST NOT be sent or accepted by either side. if that rule gets broken, the key exchange fails. no vibes allowed ๐Ÿ’€

this is implemented with the following messages. the hash algorithm used to compute the exchange hash is defined by the method name, and it's called HASH. the public key algorithm for signing is negotiated in the SSH_MSG_KEXINIT messages ๐ŸŒธ

first, the client sends this:

byte      SSH_MSG_KEXDH_INIT
mpint     e

then the server responds with this:

byte      SSH_MSG_KEXDH_REPLY
string    server public host key and certificates (K_S)
mpint     f
string    signature of H

the hash H is the HASH hash of the concatenation of the following:

string    V_C, the client's identification string (CR and LF
          excluded)
string    V_S, the server's identification string (CR and LF
          excluded)
string    I_C, the payload of the client's SSH_MSG_KEXINIT
string    I_S, the payload of the server's SSH_MSG_KEXINIT
string    K_S, the host key
mpint     e, exchange value sent by the client
mpint     f, exchange value sent by the server
mpint     K, the shared secret

this value is called the exchange hash, and it's what authenticates the key exchange. the exchange hash SHOULD be kept secret ๐Ÿคซ

the signature algorithm MUST be applied over H, not the original data. most signature algorithms already include hashing and some extra padding (e.g., "ssh-dss" specifies SHA-1 hashing). so in that case the data is first hashed with HASH to compute H, and then H gets hashed with SHA-1 as part of the signing operation. it's giving layers ๐Ÿง

8.1. diffie-hellman-group1-sha1

the "diffie-hellman-group1-sha1" method is DH key exchange with SHA-1 as HASH, using Oakley Group 2 [RFC2409] (the 1024-bit MODP Group). this method MUST be supported for interoperability, because all of the known implementations currently support it. ngl the name is kind of a plot twist: it says "group1" even though it actually uses Oakley Group 2 ๐Ÿ™ƒ

8.2. diffie-hellman-group14-sha1

the "diffie-hellman-group14-sha1" method is a Diffie-Hellman key exchange with SHA-1 as HASH and Oakley Group 14 [RFC3526] (the 2048-bit MODP Group). it MUST also be supported ๐Ÿ’–

9. Key Re-Exchange

key re-exchange starts when someone sends an SSH_MSG_KEXINIT packet while they aren't already doing a key exchange (as described in Section 7.1). when that message is received, a party MUST respond with its own SSH_MSG_KEXINIT message, unless the SSH_MSG_KEXINIT it got was already a reply. either party MAY start the re-exchange, but roles MUST NOT be changed. the server stays the server and the client stays the client, no role swaps ๐Ÿ‘‘

the re-exchange uses whatever encryption was in effect when the exchange started. encryption, compression, and MAC methods don't change until a new SSH_MSG_NEWKEYS is sent after the key exchange (just like the initial one). the re-exchange gets processed exactly like the initial key exchange, except the session identifier stays the same. it's totally allowed to change some or all of the algorithms during the re-exchange, and host keys can change too ๐Ÿฆ‹ all keys and initialization vectors get recomputed after the exchange, and the compression and encryption contexts get reset.

it is RECOMMENDED that the keys be changed after each gigabyte of transmitted data or after each hour of connection time, whichever comes sooner. BUT the re-exchange is a public key operation, so it takes a fair amount of processing power and should not be performed too often. main character energy means not overdoing it ๐Ÿง 

more application data can be sent after the SSH_MSG_NEWKEYS packet has been sent. the key exchange doesn't affect the protocols that sit above the SSH transport layer, so your stuff keeps flowing โœจ

10. Service Request

after the key exchange, the client requests a service. each service is identified by a name. the format of names, and the procedures for defining new names, are defined in [SSH-ARCH] and [SSH-NUMBERS] ๐Ÿ“–

right now, these names are reserved:

ssh-userauth
ssh-connection

service names follow a similar local naming policy to the one used for algorithm names. a local service should use the PRIVATE USE syntax of "servicename@domain" ๐ŸŽ€

byte      SSH_MSG_SERVICE_REQUEST
string    service name

if the server rejects the service request, it SHOULD send an appropriate SSH_MSG_DISCONNECT message, and it MUST disconnect. ๐Ÿ’€

when the service starts, it may have access to the session identifier that was generated during the key exchange ๐ŸŒˆ

if the server supports the service (and lets the client use it), it MUST respond with this:

byte      SSH_MSG_SERVICE_ACCEPT
string    service name

message numbers used by services should be in the area reserved for them (see [SSH-ARCH] and [SSH-NUMBERS]). the transport level keeps processing its own messages, so they don't get lost in the shuffle ๐Ÿงš

note that after a key exchange with implicit server authentication, the client MUST wait for a response to its service request message before sending any further data. patience is a virtue, bestie ๐Ÿซถ

11. Additional Messages

either party may send any of the following messages at any time ๐Ÿ’œ

11.1. Disconnection Message

byte      SSH_MSG_DISCONNECT
uint32    reason code
string    description in ISO-10646 UTF-8 encoding [RFC3629]
string    language tag [RFC3066]

this message causes an immediate termination of the connection. all implementations MUST be able to process this message, and they SHOULD be able to send it. ๐Ÿšจ

the sender MUST NOT send or receive any data after this message, and the recipient MUST NOT accept any data after receiving it. the Disconnection Message 'description' string gives a more specific explanation in human-readable form. the Disconnection Message 'reason code' gives the reason in a more machine-readable format (suitable for localization). it can have the values shown in the table below. the decimal representation is shown in the table for readability, but the values are actually uint32 values ๐Ÿ”ข

        Symbolic name                                reason code
        -------------                                -----------
   SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT             1
   SSH_DISCONNECT_PROTOCOL_ERROR                          2
   SSH_DISCONNECT_KEY_EXCHANGE_FAILED                     3
   SSH_DISCONNECT_RESERVED                                4
   SSH_DISCONNECT_MAC_ERROR                               5
   SSH_DISCONNECT_COMPRESSION_ERROR                       6
   SSH_DISCONNECT_SERVICE_NOT_AVAILABLE                   7
   SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED          8
   SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE                 9
   SSH_DISCONNECT_CONNECTION_LOST                        10
   SSH_DISCONNECT_BY_APPLICATION                         11
   SSH_DISCONNECT_TOO_MANY_CONNECTIONS                   12
   SSH_DISCONNECT_AUTH_CANCELLED_BY_USER                 13
   SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE         14
   SSH_DISCONNECT_ILLEGAL_USER_NAME                      15

if the 'description' string gets displayed, the control character filtering discussed in [SSH-ARCH] should be used to avoid attacks that send terminal control characters. this is a real safety thing, so don't skip it ๐Ÿ™ˆ

requests for assignments of new Disconnection Message 'reason code' values (and the associated 'description' text) in the range of 0x00000010 to 0xFDFFFFFF MUST be done through the IETF CONSENSUS method, as described in [RFC2434]. the Disconnection Message 'reason code' values in the range of 0xFE000000 through 0xFFFFFFFF are reserved for PRIVATE USE. as noted, the actual instructions to the IANA are in [SSH-NUMBERS] ๐Ÿ“‹

11.2. Ignored Data Message

byte      SSH_MSG_IGNORE
string    data

all implementations MUST understand (and ignore) this message at any time after receiving the identification string. no implementation is required to send them. this message can be used as an extra protection measure against advanced traffic analysis techniques ๐Ÿ•ต๏ธโ€โ™€๏ธโœจ

11.3. Debug Message

byte      SSH_MSG_DEBUG
boolean   always_display
string    message in ISO-10646 UTF-8 encoding [RFC3629]
string    language tag [RFC3066]

all implementations MUST understand this message, but they're allowed to ignore it. it's used to send information that may help with debugging ๐Ÿ› if 'always_display' is TRUE, the message SHOULD be displayed. otherwise, it SHOULD NOT be displayed unless the user has explicitly asked for debugging information ๐Ÿค“

the 'message' doesn't need to contain a newline. it is, however, allowed to be made of multiple lines separated by CRLF (Carriage Return - Line Feed) pairs ๐Ÿ“

if the 'message' string gets displayed, the terminal control character filtering discussed in [SSH-ARCH] should be used to avoid attacks that send terminal control characters. same energy as before, bestie, don't skip it ๐Ÿ’…

11.4. Reserved Messages

an implementation MUST respond to all unrecognized messages with an SSH_MSG_UNIMPLEMENTED message, in the order the messages were received. those messages MUST be otherwise ignored. later protocol versions may define other meanings for these message types ๐Ÿ”ฎ

byte      SSH_MSG_UNIMPLEMENTED
uint32    packet sequence number of rejected message

12. Summary of Message Numbers ๐Ÿ”ขโœจ

okay so this is the cheat sheet bestie ๐Ÿซถ every message and its number, all in one place:

SSH_MSG_DISCONNECT             1
SSH_MSG_IGNORE                 2
SSH_MSG_UNIMPLEMENTED          3
SSH_MSG_DEBUG                  4
SSH_MSG_SERVICE_REQUEST        5
SSH_MSG_SERVICE_ACCEPT         6
SSH_MSG_KEXINIT                20
SSH_MSG_NEWKEYS                21

ngl the gap between 21 and 30 is giving "saving room for later" ๐ŸŒธ and numbers 30-49 are reserved for kex packets ๐Ÿ”‘ different kex methods are allowed to reuse those same numbers, so the number alone doesn't tell you which method is in use ๐Ÿ’…


13. IANA Considerations ๐Ÿ“‹๐Ÿ’–

this one's a little plot twist ๐Ÿงš this document is part of a set, so the IANA stuff for the whole SSH protocol is spread out across [SSH-ARCH], [SSH-USERAUTH], [SSH-CONNECT], and this document, and all the details live in [SSH-NUMBERS] ๐ŸŽ€


14. Security Considerations ๐Ÿ”๐Ÿ˜ญ

okay this section is serious business, no cap ๐Ÿ’€ this protocol gives you a secure encrypted channel over a network that is NOT secure (the internet is kinda chaotic lol). it does server host authentication, key exchange, encryption, and integrity protection all in one go ๐Ÿ›ก๏ธ it also comes up with a unique session ID that higher-level protocols can use ๐Ÿ”‘โœจ

the full security considerations are in [SSH-ARCH], so go read that one too, periodt ๐Ÿ“–๐Ÿ’œ


15. References ๐Ÿ“š๐ŸŒˆ

15.1. Normative References ๐Ÿ’œ

  • [SSH-ARCH] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) Protocol Architecture", RFC 4251, January 2006.
  • [SSH-USERAUTH] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) Authentication Protocol", RFC 4252, January 2006.
  • [SSH-CONNECT] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) Connection Protocol", RFC 4254, January 2006.
  • [SSH-NUMBERS] Lehtinen, S. and C. Lonvick, Ed., "The Secure Shell (SSH) Protocol Assigned Numbers", RFC 4250, January 2006.
  • [RFC1321] Rivest, R., "The MD5 Message-Digest Algorithm ", RFC 1321, April 1992.
  • [RFC1950] Deutsch, P. and J-L. Gailly, "ZLIB Compressed Data Format Specification version 3.3", RFC 1950, May 1996.
  • [RFC1951] Deutsch, P., "DEFLATE Compressed Data Format Specification version 1.3", RFC 1951, May 1996.
  • [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, February 1997.
  • [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [RFC2144] Adams, C., "The CAST-128 Encryption Algorithm", RFC 2144, May 1997.
  • [RFC2409] Harkins, D. and D. Carrel, "The Internet Key Exchange (IKE)", RFC 2409, November 1998.
  • [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
  • [RFC2440] Callas, J., Donnerhacke, L., Finney, H., and R. Thayer, "OpenPGP Message Format", RFC 2440, November 1998.
  • [RFC3066] Alvestrand, H., "Tags for the Identification of Languages", BCP 47, RFC 3066, January 2001.
  • [RFC3447] Jonsson, J. and B. Kaliski, "Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1", RFC 3447, February 2003.
  • [RFC3526] Kivinen, T. and M. Kojo, "More Modular Exponential (MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)", RFC 3526, May 2003.
  • [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, November 2003.
  • [FIPS-180-2] US National Institute of Standards and Technology, "Secure Hash Standard (SHS)", Federal Information Processing Standards Publication 180-2, August 2002.
  • [FIPS-186-2] US National Institute of Standards and Technology, "Digital Signature Standard (DSS)", Federal Information Processing Standards Publication 186-2, January 2000.
  • [FIPS-197] US National Institute of Standards and Technology, "Advanced Encryption Standard (AES)", Federal Information Processing Standards Publication 197, November 2001.
  • [FIPS-46-3] US National Institute of Standards and Technology, "Data Encryption Standard (DES)", Federal Information Processing Standards Publication 46-3, October 1999.
  • [SCHNEIER] Schneier, B., "Applied Cryptography Second Edition: protocols algorithms and source in code in C", John Wiley and Sons, New York, NY, 1996.
  • [TWOFISH] Schneier, B., "The Twofish Encryptions Algorithm: A 128-Bit Block Cipher, 1st Edition", March 1999.

15.2. Informative References ๐Ÿงš

  • [RFC0894] Hornig, C., "Standard for the transmission of IP datagrams over Ethernet networks", STD 41, RFC 894, April 1984.
  • [RFC1661] Simpson, W., "The Point-to-Point Protocol (PPP)", STD 51, RFC 1661, July 1994.
  • [RFC2412] Orman, H., "The OAKLEY Key Determination Protocol", RFC 2412, November 1998.
  • [ssh-1.2.30] Ylonen, T., "ssh-1.2.30/RFC", File within compressed tarball ftp://ftp.funet.fi/pub/unix/security/login/ssh/ssh-1.2.30.tar.gz, November 1995.

Authors' Addresses ๐Ÿก๐Ÿ’Œ

Tatu Ylonen
SSH Communications Security Corp
Valimotie 17
00380 Helsinki
Finland

EMail: ylo@ssh.com


Chris Lonvick (editor)
Cisco Systems, Inc.
12515 Research Blvd.
Austin  78759
USA

EMail: clonvick@cisco.com

Trademark Notice ๐Ÿท๏ธ

"ssh" is a registered trademark in the United States and/or other countries. โ„ข๏ธ bestie knows whose name is on it ๐Ÿ’…


Copyright (C) The Internet Society (2006).

This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.

This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.


Intellectual Property ๐Ÿฆ‹

The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.

Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.

The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.


Acknowledgement ๐ŸŒท

Funding for the RFC Editor function is provided by the IETF Administrative Support Activity (IASA). ๐Ÿซถ๐ŸŒˆ

๐Ÿ“ฆ where this page comes from