mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Offer rsa-sha2-512 and rsa-sha2-256 algorithms in internal SSH (#17281)
* Offer rsa-sha2-512 and rsa-sha2-256 algorithms in internal SSH There is a subtle bug in the SSH library x/crypto/ssh which makes the incorrect assumption that the public key type is the same as the signature algorithm type. This means that only ssh-rsa signatures are offered by default. This PR adds a workaround around this problem. Fix #17175 Signed-off-by: Andrew Thornton <art27@cantab.net> * as per review Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
		@@ -316,10 +316,66 @@ func Listen(host string, port int, ciphers []string, keyExchanges []string, macs
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Workaround slightly broken behaviour in x/crypto/ssh/handshake.go:458-463
 | 
			
		||||
	//
 | 
			
		||||
	// Fundamentally the issue here is that HostKeyAlgos make the incorrect assumption
 | 
			
		||||
	// that the PublicKey().Type() matches the signature algorithm.
 | 
			
		||||
	//
 | 
			
		||||
	// Therefore we need to add duplicates for the RSA with different signing algorithms.
 | 
			
		||||
	signers := make([]ssh.Signer, 0, len(srv.HostSigners))
 | 
			
		||||
	for _, signer := range srv.HostSigners {
 | 
			
		||||
		if signer.PublicKey().Type() == "ssh-rsa" {
 | 
			
		||||
			signers = append(signers,
 | 
			
		||||
				&wrapSigner{
 | 
			
		||||
					Signer:    signer,
 | 
			
		||||
					algorithm: gossh.SigAlgoRSASHA2512,
 | 
			
		||||
				},
 | 
			
		||||
				&wrapSigner{
 | 
			
		||||
					Signer:    signer,
 | 
			
		||||
					algorithm: gossh.SigAlgoRSASHA2256,
 | 
			
		||||
				},
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
		signers = append(signers, signer)
 | 
			
		||||
	}
 | 
			
		||||
	srv.HostSigners = signers
 | 
			
		||||
 | 
			
		||||
	go listen(&srv)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// wrapSigner wraps a signer and overrides its public key type with the provided algorithm
 | 
			
		||||
type wrapSigner struct {
 | 
			
		||||
	ssh.Signer
 | 
			
		||||
	algorithm string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PublicKey returns an associated PublicKey instance.
 | 
			
		||||
func (s *wrapSigner) PublicKey() gossh.PublicKey {
 | 
			
		||||
	return &wrapPublicKey{
 | 
			
		||||
		PublicKey: s.Signer.PublicKey(),
 | 
			
		||||
		algorithm: s.algorithm,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sign returns raw signature for the given data. This method
 | 
			
		||||
// will apply the hash specified for the keytype to the data using
 | 
			
		||||
// the algorithm assigned for this key
 | 
			
		||||
func (s *wrapSigner) Sign(rand io.Reader, data []byte) (*gossh.Signature, error) {
 | 
			
		||||
	return s.Signer.(gossh.AlgorithmSigner).SignWithAlgorithm(rand, data, s.algorithm)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// wrapPublicKey wraps a PublicKey and overrides its type
 | 
			
		||||
type wrapPublicKey struct {
 | 
			
		||||
	gossh.PublicKey
 | 
			
		||||
	algorithm string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Type returns the algorithm
 | 
			
		||||
func (k *wrapPublicKey) Type() string {
 | 
			
		||||
	return k.algorithm
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenKeyPair make a pair of public and private keys for SSH access.
 | 
			
		||||
// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file.
 | 
			
		||||
// Private Key generated is PEM encoded
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user