diff options
| -rw-r--r-- | design/68723-crypto-ssh-v2.md | 41 | ||||
| -rw-r--r-- | design/68723/ssh.html | 74 |
2 files changed, 83 insertions, 32 deletions
diff --git a/design/68723-crypto-ssh-v2.md b/design/68723-crypto-ssh-v2.md index e1b2957..8827f14 100644 --- a/design/68723-crypto-ssh-v2.md +++ b/design/68723-crypto-ssh-v2.md @@ -379,6 +379,47 @@ type ExtendedAgent interface { } ``` +### Add PrivateKeySigner + +`PrivateKeySigner` is a `Signer` that can also return the associated `crypto.Signer`. +This means `ParseRawPrivateKey` and `ParseRawPrivateKeyWithPassphrase` can be private now because `ParsePrivateKey` and `ParsePrivateKeyWithPassphrase` return both a `Signer` and a `crypto.Signer`. + +```go +// PrivateKeySigner is a [ssh.Signer] that can also return the associated +// [crypto.Signer]. +type PrivateKeySigner struct { + Signer +} + +func (k *PrivateKeySigner) CryptoSigner() crypto.Signer + +func ParsePrivateKey(pemBytes []byte) (*PrivateKeySigner, error) + +func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (*PrivateKeySigner, error) +``` + +### Add MarshalPrivateKeyOptions + +Instead of passing options as function parameters to `MarshalPrivateKey` add a struct for options. + +```go +// MarshalPrivateKeyOptions defines the available options to Marshal a private +// key in OpenSSH format. +type MarshalPrivateKeyOptions struct { + Comment string + Passphrase string + SaltRounds int +} +``` + +And change `MarshalPrivateKey` like this. + +```go +func MarshalPrivateKey(key crypto.PrivateKey, options MarshalPrivateKeyOptions) (*pem.Block, error) +``` + +This way we can remove `MarshalPrivateKeyWithPassphrase` because the passphrase is now an option. We can easily add support for other options, for example making salt rounds confgurable, see [golang/go#68700](https://github.com/golang/go/issues/68700). + ### Deprecated API and algorithms removal We'll remove DSA support, see [here](https://lists.mindrot.org/pipermail/openssh-unix-announce/2024-January/000156.html) for DSA status in OpenSSH, it is already disabled by default and will be removed in January, 2025. diff --git a/design/68723/ssh.html b/design/68723/ssh.html index c079e1a..ff90f86 100644 --- a/design/68723/ssh.html +++ b/design/68723/ssh.html @@ -573,10 +573,7 @@ so its API may be changed when pressing needs arise. <li><a href="#FingerprintSHA256">func FingerprintSHA256(pubKey PublicKey) string</a></li> <li><a href="#Marshal">func Marshal(msg interface{}) []byte</a></li> <li><a href="#MarshalAuthorizedKey">func MarshalAuthorizedKey(key PublicKey) []byte</a></li> - <li><a href="#MarshalPrivateKey">func MarshalPrivateKey(key crypto.PrivateKey, comment string) (*pem.Block, error)</a></li> - <li><a href="#MarshalPrivateKeyWithPassphrase">func MarshalPrivateKeyWithPassphrase(key crypto.PrivateKey, comment string, passphrase []byte) (*pem.Block, error)</a></li> - <li><a href="#ParseRawPrivateKey">func ParseRawPrivateKey(pemBytes []byte) (crypto.Signer, error)</a></li> - <li><a href="#ParseRawPrivateKeyWithPassphrase">func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (crypto.Signer, error)</a></li> + <li><a href="#MarshalPrivateKey">func MarshalPrivateKey(key crypto.PrivateKey, options MarshalPrivateKeyOptions) (*pem.Block, error)</a></li> <li><a href="#Unmarshal">func Unmarshal(data []byte, out interface{}) error</a></li> <li> <a href="#Algorithms">type Algorithms</a> @@ -737,6 +734,9 @@ so its API may be changed when pressing needs arise. <a href="#KeyboardInteractiveChallenge">type KeyboardInteractiveChallenge</a> </li> <li> + <a href="#MarshalPrivateKeyOptions">type MarshalPrivateKeyOptions</a> + </li> + <li> <a href="#NewChannel">type NewChannel</a> <ul> <li><a href="#NewChannel.Accept">func (c *NewChannel) Accept() (*Channel, error)</a></li> @@ -767,6 +767,14 @@ so its API may be changed when pressing needs arise. <a href="#Permissions">type Permissions</a> </li> <li> + <a href="#PrivateKeySigner">type PrivateKeySigner</a> + <ul> + <li><a href="#ParsePrivateKey">func ParsePrivateKey(pemBytes []byte) (*PrivateKeySigner, error)</a></li> + <li><a href="#ParsePrivateKeyWithPassphrase">func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (*PrivateKeySigner, error)</a></li> + <li><a href="#PrivateKeySigner.CryptoSigner">func (k *PrivateKeySigner) CryptoSigner() crypto.Signer</a></li> + </ul> + </li> + <li> <a href="#PublicKey">type PublicKey</a> <ul> <li><a href="#NewPublicKey">func NewPublicKey(key interface{}) (PublicKey, error)</a></li> @@ -855,8 +863,6 @@ so its API may be changed when pressing needs arise. <li><a href="#NewCertSigner">func NewCertSigner(cert *Certificate, signer Signer) (Signer, error)</a></li> <li><a href="#NewSigner">func NewSigner(signer crypto.Signer) (Signer, error)</a></li> <li><a href="#NewSignerWithAlgorithms">func NewSignerWithAlgorithms(signer Signer, algorithms []string) (Signer, error)</a></li> - <li><a href="#ParsePrivateKey">func ParsePrivateKey(pemBytes []byte) (Signer, error)</a></li> - <li><a href="#ParsePrivateKeyWithPassphrase">func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error)</a></li> </ul> </li> <li> @@ -1068,23 +1074,9 @@ number is prepended to the result. If the last of member has the <p>MarshalAuthorizedKey serializes key for inclusion in an OpenSSH authorized_keys file. The return value ends with newline. <h3 id="MarshalPrivateKey">func MarshalPrivateKey</h3> - <pre class="chroma"><span class="kd">func</span> <span class="nf">MarshalPrivateKey</span><span class="p">(</span><span class="nx">key</span> <a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#PrivateKey"><span class="nx">PrivateKey</span></a><span class="p">,</span> <span class="nx">comment</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="https://pkg.go.dev/encoding/pem"><span class="nx">pem</span></a><span class="p">.</span><a href="https://pkg.go.dev/encoding/pem#Block"><span class="nx">Block</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <pre class="chroma"><span class="kd">func</span> <span class="nf">MarshalPrivateKey</span><span class="p">(</span><span class="nx">key</span> <a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#PrivateKey"><span class="nx">PrivateKey</span></a><span class="p">,</span> <span class="nx">options</span> <a href="#MarshalPrivateKeyOptions"><span class="nx">MarshalPrivateKeyOptions</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="https://pkg.go.dev/encoding/pem"><span class="nx">pem</span></a><span class="p">.</span><a href="https://pkg.go.dev/encoding/pem#Block"><span class="nx">Block</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> <p>MarshalPrivateKey returns a PEM block with the private key serialized in the OpenSSH format. -<h3 id="MarshalPrivateKeyWithPassphrase">func MarshalPrivateKeyWithPassphrase</h3> - <pre class="chroma"><span class="kd">func</span> <span class="nf">MarshalPrivateKeyWithPassphrase</span><span class="p">(</span><span class="nx">key</span> <a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#PrivateKey"><span class="nx">PrivateKey</span></a><span class="p">,</span> <span class="nx">comment</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">passphrase</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="https://pkg.go.dev/encoding/pem"><span class="nx">pem</span></a><span class="p">.</span><a href="https://pkg.go.dev/encoding/pem#Block"><span class="nx">Block</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> - <p>MarshalPrivateKeyWithPassphrase returns a PEM block holding the encrypted -private key serialized in the OpenSSH format. -<h3 id="ParseRawPrivateKey">func ParseRawPrivateKey</h3> - <pre class="chroma"><span class="kd">func</span> <span class="nf">ParseRawPrivateKey</span><span class="p">(</span><span class="nx">pemBytes</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> - <p>ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports -RSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH -formats. If the private key is encrypted, it will return a PassphraseMissingError. -<h3 id="ParseRawPrivateKeyWithPassphrase">func ParseRawPrivateKeyWithPassphrase</h3> - <pre class="chroma"><span class="kd">func</span> <span class="nf">ParseRawPrivateKeyWithPassphrase</span><span class="p">(</span><span class="nx">pemBytes</span><span class="p">,</span> <span class="nx">passphrase</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> - <p>ParseRawPrivateKeyWithPassphrase returns a private key decrypted with -passphrase from a PEM encoded private key. If the passphrase is wrong, it -will return x509.IncorrectPasswordError. <h3 id="Unmarshal">func Unmarshal</h3> <pre class="chroma"><span class="kd">func</span> <span class="nf">Unmarshal</span><span class="p">(</span><span class="nx">data</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">out</span> <span class="kd">interface</span><span class="p">{})</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> <p>Unmarshal parses data in SSH wire format into a structure. The out @@ -1860,6 +1852,14 @@ successful authentication, the server may send a challenge with no questions, for which the name and instruction messages should be printed. RFC 4256 section 3.3 details how the UI should behave for both CLI and GUI environments. +<h3 id="MarshalPrivateKeyOptions">type MarshalPrivateKeyOptions</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">MarshalPrivateKeyOptions</span> <span class="kd">struct</span> <span class="p">{</span> + <span id="MarshalPrivateKeyOptions.Comment"><span class="nx">Comment</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="MarshalPrivateKeyOptions.Passphrase"><span class="nx">Passphrase</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="MarshalPrivateKeyOptions.SaltRounds"><span class="nx">SaltRounds</span></span> <a href="https://pkg.go.dev/builtin#int"><span class="kt">int</span></a> +<span class="p">}</span></pre> + <p>MarshalPrivateKeyOptions defines the available options to Marshal a private +key in OpenSSH format. <h3 id="NewChannel">type NewChannel</h3> <pre class="chroma"><span class="kd">type</span> <span class="nx">NewChannel</span> <span class="kd">struct</span> <span class="p">{</span> <span class="c1">// contains filtered or unexported fields @@ -1945,7 +1945,27 @@ specific to a user or a specific authentication method for a user. The Permissions value for a successful authentication attempt is available in ServerConn, so it can be used to pass information from the user-authentication phase to the application layer. -<h3 id="PublicKey">type PublicKey</h3> +<h3 id="PrivateKeySigner">type PrivateKeySigner</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">PrivateKeySigner</span> <span class="kd">struct</span> <span class="p">{</span> + <a href="#Signer"><span class="nx">Signer</span></a> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>PrivateKeySigner is a <a href="#Signer">ssh.Signer</a> that can also return the associated +<a href="https://pkg.go.dev/crypto#Signer">crypto.Signer</a>. +<h4 id="ParsePrivateKey">func ParsePrivateKey</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">ParsePrivateKey</span><span class="p">(</span><span class="nx">pemBytes</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#PrivateKeySigner"><span class="nx">PrivateKeySigner</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>ParsePrivateKey returns a <a href="#PrivateKeySigner">ssh.PrivateKeySigner</a> from a PEM encoded private +key. It supports RSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, +OpenSSL, and OpenSSH formats. If the private key is encrypted, it will return +a PassphraseMissingError. +<h4 id="ParsePrivateKeyWithPassphrase">func ParsePrivateKeyWithPassphrase</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">ParsePrivateKeyWithPassphrase</span><span class="p">(</span><span class="nx">pemBytes</span><span class="p">,</span> <span class="nx">passphrase</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#PrivateKeySigner"><span class="nx">PrivateKeySigner</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>ParsePrivateKeyWithPassphrase returns a <a href="#PrivateKeySigner">ssh.PrivateKeySigner</a> from a PEM +encoded private key and passphrase. It supports the same keys as +<a href="#ParsePrivateKey">ssh.ParsePrivateKey</a>. +<h4 id="PrivateKeySigner.CryptoSigner">func (*PrivateKeySigner) CryptoSigner</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">k</span> <span class="o">*</span><a href="#PrivateKeySigner"><span class="nx">PrivateKeySigner</span></a><span class="p">)</span> <span class="nf">CryptoSigner</span><span class="p">()</span> <a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#Signer"><span class="nx">Signer</span></a></pre> + <h3 id="PublicKey">type PublicKey</h3> <pre class="chroma"><span class="kd">type</span> <span class="nx">PublicKey</span> <span class="kd">interface</span> <span class="p">{</span> <span class="c1">// Type returns the key format name, e.g. "ssh-rsa". </span><span class="c1"></span> <span id="PublicKey.Type"><span class="nf">Type</span></span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> @@ -2713,16 +2733,6 @@ modules. algorithms. The algorithms must be set in preference order. The list must not be empty, and it must not include certificate types. An error is returned if the specified algorithms are incompatible with the public key type. -<h4 id="ParsePrivateKey">func ParsePrivateKey</h4> - <pre class="chroma"><span class="kd">func</span> <span class="nf">ParsePrivateKey</span><span class="p">(</span><span class="nx">pemBytes</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> - <p>ParsePrivateKey returns a Signer from a PEM encoded private key. It supports -the same keys as ParseRawPrivateKey. If the private key is encrypted, it -will return a PassphraseMissingError. -<h4 id="ParsePrivateKeyWithPassphrase">func ParsePrivateKeyWithPassphrase</h4> - <pre class="chroma"><span class="kd">func</span> <span class="nf">ParsePrivateKeyWithPassphrase</span><span class="p">(</span><span class="nx">pemBytes</span><span class="p">,</span> <span class="nx">passphrase</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> - <p>ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private -key and passphrase. It supports the same keys as -ParseRawPrivateKeyWithPassphrase. <h3 id="TerminalModes">type TerminalModes</h3> <pre class="chroma"><span class="kd">type</span> <span class="nx">TerminalModes</span> <span class="kd">map</span><span class="p">[</span><a href="https://pkg.go.dev/builtin#uint8"><span class="kt">uint8</span></a><span class="p">]</span><a href="https://pkg.go.dev/builtin#uint32"><span class="kt">uint32</span></a></pre> <h3 id="Waitmsg">type Waitmsg</h3> |
