From c533991519816313dfaa0ddcec183756a97b9348 Mon Sep 17 00:00:00 2001
From: mainboarder <git@mainboarder.de>
Date: Mon, 28 Aug 2023 02:53:16 +0200
Subject: [PATCH] Expanded minimum RSA Keylength to 3072 (#26604)

German Federal Office for Information Security requests in its technical
guideline BSI TR-02102-1 RSA Keylength not shorter than 3000bits
starting 2024, in the year 2023 3000bits as a recommendation. Gitea
should request longer RSA Keys by default in favor of security and drop
old clients which do not support longer keys.


https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR02102/BSI-TR-02102.pdf?__blob=publicationFile&v=9
- Page 19, Table 1.2

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
---
 cmd/cert.go                                             | 2 +-
 custom/conf/app.example.ini                             | 2 +-
 docker/root/etc/s6/openssh/setup                        | 2 +-
 docs/content/administration/command-line.en-us.md       | 2 +-
 docs/content/administration/command-line.zh-cn.md       | 2 +-
 docs/content/administration/config-cheat-sheet.en-us.md | 2 +-
 docs/content/administration/config-cheat-sheet.zh-cn.md | 2 +-
 modules/activitypub/user_settings.go                    | 2 +-
 modules/setting/ssh.go                                  | 2 +-
 tests/integration/api_httpsig_test.go                   | 3 +++
 10 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/cmd/cert.go b/cmd/cert.go
index 9ae5ed06ce8a..38241d71a337 100644
--- a/cmd/cert.go
+++ b/cmd/cert.go
@@ -43,7 +43,7 @@ Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
 		},
 		&cli.IntFlag{
 			Name:  "rsa-bits",
-			Value: 2048,
+			Value: 3072,
 			Usage: "Size of RSA key to generate. Ignored if --ecdsa-curve is set",
 		},
 		&cli.StringFlag{
diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index a3d24b1961fa..96a0a3ede93d 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -1339,7 +1339,7 @@ LEVEL = Info
 ;; Define allowed algorithms and their minimum key length (use -1 to disable a type)
 ;ED25519 = 256
 ;ECDSA = 256
-;RSA = 2047 ; we allow 2047 here because an otherwise valid 2048 bit RSA key can be reported as having 2047 bit length
+;RSA = 3071 ; we allow 3071 here because an otherwise valid 3072 bit RSA key can be reported as having 3071 bit length
 ;DSA = -1 ; set to 1024 to switch on
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/docker/root/etc/s6/openssh/setup b/docker/root/etc/s6/openssh/setup
index f43544d65527..dbb3bafd3524 100755
--- a/docker/root/etc/s6/openssh/setup
+++ b/docker/root/etc/s6/openssh/setup
@@ -11,7 +11,7 @@ fi
 
 if [ ! -f /data/ssh/ssh_host_rsa_key ]; then
     echo "Generating /data/ssh/ssh_host_rsa_key..."
-    ssh-keygen -t rsa -b 2048 -f /data/ssh/ssh_host_rsa_key -N "" > /dev/null
+    ssh-keygen -t rsa -b 3072 -f /data/ssh/ssh_host_rsa_key -N "" > /dev/null
 fi
 
 if [ ! -f /data/ssh/ssh_host_ecdsa_key ]; then
diff --git a/docs/content/administration/command-line.en-us.md b/docs/content/administration/command-line.en-us.md
index 91c6c1e62627..05caff90e433 100644
--- a/docs/content/administration/command-line.en-us.md
+++ b/docs/content/administration/command-line.en-us.md
@@ -313,7 +313,7 @@ directory and will overwrite any existing files.
   - `--ecdsa-curve value`: ECDSA curve to use to generate a key. Optional. Valid options
     are P224, P256, P384, P521.
   - `--rsa-bits value`: Size of RSA key to generate. Optional. Ignored if --ecdsa-curve is
-    set. (default: 2048).
+    set. (default: 3072).
   - `--start-date value`: Creation date. Optional. (format: `Jan 1 15:04:05 2011`).
   - `--duration value`: Duration which the certificate is valid for. Optional. (default: 8760h0m0s)
   - `--ca`: If provided, this cert generates it's own certificate authority. Optional.
diff --git a/docs/content/administration/command-line.zh-cn.md b/docs/content/administration/command-line.zh-cn.md
index bd3d0c72bcf8..6e6bcb6082d4 100644
--- a/docs/content/administration/command-line.zh-cn.md
+++ b/docs/content/administration/command-line.zh-cn.md
@@ -295,7 +295,7 @@ menu:
 - 选项:
   - `--host value`:逗号分隔的主机名和IP地址列表,此证书适用于这些主机。支持使用通配符。必填。
   - `--ecdsa-curve value`:用于生成密钥的ECDSA曲线。可选。有效选项为P224、P256、P384、P521。
-  - `--rsa-bits value`:要生成的RSA密钥的大小。可选。如果设置了--ecdsa-curve,则忽略此选项。(默认值:2048)。
+  - `--rsa-bits value`:要生成的RSA密钥的大小。可选。如果设置了--ecdsa-curve,则忽略此选项。(默认值:3072)。
   - `--start-date value`:证书的创建日期。可选。(格式:`Jan 1 15:04:05 2011`)。
   - `--duration value`:证书有效期。可选。(默认值:8760h0m0s)
   - `--ca`:如果提供此选项,则证书将生成自己的证书颁发机构。可选。
diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md
index 968b47c2302e..311a2b2b7588 100644
--- a/docs/content/administration/config-cheat-sheet.en-us.md
+++ b/docs/content/administration/config-cheat-sheet.en-us.md
@@ -681,7 +681,7 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
 
 - `ED25519`: **256**
 - `ECDSA`: **256**
-- `RSA`: **2047**: We set 2047 here because an otherwise valid 2048 RSA key can be reported as 2047 length.
+- `RSA`: **3071**: We set 3071 here because an otherwise valid 3072 RSA key can be reported as 3071 length.
 - `DSA`: **-1**: DSA is now disabled by default. Set to **1024** to re-enable but ensure you may need to reconfigure your SSHD provider
 
 ## Webhook (`webhook`)
diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md
index 87e45aa6934d..39121908c21a 100644
--- a/docs/content/administration/config-cheat-sheet.zh-cn.md
+++ b/docs/content/administration/config-cheat-sheet.zh-cn.md
@@ -648,7 +648,7 @@ Gitea 创建以下非唯一队列:
 
 - `ED25519`:**256**
 - `ECDSA`:**256**
-- `RSA`:**2047**:我们在这里设置为2047,因为一个其他方面有效的2048 RSA密钥可能被报告为2047长度。
+- `RSA`:**3071**:我们在这里设置为2047,因为一个其他方面有效的3072 RSA密钥可能被报告为3071长度。
 - `DSA`:**-1**:默认情况下禁用DSA。设置为**1024**以重新启用,但请注意可能需要重新配置您的SSHD提供者
 
 ## Webhook (`webhook`)
diff --git a/modules/activitypub/user_settings.go b/modules/activitypub/user_settings.go
index 20b3d759c2f9..ef9bc0a864b6 100644
--- a/modules/activitypub/user_settings.go
+++ b/modules/activitypub/user_settings.go
@@ -8,7 +8,7 @@ import (
 	"code.gitea.io/gitea/modules/util"
 )
 
-const rsaBits = 2048
+const rsaBits = 3072
 
 // GetKeyPair function returns a user's private and public keys
 func GetKeyPair(user *user_model.User) (pub, priv string, err error) {
diff --git a/modules/setting/ssh.go b/modules/setting/ssh.go
index bbb7f5ab6cda..ea387e521fad 100644
--- a/modules/setting/ssh.go
+++ b/modules/setting/ssh.go
@@ -60,7 +60,7 @@ var SSH = struct {
 	ServerMACs:                    []string{"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1"},
 	KeygenPath:                    "",
 	MinimumKeySizeCheck:           true,
-	MinimumKeySizes:               map[string]int{"ed25519": 256, "ed25519-sk": 256, "ecdsa": 256, "ecdsa-sk": 256, "rsa": 2047},
+	MinimumKeySizes:               map[string]int{"ed25519": 256, "ed25519-sk": 256, "ecdsa": 256, "ecdsa-sk": 256, "rsa": 3071},
 	ServerHostKeys:                []string{"ssh/gitea.rsa", "ssh/gogs.rsa"},
 	AuthorizedKeysCommandTemplate: "{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}",
 	PerWriteTimeout:               PerWriteTimeout,
diff --git a/tests/integration/api_httpsig_test.go b/tests/integration/api_httpsig_test.go
index 4520364527f1..675ec54ff58f 100644
--- a/tests/integration/api_httpsig_test.go
+++ b/tests/integration/api_httpsig_test.go
@@ -11,7 +11,9 @@ import (
 	"testing"
 
 	auth_model "code.gitea.io/gitea/models/auth"
+	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/modules/test"
 	"code.gitea.io/gitea/tests"
 
 	"github.com/go-fed/httpsig"
@@ -52,6 +54,7 @@ fhTNAzWwZoQ91aHdAAAAFHUwMDIyMTQ2QGljdHMtcC1ueC03AQIDBAUG
 func TestHTTPSigPubKey(t *testing.T) {
 	// Add our public key to user1
 	defer tests.PrepareTestEnv(t)()
+	defer test.MockVariableValue(&setting.SSH.MinimumKeySizeCheck, false)()
 	session := loginUser(t, "user1")
 	token := url.QueryEscape(getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser))
 	keysURL := fmt.Sprintf("/api/v1/user/keys?token=%s", token)