mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-10 05:24:18 +09:00
feat(ssh): auto generate additional ssh keys (#33974)
adds capabilities for gitea to generate ecdsa and ed25519 keys by default adds cli for built-in ssh key generation helpers closes: https://github.com/go-gitea/gitea/issues/33783 --------- Co-authored-by: Nicolas <bircni@icloud.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
co-authored by
Nicolas
wxiaoguang
Giteabot
parent
ade76fe838
commit
d76a974b24
@@ -5,15 +5,23 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"gitea.dev/modules/consts"
|
||||
"gitea.dev/modules/util"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// NewInternalToken generate a new value intended to be used by INTERNAL_TOKEN.
|
||||
@@ -67,3 +75,75 @@ func NewJwtSecretWithBase64() ([]byte, string) {
|
||||
func NewSecretKey() (string, error) {
|
||||
return util.CryptoRandomString(64), nil
|
||||
}
|
||||
|
||||
type SSHKeyType string
|
||||
|
||||
const (
|
||||
SSHKeyRSA SSHKeyType = "rsa"
|
||||
SSHKeyECDSA SSHKeyType = "ecdsa"
|
||||
SSHKeyED25519 SSHKeyType = "ed25519"
|
||||
)
|
||||
|
||||
func NewSSHKey(keyType SSHKeyType, bits int) (ssh.PublicKey, *pem.Block, error) {
|
||||
pub, priv, err := commonKeyGen(keyType, bits)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pemPriv, err := ssh.MarshalPrivateKey(priv, "")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
sshPub, err := ssh.NewPublicKey(pub)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return sshPub, pemPriv, nil
|
||||
}
|
||||
|
||||
// commonKeyGen is an abstraction over rsa, ecdsa, and ed25519 generating functions
|
||||
func commonKeyGen(keyType SSHKeyType, bits int) (crypto.PublicKey, crypto.PrivateKey, error) {
|
||||
switch keyType {
|
||||
case SSHKeyRSA:
|
||||
bits = util.IfZero(bits, consts.AsymKeyDefaultBitsRsa)
|
||||
if bits < consts.AsymKeyMinBitsRsa {
|
||||
return nil, nil, util.NewInvalidArgumentErrorf("invalid rsa bits: %d", bits)
|
||||
}
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return &privateKey.PublicKey, privateKey, nil
|
||||
case SSHKeyED25519:
|
||||
return ed25519.GenerateKey(rand.Reader)
|
||||
case SSHKeyECDSA:
|
||||
bits = util.IfZero(bits, consts.AsymKeyDefaultBitsEcdsa)
|
||||
if bits < consts.AsymKeyMinBitsEC {
|
||||
return nil, nil, util.NewInvalidArgumentErrorf("invalid elliptic-curve bits: %d", bits)
|
||||
}
|
||||
curve, err := getEllipticCurve(bits)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return &privateKey.PublicKey, privateKey, nil
|
||||
default:
|
||||
return nil, nil, util.NewInvalidArgumentErrorf("unknown key type: %s", keyType)
|
||||
}
|
||||
}
|
||||
|
||||
func getEllipticCurve(bits int) (elliptic.Curve, error) {
|
||||
switch bits {
|
||||
case 256:
|
||||
return elliptic.P256(), nil
|
||||
case 384:
|
||||
return elliptic.P384(), nil
|
||||
case 521:
|
||||
return elliptic.P521(), nil
|
||||
default:
|
||||
return nil, util.NewInvalidArgumentErrorf("unsupported elliptic-curve bits: %d", bits)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user