From 2e8e3faff00cc4afec4d98520039e9dc6a9b9fdf Mon Sep 17 00:00:00 2001 From: LeonL <132875948+Lenrul@users.noreply.github.com> Date: Fri, 6 Nov 2026 10:18:02 -0800 Subject: [PATCH] updated ssh setup --- git-ssh-setup.cmd | 3 ++ git-ssh-setup.ps1 | 116 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 git-ssh-setup.cmd diff --git a/git-ssh-setup.cmd b/git-ssh-setup.cmd new file mode 100644 index 0000000..2ccbee5 --- /dev/null +++ b/git-ssh-setup.cmd @@ -0,0 +1,3 @@ +@echo off +powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0git-ssh-setup.ps1" %* +pause diff --git a/git-ssh-setup.ps1 b/git-ssh-setup.ps1 index 14fe684..bd511fd 100644 --- a/git-ssh-setup.ps1 +++ b/git-ssh-setup.ps1 @@ -1,9 +1,9 @@ <# .SYNOPSIS Sets up SSH for Git on Windows: creates a key in ~/.ssh, loads it into the - Windows ssh-agent, adds a host entry to ~/.ssh/config, and points Git at + Windows ssh-agent, adds a host entry to ~/.ssh/config, points Git at Windows' OpenSSH so pushes (and Git LFS) use the agent instead of asking - for the passphrase every time. + for the passphrase every time, and signs Gitea's key-verification token. .DESCRIPTION Safe to re-run: an existing key is reused (unless -Force), a key already in @@ -13,14 +13,22 @@ Run it as your normal user, NOT "Run as administrator". It asks for admin rights (UAC prompt) only if the ssh-agent service needs to be enabled. -.EXAMPLE - powershell -ExecutionPolicy Bypass -File .\setup-git-ssh.ps1 + Execution policy: start it through powershell.exe with -ExecutionPolicy + Bypass as in the examples, or double-click git-ssh-setup.cmd. Either way the + bypass applies to this one run only; the system setting is not changed. .EXAMPLE - powershell -ExecutionPolicy Bypass -File .\setup-git-ssh.ps1 -Comment "you@example.com" + powershell -NoProfile -ExecutionPolicy Bypass -File .\git-ssh-setup.ps1 .EXAMPLE - powershell -ExecutionPolicy Bypass -File .\setup-git-ssh.ps1 -HostName github.com -KeyName id_ed25519_github + powershell -NoProfile -ExecutionPolicy Bypass -File .\git-ssh-setup.ps1 -Comment "you@example.com" + +.EXAMPLE + # Verify the key later: click Verify next to it in Gitea and pass the token it shows. + powershell -NoProfile -ExecutionPolicy Bypass -File .\git-ssh-setup.ps1 -NoTest -Token d0d4b8e7... + +.EXAMPLE + powershell -NoProfile -ExecutionPolicy Bypass -File .\git-ssh-setup.ps1 -HostName github.com -KeyName id_ed25519_github -NoVerify #> [CmdletBinding()] param( @@ -41,9 +49,15 @@ param( [ValidateNotNullOrEmpty()] [string]$Comment = "$env:USERNAME@$env:COMPUTERNAME", + # Token from Gitea's Verify button. If omitted, the script asks for it. + [string]$Token, + # Replace an existing key with the same name instead of reusing it. [switch]$Force, + # Skip the Gitea key-verification step. + [switch]$NoVerify, + # Skip the connection test at the end. [switch]$NoTest ) @@ -56,6 +70,32 @@ function Stop-Setup([string]$Message) { exit 1 } +# Signs $Text exactly as given and returns the armored signature, or $null if +# ssh-keygen failed. The text is written to a file with no trailing newline and +# no BOM: piping it into ssh-keygen from PowerShell would add a newline and +# change what gets signed. +function Get-SshSignature([string]$Text, [string]$Keygen, [string]$KeyFile, [string]$Namespace = 'gitea') { + $file = Join-Path ([IO.Path]::GetTempPath()) ("gitea-verify-" + [guid]::NewGuid().ToString('N')) + $sigFile = "$file.sig" + try { + [IO.File]::WriteAllText($file, $Text, (New-Object Text.UTF8Encoding($false))) + # A .pub key file makes ssh-keygen sign through ssh-agent (no passphrase prompt). + & $Keygen -Y sign -n $Namespace -f $KeyFile $file | Out-Host + if ($LASTEXITCODE -eq 0 -and (Test-Path $sigFile)) { + return (Get-Content -Path $sigFile -Raw).Trim() + } + return $null + } finally { + Remove-Item -LiteralPath $file, $sigFile -Force -ErrorAction SilentlyContinue + } +} + +# Accept the token with stray spaces or quotes, but nothing that isn't hex. +$Token = "$Token" -replace '[\s''"]', '' +if ($Token -and $Token -notmatch '^[0-9a-fA-F]+$') { + Stop-Setup "-Token should be just the hex string from Gitea's Token box." +} + $openSshDir = Join-Path $env:WINDIR 'System32\OpenSSH' $sshExe = Join-Path $openSshDir 'ssh.exe' $keygenExe = Join-Path $openSshDir 'ssh-keygen.exe' @@ -210,10 +250,68 @@ try { } Write-Host " Add it in Gitea: your avatar > Settings > SSH / GPG Keys > Add Key" -# --- 7. Test ----------------------------------------------------------------- +# --- 7. Verify the key in Gitea (optional) ----------------------------------- +# Gitea's Verify button shows a token. Signing it with this key proves you own +# the key, and Gitea then marks the key as verified. +if (-not $NoVerify) { + Write-Step "Verifying the key in Gitea (optional)" + if (-not $Token) { + Write-Host " 1. Add the key in Gitea first (it's on your clipboard)." + Write-Host " 2. Click Verify next to the key and copy the token Gitea shows." + while ($true) { + $Token = "$(Read-Host ' Paste the token here, or press Enter to skip')" -replace '[\s''"]', '' + if (-not $Token -or $Token -match '^[0-9a-fA-F]+$') { break } + Write-Note "That doesn't look like a token. Paste only the hex string from the Token box." + } + } + + if (-not $Token) { + Write-Note "Skipped. To verify later, click Verify in Gitea and re-run with -NoTest -Token ." + } else { + $signature = Get-SshSignature -Text $Token -Keygen $keygenExe -KeyFile $pubPath + + if (-not $signature) { + # Windows OpenSSH older than 8.1 has no 'ssh-keygen -Y'; Git for Windows ships a newer one. + $gitKeygen = $null + $gitCmd = Get-Command git -ErrorAction SilentlyContinue + if ($gitCmd) { + $dir = Split-Path $gitCmd.Source + foreach ($i in 1..3) { + if (-not $dir) { break } + $candidate = Join-Path $dir 'usr\bin\ssh-keygen.exe' + if (Test-Path $candidate) { $gitKeygen = $candidate; break } + $dir = Split-Path $dir + } + } + if ($gitKeygen) { + Write-Note "Retrying with Git for Windows' ssh-keygen (it may ask for the key's passphrase)." + $signature = Get-SshSignature -Text $Token -Keygen $gitKeygen -KeyFile $keyPath + } + } + + if ($signature) { + Write-Host "`n$signature`n" + try { + Set-Clipboard -Value $signature + Write-Ok "Signature copied to the clipboard." + } catch { + Write-Note "Couldn't copy to the clipboard - copy the block above." + } + Write-Host " Paste it into Gitea's 'Armored SSH signature' box and click Verify." + Write-Note "The token only stays valid for a short time. If Gitea rejects the signature," + Write-Note "click Verify again for a new token and re-run with -NoTest -Token ." + } else { + Write-Note "Couldn't sign the token, so the key wasn't verified. Everything else is set up." + } + } +} + +# --- 8. Test ----------------------------------------------------------------- if ($HostName -and -not $NoTest) { - Write-Host "" - Read-Host "Press Enter once the key is added to test the connection (Ctrl+C to skip)" | Out-Null + Write-Step "Testing the connection to $HostName" + if ($NoVerify) { + Read-Host "Press Enter once the key is added in Gitea (Ctrl+C to skip)" | Out-Null + } & $sshExe -T -p $Port "$User@$HostName" Write-Host "" Write-Note "A 'Hi there, ! You've successfully authenticated' message means it worked."