forked from kevadesu/forgejo
Add support for ssh commit signing (#17743)
* Add support for ssh commit signing * Split out ssh verification to separate file * Show ssh key fingerprint on commit page * Update sshsig lib * Make sure we verify against correct namespace * Add ssh public key verification via ssh signatures When adding a public ssh key also validate that this user actually owns the key by signing a token with the private key. * Remove some gpg references and make verify key optional * Fix spaces indentation * Update options/locale/locale_en-US.ini Co-authored-by: Gusted <williamzijl7@hotmail.com> * Update templates/user/settings/keys_ssh.tmpl Co-authored-by: Gusted <williamzijl7@hotmail.com> * Update options/locale/locale_en-US.ini Co-authored-by: Gusted <williamzijl7@hotmail.com> * Update options/locale/locale_en-US.ini Co-authored-by: Gusted <williamzijl7@hotmail.com> * Update models/ssh_key_commit_verification.go Co-authored-by: Gusted <williamzijl7@hotmail.com> * Reword ssh/gpg_key_success message * Change Badsignature to NoKeyFound * Add sign/verify tests * Fix upstream api changes to user_model User * Match exact on SSH signature * Fix code review remarks Co-authored-by: Gusted <williamzijl7@hotmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
f1e85622da
commit
6fe756dc93
182 changed files with 17554 additions and 15288 deletions
24
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
24
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
|
@ -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,
|
||||
|
|
2
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
|
@ -18,7 +18,7 @@ import (
|
|||
"io/ioutil"
|
||||
|
||||
"golang.org/x/crypto/chacha20"
|
||||
"golang.org/x/crypto/poly1305"
|
||||
"golang.org/x/crypto/internal/poly1305"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
15
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
15
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
30
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
30
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
|
@ -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
|
||||
|
|
29
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
29
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
|
@ -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
|
||||
}
|
||||
|
||||
|
|
9
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
9
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
|
@ -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
|
||||
|
|
2
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue