From 2fc1127816961e26c06ea768f344b3ed7d9ffb57 Mon Sep 17 00:00:00 2001 From: Hans Nielsen Date: Tue, 18 Feb 2020 22:05:19 -0800 Subject: [PATCH] ssh: support RSA SHA-2 (RFC8332) signatures This change adds support for RSA SHA-2 based signatures for host keys and certificates. It also switches the default certificate signature algorithm for RSA to use SHA-512. This is implemented by treating ssh.Signer specially when the key type is `ssh-rsa` by also allowing SHA-256 and SHA-512 signatures. Fixes golang/go#37278 Change-Id: I2ee1ac4ae4c9c1de441a2d6cf1e806357ef18910 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/220037 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Jason A. Donenfeld Reviewed-by: Roland Shoemaker --- ssh/certs.go | 24 +++++++++++- ssh/certs_test.go | 78 +++++++++++++++----------------------- ssh/client.go | 15 +++++++- ssh/client_test.go | 41 ++++++++++++++++++++ ssh/common.go | 30 +++++++++------ ssh/handshake.go | 29 ++++++++++++-- ssh/keys.go | 9 +++++ ssh/server.go | 2 +- ssh/session_test.go | 8 +++- ssh/test/test_unix_test.go | 2 +- ssh/testdata/keys.go | 36 ++++++++++++++++++ ssh/testdata_test.go | 8 ++++ 12 files changed, 213 insertions(+), 69 deletions(-) diff --git a/ssh/certs.go b/ssh/certs.go index 916c840..6605bf6 100644 --- a/ssh/certs.go +++ b/ssh/certs.go @@ -14,7 +14,7 @@ import ( "time" ) -// These constants from [PROTOCOL.certkeys] represent the algorithm names +// These constants from [PROTOCOL.certkeys] represent the key algorithm names // for certificate types supported by this package. const ( CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" @@ -27,6 +27,14 @@ const ( CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com" ) +// These constants from [PROTOCOL.certkeys] represent additional signature +// algorithm names for certificate types supported by this package. +const ( + CertSigAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" + CertSigAlgoRSASHA2256v01 = "rsa-sha2-256-cert-v01@openssh.com" + CertSigAlgoRSASHA2512v01 = "rsa-sha2-512-cert-v01@openssh.com" +) + // Certificate types distinguish between host and user // certificates. The values can be set in the CertType field of // Certificate. @@ -423,6 +431,12 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { } c.SignatureKey = authority.PublicKey() + if v, ok := authority.(AlgorithmSigner); ok { + if v.PublicKey().Type() == KeyAlgoRSA { + authority = &rsaSigner{v, SigAlgoRSASHA2512} + } + } + sig, err := authority.Sign(rand, c.bytesForSigning()) if err != nil { return err @@ -431,8 +445,14 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { return nil } +// certAlgoNames includes a mapping from signature algorithms to the +// corresponding certificate signature algorithm. When a key type (such +// as ED25516) is associated with only one algorithm, the KeyAlgo +// constant is used instead of the SigAlgo. var certAlgoNames = map[string]string{ - KeyAlgoRSA: CertAlgoRSAv01, + SigAlgoRSA: CertSigAlgoRSAv01, + SigAlgoRSASHA2256: CertSigAlgoRSASHA2256v01, + SigAlgoRSASHA2512: CertSigAlgoRSASHA2512v01, KeyAlgoDSA: CertAlgoDSAv01, KeyAlgoECDSA256: CertAlgoECDSA256v01, KeyAlgoECDSA384: CertAlgoECDSA384v01, diff --git a/ssh/certs_test.go b/ssh/certs_test.go index c8e7cf5..bae7f7e 100644 --- a/ssh/certs_test.go +++ b/ssh/certs_test.go @@ -9,12 +9,12 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" + "fmt" + "io" "net" "reflect" "testing" "time" - - "golang.org/x/crypto/ssh/testdata" ) // Cert generated by ssh-keygen 6.0p1 Debian-4. @@ -226,53 +226,33 @@ func TestHostKeyCert(t *testing.T) { } } +type legacyRSASigner struct { + Signer +} + +func (s *legacyRSASigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + v, ok := s.Signer.(AlgorithmSigner) + if !ok { + return nil, fmt.Errorf("invalid signer") + } + return v.SignWithAlgorithm(rand, data, SigAlgoRSA) +} + func TestCertTypes(t *testing.T) { var testVars = []struct { - name string - keys func() Signer + name string + signer Signer + algo string }{ - { - name: CertAlgoECDSA256v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap256"]) - return s - }, - }, - { - name: CertAlgoECDSA384v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap384"]) - return s - }, - }, - { - name: CertAlgoECDSA521v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap521"]) - return s - }, - }, - { - name: CertAlgoED25519v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ed25519"]) - return s - }, - }, - { - name: CertAlgoRSAv01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["rsa"]) - return s - }, - }, - { - name: CertAlgoDSAv01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["dsa"]) - return s - }, - }, + {CertAlgoECDSA256v01, testSigners["ecdsap256"], ""}, + {CertAlgoECDSA384v01, testSigners["ecdsap384"], ""}, + {CertAlgoECDSA521v01, testSigners["ecdsap521"], ""}, + {CertAlgoED25519v01, testSigners["ed25519"], ""}, + {CertAlgoRSAv01, testSigners["rsa"], SigAlgoRSASHA2512}, + {CertAlgoRSAv01, &legacyRSASigner{testSigners["rsa"]}, SigAlgoRSA}, + {CertAlgoRSAv01, testSigners["rsa-sha2-256"], SigAlgoRSASHA2512}, + {CertAlgoRSAv01, testSigners["rsa-sha2-512"], SigAlgoRSASHA2512}, + {CertAlgoDSAv01, testSigners["dsa"], ""}, } k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -304,7 +284,7 @@ func TestCertTypes(t *testing.T) { go NewServerConn(c1, conf) - priv := m.keys() + priv := m.signer if err != nil { t.Fatalf("error generating ssh pubkey: %v", err) } @@ -320,6 +300,10 @@ func TestCertTypes(t *testing.T) { t.Fatalf("error generating cert signer: %v", err) } + if m.algo != "" && cert.Signature.Format != m.algo { + t.Errorf("expected %q signature format, got %q", m.algo, cert.Signature.Format) + } + config := &ClientConfig{ User: "user", HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil }, diff --git a/ssh/client.go b/ssh/client.go index 99f68bd..ba8621a 100644 --- a/ssh/client.go +++ b/ssh/client.go @@ -115,12 +115,25 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e // verifyHostKeySignature verifies the host key obtained in the key // exchange. -func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error { +func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexResult) error { sig, rest, ok := parseSignatureBody(result.Signature) if len(rest) > 0 || !ok { return errors.New("ssh: signature parse error") } + // For keys, underlyingAlgo is exactly algo. For certificates, + // we have to look up the underlying key algorithm that SSH + // uses to evaluate signatures. + underlyingAlgo := algo + for sigAlgo, certAlgo := range certAlgoNames { + if certAlgo == algo { + underlyingAlgo = sigAlgo + } + } + if sig.Format != underlyingAlgo { + return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, underlyingAlgo) + } + return hostKey.Verify(result.H, sig) } diff --git a/ssh/client_test.go b/ssh/client_test.go index 6aaa003..3063433 100644 --- a/ssh/client_test.go +++ b/ssh/client_test.go @@ -5,6 +5,8 @@ package ssh import ( + "bytes" + "crypto/rand" "strings" "testing" ) @@ -116,6 +118,45 @@ func TestHostKeyCheck(t *testing.T) { } } +func TestVerifyHostKeySignature(t *testing.T) { + for _, tt := range []struct { + key string + signAlgo string + verifyAlgo string + wantError string + }{ + {"rsa", SigAlgoRSA, SigAlgoRSA, ""}, + {"rsa", SigAlgoRSASHA2256, SigAlgoRSASHA2256, ""}, + {"rsa", SigAlgoRSA, SigAlgoRSASHA2512, `ssh: invalid signature algorithm "ssh-rsa", expected "rsa-sha2-512"`}, + {"ed25519", KeyAlgoED25519, KeyAlgoED25519, ""}, + } { + key := testSigners[tt.key].PublicKey() + s, ok := testSigners[tt.key].(AlgorithmSigner) + if !ok { + t.Fatalf("needed an AlgorithmSigner") + } + sig, err := s.SignWithAlgorithm(rand.Reader, []byte("test"), tt.signAlgo) + if err != nil { + t.Fatalf("couldn't sign: %q", err) + } + + b := bytes.Buffer{} + writeString(&b, []byte(sig.Format)) + writeString(&b, sig.Blob) + + result := kexResult{Signature: b.Bytes(), H: []byte("test")} + + err = verifyHostKeySignature(key, tt.verifyAlgo, &result) + if err != nil { + if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { + t.Errorf("got error %q, expecting %q", err.Error(), tt.wantError) + } + } else if tt.wantError != "" { + t.Errorf("succeeded, but want error string %q", tt.wantError) + } + } +} + func TestBannerCallback(t *testing.T) { c1, c2, err := netPipe() if err != nil { diff --git a/ssh/common.go b/ssh/common.go index 290382d..5ae2275 100644 --- a/ssh/common.go +++ b/ssh/common.go @@ -69,11 +69,13 @@ var preferredKexAlgos = []string{ // supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods // of authenticating servers) in preference order. var supportedHostKeyAlgos = []string{ - CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, + CertSigAlgoRSASHA2512v01, CertSigAlgoRSASHA2256v01, + CertSigAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, - KeyAlgoRSA, KeyAlgoDSA, + SigAlgoRSASHA2512, SigAlgoRSASHA2256, + SigAlgoRSA, KeyAlgoDSA, KeyAlgoED25519, } @@ -90,16 +92,20 @@ var supportedCompressions = []string{compressionNone} // hashFuncs keeps the mapping of supported algorithms to their respective // hashes needed for signature verification. var hashFuncs = map[string]crypto.Hash{ - KeyAlgoRSA: crypto.SHA1, - KeyAlgoDSA: crypto.SHA1, - KeyAlgoECDSA256: crypto.SHA256, - KeyAlgoECDSA384: crypto.SHA384, - KeyAlgoECDSA521: crypto.SHA512, - CertAlgoRSAv01: crypto.SHA1, - CertAlgoDSAv01: crypto.SHA1, - CertAlgoECDSA256v01: crypto.SHA256, - CertAlgoECDSA384v01: crypto.SHA384, - CertAlgoECDSA521v01: crypto.SHA512, + SigAlgoRSA: crypto.SHA1, + SigAlgoRSASHA2256: crypto.SHA256, + SigAlgoRSASHA2512: crypto.SHA512, + KeyAlgoDSA: crypto.SHA1, + KeyAlgoECDSA256: crypto.SHA256, + KeyAlgoECDSA384: crypto.SHA384, + KeyAlgoECDSA521: crypto.SHA512, + CertSigAlgoRSAv01: crypto.SHA1, + CertSigAlgoRSASHA2256v01: crypto.SHA256, + CertSigAlgoRSASHA2512v01: crypto.SHA512, + CertAlgoDSAv01: crypto.SHA1, + CertAlgoECDSA256v01: crypto.SHA256, + CertAlgoECDSA384v01: crypto.SHA384, + CertAlgoECDSA521v01: crypto.SHA512, } // unexpectedMessageError results when the SSH message that we received didn't diff --git a/ssh/handshake.go b/ssh/handshake.go index 2b10b05..05ad49c 100644 --- a/ssh/handshake.go +++ b/ssh/handshake.go @@ -457,8 +457,15 @@ func (t *handshakeTransport) sendKexInit() error { if len(t.hostKeys) > 0 { for _, k := range t.hostKeys { - msg.ServerHostKeyAlgos = append( - msg.ServerHostKeyAlgos, k.PublicKey().Type()) + algo := k.PublicKey().Type() + switch algo { + case KeyAlgoRSA: + msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, []string{SigAlgoRSASHA2512, SigAlgoRSASHA2256, SigAlgoRSA}...) + case CertAlgoRSAv01: + msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, []string{CertSigAlgoRSASHA2512v01, CertSigAlgoRSASHA2256v01, CertSigAlgoRSAv01}...) + default: + msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algo) + } } } else { msg.ServerHostKeyAlgos = t.hostKeyAlgorithms @@ -614,8 +621,22 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { var hostKey Signer for _, k := range t.hostKeys { - if algs.hostKey == k.PublicKey().Type() { + kt := k.PublicKey().Type() + if kt == algs.hostKey { hostKey = k + } else if signer, ok := k.(AlgorithmSigner); ok { + // Some signature algorithms don't show up as key types + // so we have to manually check for a compatible host key. + switch kt { + case KeyAlgoRSA: + if algs.hostKey == SigAlgoRSASHA2256 || algs.hostKey == SigAlgoRSASHA2512 { + hostKey = &rsaSigner{signer, algs.hostKey} + } + case CertAlgoRSAv01: + if algs.hostKey == CertSigAlgoRSASHA2256v01 || algs.hostKey == CertSigAlgoRSASHA2512v01 { + hostKey = &rsaSigner{signer, certToPrivAlgo(algs.hostKey)} + } + } } } @@ -634,7 +655,7 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics * return nil, err } - if err := verifyHostKeySignature(hostKey, result); err != nil { + if err := verifyHostKeySignature(hostKey, algs.hostKey, result); err != nil { return nil, err } diff --git a/ssh/keys.go b/ssh/keys.go index 31f2634..c67d3a3 100644 --- a/ssh/keys.go +++ b/ssh/keys.go @@ -939,6 +939,15 @@ func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) { return &dsaPrivateKey{key}, nil } +type rsaSigner struct { + AlgorithmSigner + defaultAlgorithm string +} + +func (s *rsaSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + return s.AlgorithmSigner.SignWithAlgorithm(rand, data, s.defaultAlgorithm) +} + type wrappedSigner struct { signer crypto.Signer pubKey PublicKey diff --git a/ssh/server.go b/ssh/server.go index b6911e8..6a58e12 100644 --- a/ssh/server.go +++ b/ssh/server.go @@ -284,7 +284,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) func isAcceptableAlgo(algo string) bool { switch algo { - case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519, + case SigAlgoRSA, SigAlgoRSASHA2256, SigAlgoRSASHA2512, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519, CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: return true } diff --git a/ssh/session_test.go b/ssh/session_test.go index 39853bf..fbec952 100644 --- a/ssh/session_test.go +++ b/ssh/session_test.go @@ -757,7 +757,13 @@ func TestHostKeyAlgorithms(t *testing.T) { connect(clientConf, KeyAlgoECDSA256) // Client asks for RSA explicitly. - clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA} + clientConf.HostKeyAlgorithms = []string{SigAlgoRSA} + connect(clientConf, KeyAlgoRSA) + + // Client asks for RSA-SHA2-512 explicitly. + clientConf.HostKeyAlgorithms = []string{SigAlgoRSASHA2512} + // We get back an "ssh-rsa" key but the verification happened + // with an RSA-SHA2-512 signature. connect(clientConf, KeyAlgoRSA) c1, c2, err := netPipe() diff --git a/ssh/test/test_unix_test.go b/ssh/test/test_unix_test.go index dbd02c7..804163c 100644 --- a/ssh/test/test_unix_test.go +++ b/ssh/test/test_unix_test.go @@ -35,7 +35,7 @@ Banner {{.Dir}}/banner HostKey {{.Dir}}/id_rsa HostKey {{.Dir}}/id_dsa HostKey {{.Dir}}/id_ecdsa -HostCertificate {{.Dir}}/id_rsa-cert.pub +HostCertificate {{.Dir}}/id_rsa-sha2-512-cert.pub Pidfile {{.Dir}}/sshd.pid #UsePrivilegeSeparation no KeyRegenerationInterval 3600 diff --git a/ssh/testdata/keys.go b/ssh/testdata/keys.go index f1e2fc5..4f2f3a4 100644 --- a/ssh/testdata/keys.go +++ b/ssh/testdata/keys.go @@ -60,6 +60,38 @@ NDvRS0rjwt6lJGv7zPZoqDc65VfrK2aNyHx2PgFyzwrEOtuF57bu7pnvEIxpLTeM z26i6XVMeYXAWZMTloMCQBbpGgEERQpeUknLBqUHhg/wXF6+lFA+vEGnkY+Dwab2 KCXFGd+SQ5GdUcEMe9isUH6DYj/6/yCDoFrXXmpQb+M= -----END RSA PRIVATE KEY----- +`), + "rsa-sha2-256": []byte(`-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2 +a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8 +Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQIDAQAB +AoGAJMCk5vqfSRzyXOTXLGIYCuR4Kj6pdsbNSeuuRGfYBeR1F2c/XdFAg7D/8s5R +38p/Ih52/Ty5S8BfJtwtvgVY9ecf/JlU/rl/QzhG8/8KC0NG7KsyXklbQ7gJT8UT +Ojmw5QpMk+rKv17ipDVkQQmPaj+gJXYNAHqImke5mm/K/h0CQQDciPmviQ+DOhOq +2ZBqUfH8oXHgFmp7/6pXw80DpMIxgV3CwkxxIVx6a8lVH9bT/AFySJ6vXq4zTuV9 +6QmZcZzDAkEA2j/UXJPIs1fQ8z/6sONOkU/BjtoePFIWJlRxdN35cZjXnBraX5UR +fFHkePv4YwqmXNqrBOvSu+w2WdSDci+IKwJAcsPRc/jWmsrJW1q3Ha0hSf/WG/Bu +X7MPuXaKpP/DkzGoUmb8ks7yqj6XWnYkPNLjCc8izU5vRwIiyWBRf4mxMwJBAILa +NDvRS0rjwt6lJGv7zPZoqDc65VfrK2aNyHx2PgFyzwrEOtuF57bu7pnvEIxpLTeM +z26i6XVMeYXAWZMTloMCQBbpGgEERQpeUknLBqUHhg/wXF6+lFA+vEGnkY+Dwab2 +KCXFGd+SQ5GdUcEMe9isUH6DYj/6/yCDoFrXXmpQb+M= +-----END RSA PRIVATE KEY----- +`), + "rsa-sha2-512": []byte(`-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2 +a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8 +Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQIDAQAB +AoGAJMCk5vqfSRzyXOTXLGIYCuR4Kj6pdsbNSeuuRGfYBeR1F2c/XdFAg7D/8s5R +38p/Ih52/Ty5S8BfJtwtvgVY9ecf/JlU/rl/QzhG8/8KC0NG7KsyXklbQ7gJT8UT +Ojmw5QpMk+rKv17ipDVkQQmPaj+gJXYNAHqImke5mm/K/h0CQQDciPmviQ+DOhOq +2ZBqUfH8oXHgFmp7/6pXw80DpMIxgV3CwkxxIVx6a8lVH9bT/AFySJ6vXq4zTuV9 +6QmZcZzDAkEA2j/UXJPIs1fQ8z/6sONOkU/BjtoePFIWJlRxdN35cZjXnBraX5UR +fFHkePv4YwqmXNqrBOvSu+w2WdSDci+IKwJAcsPRc/jWmsrJW1q3Ha0hSf/WG/Bu +X7MPuXaKpP/DkzGoUmb8ks7yqj6XWnYkPNLjCc8izU5vRwIiyWBRf4mxMwJBAILa +NDvRS0rjwt6lJGv7zPZoqDc65VfrK2aNyHx2PgFyzwrEOtuF57bu7pnvEIxpLTeM +z26i6XVMeYXAWZMTloMCQBbpGgEERQpeUknLBqUHhg/wXF6+lFA+vEGnkY+Dwab2 +KCXFGd+SQ5GdUcEMe9isUH6DYj/6/yCDoFrXXmpQb+M= +-----END RSA PRIVATE KEY----- `), "pkcs8": []byte(`-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCitzS2KiRQTccf @@ -191,6 +223,10 @@ var SSHCertificates = map[string][]byte{ // 2. Assumes "ca" key above in file named "ca", sign a cert for "rsa.pub": // ssh-keygen -s ca -h -n host.example.com -V +500w -I host.example.com-key rsa.pub "rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgLjYqmmuTSEmjVhSfLQphBSTJMLwIZhRgmpn8FHKLiEIAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABZHN8UAAAAAGsjIYUAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABDwAAAAdzc2gtcnNhAAABALeDea+60H6xJGhktAyosHaSY7AYzLocaqd8hJQjEIDifBwzoTlnBmcK9CxGhKuaoJFThdCLdaevCeOSuquh8HTkf+2ebZZc/G5T+2thPvPqmcuEcmMosWo+SIjYhbP3S6KD49aLC1X0kz8IBQeauFvURhkZ5ZjhA1L4aQYt9NjL73nqOl8PplRui+Ov5w8b4ldul4zOvYAFrzfcP6wnnXk3c1Zzwwf5wynD5jakO8GpYKBuhM7Z4crzkKSQjU3hla7xqgfomC5Gz4XbR2TNjcQiRrJQ0UlKtX3X3ObRCEhuvG0Kzjklhv+Ddw6txrhKjMjiSi/Yyius/AE8TmC1p4U= host.example.com +`), + "rsa-sha2-256": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgOyK28gunJkM60qp4EbsYAjgbUsyjS8u742OLjipIgc0AAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABeSMJ4AAAAAHBPBLwAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABFAAAAAxyc2Etc2hhMi0yNTYAAAEAbG4De/+QiqopPS3O1H7ySeEUCY56qmdgr02sFErnihdXPDaWXUXxacvJHaEtLrSTSaPL/3v3iKvjLWDOHaQ5c+cN9J7Tqzso7RQCXZD2nK9bwCUyBoiDyBCRe8w4DQEtfL5okpVzQsSAiojQ8hBohMOpy3gFfXrdm4PVC1ZKqlZh4fAc7ajieRq/Tpq2xOLdHwxkcgPNR83WVHva6K9/xjev/5n227/gkHo0qbGs8YYDOFXIEhENi+B23IzxdNVieWdyQpYpe0C2i95Jhyo0wJmaFY2ArruTS+D1jGQQpMPvAQRy26/A5hI83GLhpwyhrN/M8wCxzAhyPL6Ieuh5tQ== host.example.com +`), + "rsa-sha2-512": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgFGv4IpXfs4L/Y0b3rmUdPFhWoUrVnXuPxXr6aHGs7wgAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABeSMRYAAAAAHBPBp4AAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABFAAAAAxyc2Etc2hhMi01MTIAAAEAnF4fVj6mm+UFeNCIf9AKJCv9WzymjjPvzzmaMWWkPWqoV0P0m5SiYfvbY9SbA73Blpv8SOr0DmpublF183kodREia4KyVuC8hLhSCV2Y16hy9MBegOZMepn80w+apj7Rn9QCz5OfEakDdztp6OWTBtqxnZFcTQ4XrgFkNWeWRElGdEvAVNn2WHwHi4EIdz0mdv48Imv5SPlOuW862ZdFG4Do1dUfDIiGsBofLlgcyIYlf+eNHul6sBeUkuwFxisMpI5DQzNp8PX1g/QJA2wzwT674PTqDXNttKjyh50Fdr4sXxm9Gz1+jVLoESvFNa55ERdSyAqNu4wTy11MZsWwSA== host.example.com `), } diff --git a/ssh/testdata_test.go b/ssh/testdata_test.go index 2da8c79..83aa51b 100644 --- a/ssh/testdata_test.go +++ b/ssh/testdata_test.go @@ -34,6 +34,14 @@ func init() { panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) } testSigners[t], err = NewSignerFromKey(testPrivateKeys[t]) + if v, ok := testSigners[t].(*rsaSigner); ok { + switch t { + case "rsa-sha2-256": + testSigners[t] = &rsaSigner{v, SigAlgoRSASHA2256} + case "rsa-sha2-512": + testSigners[t] = &rsaSigner{v, SigAlgoRSASHA2512} + } + } if err != nil { panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) }