mirror of
https://github.com/openp2p-cn/openp2p.git
synced 2026-06-15 14:37:48 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9e4cd6b3c |
252
.github/scripts/configure-simplysign-registry.ps1
vendored
Normal file
252
.github/scripts/configure-simplysign-registry.ps1
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
param(
|
||||
[switch]$DebugMode = $false,
|
||||
[switch]$VerifyOnly = $false
|
||||
)
|
||||
|
||||
# SimplySign Desktop Registry Configuration Script
|
||||
# Pre-configures optimal registry settings for automated login dialog display
|
||||
|
||||
Write-Host "=== SimplySign Desktop Registry Configuration ==="
|
||||
|
||||
if ($DebugMode) {
|
||||
Write-Host "Debug mode enabled - verbose logging active"
|
||||
}
|
||||
|
||||
# Registry path for SimplySign Desktop settings
|
||||
$RegistryPath = "HKCU:\Software\Certum\SimplySign"
|
||||
|
||||
# Optimal configuration values for automation
|
||||
$OptimalSettings = @{
|
||||
"ShowLoginDialogOnStart" = 1
|
||||
"ShowLoginDialogOnAppRequest" = 1
|
||||
"RememberLastUserName" = 1
|
||||
"Autostart" = 0
|
||||
"UnregisterCertificatesOnDisconnect" = 0
|
||||
"RememberPINinCSP" = 1
|
||||
"ForgetPINinCSPonDisconnect" = 1
|
||||
"LangID" = 9
|
||||
}
|
||||
|
||||
# Function to check if registry path exists
|
||||
function Test-RegistryPath {
|
||||
param([string]$Path)
|
||||
|
||||
try {
|
||||
$null = Get-Item -Path $Path -ErrorAction Stop
|
||||
return $true
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
# Function to get current registry value
|
||||
function Get-RegistryValue {
|
||||
param(
|
||||
[string]$Path,
|
||||
[string]$Name
|
||||
)
|
||||
|
||||
try {
|
||||
$value = Get-ItemProperty -Path $Path -Name $Name -ErrorAction Stop
|
||||
return $value.$Name
|
||||
} catch {
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
# Function to set registry value safely
|
||||
function Set-RegistryValue {
|
||||
param(
|
||||
[string]$Path,
|
||||
[string]$Name,
|
||||
[int]$Value
|
||||
)
|
||||
|
||||
try {
|
||||
Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type DWord -ErrorAction Stop
|
||||
if ($DebugMode) {
|
||||
Write-Host " Set $Name = $Value"
|
||||
}
|
||||
return $true
|
||||
} catch {
|
||||
Write-Host " ERROR: Failed to set $Name = $Value - $($_.Exception.Message)"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
# Function to display current settings
|
||||
function Show-CurrentSettings {
|
||||
Write-Host "Current SimplySign Desktop registry settings:"
|
||||
Write-Host "============================================="
|
||||
|
||||
if (-not (Test-RegistryPath $RegistryPath)) {
|
||||
Write-Host "Registry path does not exist: $RegistryPath"
|
||||
return
|
||||
}
|
||||
|
||||
foreach ($setting in $OptimalSettings.Keys) {
|
||||
$currentValue = Get-RegistryValue -Path $RegistryPath -Name $setting
|
||||
if ($null -eq $currentValue) {
|
||||
Write-Host " $setting : NOT SET"
|
||||
} else {
|
||||
Write-Host " $setting : $currentValue"
|
||||
}
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Function to create registry structure
|
||||
function Initialize-RegistryStructure {
|
||||
Write-Host "Initializing registry structure..."
|
||||
|
||||
# Create parent keys if they don't exist
|
||||
$ParentPaths = @(
|
||||
"HKCU:\Software\Certum",
|
||||
$RegistryPath
|
||||
)
|
||||
|
||||
$allCreated = $true
|
||||
foreach ($path in $ParentPaths) {
|
||||
if (-not (Test-RegistryPath $path)) {
|
||||
try {
|
||||
New-Item -Path $path -Force -ErrorAction Stop | Out-Null
|
||||
if ($DebugMode) {
|
||||
Write-Host " Created registry path: $path"
|
||||
}
|
||||
} catch {
|
||||
Write-Host " ERROR: Failed to create registry path: $path - $($_.Exception.Message)"
|
||||
$allCreated = $false
|
||||
}
|
||||
} else {
|
||||
if ($DebugMode) {
|
||||
Write-Host " Registry path exists: $path"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $allCreated
|
||||
}
|
||||
|
||||
# Function to apply optimal configuration
|
||||
function Set-OptimalConfiguration {
|
||||
Write-Host "Applying optimal configuration for automation..."
|
||||
|
||||
$successCount = 0
|
||||
$totalSettings = $OptimalSettings.Count
|
||||
|
||||
foreach ($setting in $OptimalSettings.Keys) {
|
||||
$value = $OptimalSettings[$setting]
|
||||
if (Set-RegistryValue -Path $RegistryPath -Name $setting -Value $value) {
|
||||
$successCount++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Applied $successCount of $totalSettings settings successfully"
|
||||
return ($successCount -eq $totalSettings)
|
||||
}
|
||||
|
||||
# Function to verify configuration
|
||||
function Test-Configuration {
|
||||
Write-Host "Verifying configuration..."
|
||||
|
||||
$verificationResults = @{}
|
||||
$allCorrect = $true
|
||||
|
||||
foreach ($setting in $OptimalSettings.Keys) {
|
||||
$expectedValue = $OptimalSettings[$setting]
|
||||
$actualValue = Get-RegistryValue -Path $RegistryPath -Name $setting
|
||||
|
||||
$isCorrect = ($actualValue -eq $expectedValue)
|
||||
$verificationResults[$setting] = @{
|
||||
Expected = $expectedValue
|
||||
Actual = $actualValue
|
||||
Correct = $isCorrect
|
||||
}
|
||||
|
||||
if (-not $isCorrect) {
|
||||
$allCorrect = $false
|
||||
}
|
||||
|
||||
if ($DebugMode -or -not $isCorrect) {
|
||||
$status = if ($isCorrect) { "OK" } else { "MISMATCH" }
|
||||
Write-Host " $setting : Expected=$expectedValue, Actual=$actualValue [$status]"
|
||||
}
|
||||
}
|
||||
|
||||
return $verificationResults, $allCorrect
|
||||
}
|
||||
|
||||
# Main execution
|
||||
try {
|
||||
Write-Host "Starting registry configuration process..."
|
||||
Write-Host ""
|
||||
|
||||
# Show current state
|
||||
Write-Host "BEFORE CONFIGURATION:"
|
||||
Show-CurrentSettings
|
||||
|
||||
if ($VerifyOnly) {
|
||||
Write-Host "Verification-only mode - no changes will be made"
|
||||
$verificationResults, $allCorrect = Test-Configuration
|
||||
|
||||
if ($allCorrect) {
|
||||
Write-Host "SUCCESS: All settings are correctly configured"
|
||||
exit 0
|
||||
} else {
|
||||
Write-Host "CONFIGURATION NEEDED: Some settings require adjustment"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Initialize registry structure
|
||||
if (-not (Initialize-RegistryStructure)) {
|
||||
Write-Host "FATAL ERROR: Failed to initialize registry structure"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Apply optimal configuration
|
||||
if (-not (Set-OptimalConfiguration)) {
|
||||
Write-Host "ERROR: Failed to apply complete configuration"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "AFTER CONFIGURATION:"
|
||||
Show-CurrentSettings
|
||||
|
||||
# Verify the configuration was applied correctly
|
||||
$verificationResults, $allCorrect = Test-Configuration
|
||||
|
||||
if ($allCorrect) {
|
||||
Write-Host "SUCCESS: Registry configuration completed successfully"
|
||||
Write-Host ""
|
||||
Write-Host "Key automation settings enabled:"
|
||||
Write-Host " ShowLoginDialogOnStart = 1 (Login dialog will appear automatically)"
|
||||
Write-Host " ShowLoginDialogOnAppRequest = 1 (Dialog appears when apps request access)"
|
||||
Write-Host " RememberLastUserName = 1 (Username persistence for efficiency)"
|
||||
Write-Host ""
|
||||
Write-Host "Next steps:"
|
||||
Write-Host "1. Launch SimplySign Desktop"
|
||||
Write-Host "2. Login dialog should appear automatically"
|
||||
Write-Host "3. Complete authentication process"
|
||||
|
||||
# Create a status file for the workflow to check
|
||||
"REGISTRY_CONFIGURATION_SUCCESS" | Out-File -FilePath "registry_config_status.log" -Encoding UTF8
|
||||
|
||||
exit 0
|
||||
} else {
|
||||
Write-Host "ERROR: Configuration verification failed"
|
||||
Write-Host "Some settings were not applied correctly"
|
||||
|
||||
"REGISTRY_CONFIGURATION_PARTIAL" | Out-File -FilePath "registry_config_status.log" -Encoding UTF8
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Host "FATAL ERROR: Registry configuration failed - $($_.Exception.Message)"
|
||||
|
||||
"REGISTRY_CONFIGURATION_FAILED" | Out-File -FilePath "registry_config_status.log" -Encoding UTF8
|
||||
|
||||
exit 1
|
||||
}
|
||||
390
.github/scripts/connect-simplySign-enhanced.ps1
vendored
Normal file
390
.github/scripts/connect-simplySign-enhanced.ps1
vendored
Normal file
@@ -0,0 +1,390 @@
|
||||
# Connect-SimplySign-Enhanced.ps1
|
||||
# Registry-Enhanced TOTP Authentication for SimplySign Desktop
|
||||
# Uses registry pre-configuration + TOTP credential injection approach
|
||||
|
||||
param(
|
||||
[string]$OtpUri = $env:CERTUM_OTP_URI,
|
||||
[string]$UserId = $env:CERTUM_USERNAME,
|
||||
[string]$ExePath = $env:CERTUM_EXE_PATH,
|
||||
[string]$ExpectedCertificateSHA1 = $env:CERTUM_CERTIFICATE_SHA1
|
||||
)
|
||||
|
||||
function Normalize-Sha1 {
|
||||
param([string]$InputSha1)
|
||||
if (-not $InputSha1) {
|
||||
return $null
|
||||
}
|
||||
return ($InputSha1 -replace "[^a-fA-F0-9]", "").ToUpperInvariant()
|
||||
}
|
||||
|
||||
function Find-CertificateByThumbprint {
|
||||
param([string]$Thumbprint)
|
||||
|
||||
if (-not $Thumbprint) {
|
||||
return @()
|
||||
}
|
||||
|
||||
$all = Get-ChildItem -Path "Cert:\CurrentUser\My", "Cert:\LocalMachine\My" -ErrorAction SilentlyContinue
|
||||
# 对证书库中的 Thumbprint 同样做规范化(去除不可见字符、统一大写),避免 BOM 或格式差异导致匹配失败
|
||||
return @($all | Where-Object {
|
||||
$normalizedStoreThumbprint = ($_.Thumbprint -replace "[^a-fA-F0-9]", "").ToUpperInvariant()
|
||||
$normalizedStoreThumbprint -eq $Thumbprint
|
||||
})
|
||||
}
|
||||
|
||||
# Validate required parameters
|
||||
if (-not $OtpUri) {
|
||||
Write-Host "ERROR: CERTUM_OTP_URI environment variable not provided"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not $UserId) {
|
||||
Write-Host "ERROR: CERTUM_USERNAME environment variable not provided"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not $ExePath) {
|
||||
$ExePath = "C:\Program Files\Certum\SimplySign Desktop\SimplySignDesktop.exe"
|
||||
}
|
||||
|
||||
Write-Host "=== REGISTRY-ENHANCED TOTP AUTHENTICATION ==="
|
||||
Write-Host "Using registry pre-configuration + credential injection"
|
||||
Write-Host "OTP URI provided (length: $($OtpUri.Length))"
|
||||
Write-Host "User ID: $UserId"
|
||||
Write-Host "Executable: $ExePath"
|
||||
Write-Host ""
|
||||
|
||||
# Verify SimplySign Desktop exists
|
||||
if (-not (Test-Path $ExePath)) {
|
||||
Write-Host "ERROR: SimplySign Desktop not found at: $ExePath"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Parse the otpauth:// URI
|
||||
$uri = [Uri]$OtpUri
|
||||
|
||||
# Parse query parameters (compatible with both PowerShell 5.1 and 7+)
|
||||
try {
|
||||
$q = [System.Web.HttpUtility]::ParseQueryString($uri.Query)
|
||||
} catch {
|
||||
$q = @{}
|
||||
foreach ($part in $uri.Query.TrimStart('?') -split '&') {
|
||||
$kv = $part -split '=', 2
|
||||
if ($kv.Count -eq 2) {
|
||||
$q[$kv[0]] = [Uri]::UnescapeDataString($kv[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$Base32 = $q['secret']
|
||||
$Digits = if ($q['digits']) { [int]$q['digits'] } else { 6 }
|
||||
$Period = if ($q['period']) { [int]$q['period'] } else { 30 }
|
||||
$Algorithm = if ($q['algorithm']) { $q['algorithm'].ToUpper() } else { 'SHA256' }
|
||||
|
||||
# Validate supported algorithms
|
||||
$SupportedAlgorithms = @('SHA1', 'SHA256', 'SHA512')
|
||||
if ($Algorithm -notin $SupportedAlgorithms) {
|
||||
Write-Host "ERROR: Unsupported algorithm: $Algorithm. Supported: $($SupportedAlgorithms -join ', ')"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# TOTP Generator (inline C# implementation)
|
||||
Add-Type -Language CSharp @"
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
public static class Totp
|
||||
{
|
||||
private const string B32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
private static byte[] Base32Decode(string s)
|
||||
{
|
||||
s = s.TrimEnd('=').ToUpperInvariant();
|
||||
int byteCount = s.Length * 5 / 8;
|
||||
byte[] bytes = new byte[byteCount];
|
||||
|
||||
int bitBuffer = 0, bitsLeft = 0, idx = 0;
|
||||
foreach (char c in s)
|
||||
{
|
||||
int val = B32.IndexOf(c);
|
||||
if (val < 0) throw new ArgumentException("Invalid Base32 char: " + c);
|
||||
|
||||
bitBuffer = (bitBuffer << 5) | val;
|
||||
bitsLeft += 5;
|
||||
|
||||
if (bitsLeft >= 8)
|
||||
{
|
||||
bytes[idx++] = (byte)(bitBuffer >> (bitsLeft - 8));
|
||||
bitsLeft -= 8;
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static HMAC GetHmacAlgorithm(string algorithm, byte[] key)
|
||||
{
|
||||
switch (algorithm.ToUpper())
|
||||
{
|
||||
case "SHA1":
|
||||
return new HMACSHA1(key);
|
||||
case "SHA256":
|
||||
return new HMACSHA256(key);
|
||||
case "SHA512":
|
||||
return new HMACSHA512(key);
|
||||
default:
|
||||
throw new ArgumentException("Unsupported algorithm: " + algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
public static string Now(string secret, int digits, int period, string algorithm = "SHA256")
|
||||
{
|
||||
byte[] key = Base32Decode(secret);
|
||||
long counter = DateTimeOffset.UtcNow.ToUnixTimeSeconds() / period;
|
||||
|
||||
byte[] cnt = BitConverter.GetBytes(counter);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(cnt);
|
||||
|
||||
byte[] hash;
|
||||
using (var hmac = GetHmacAlgorithm(algorithm, key))
|
||||
{
|
||||
hash = hmac.ComputeHash(cnt);
|
||||
}
|
||||
|
||||
int offset = hash[hash.Length - 1] & 0x0F;
|
||||
int binary =
|
||||
((hash[offset] & 0x7F) << 24) |
|
||||
((hash[offset + 1] & 0xFF) << 16) |
|
||||
((hash[offset + 2] & 0xFF) << 8) |
|
||||
(hash[offset + 3] & 0xFF);
|
||||
|
||||
int otp = binary % (int)Math.Pow(10, digits);
|
||||
return otp.ToString(new string('0', digits));
|
||||
}
|
||||
}
|
||||
"@
|
||||
|
||||
function Get-TotpCode {
|
||||
param([string]$Secret, [int]$Digits = 6, [int]$Period = 30, [string]$Algorithm = 'SHA256')
|
||||
[Totp]::Now($Secret, $Digits, $Period, $Algorithm)
|
||||
}
|
||||
|
||||
# Add Win32 API for force foreground window
|
||||
Add-Type @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public static class Win32 {
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool AllowSetForegroundWindow(int dwProcessId);
|
||||
|
||||
public const int SW_RESTORE = 9;
|
||||
public const int SW_SHOW = 5;
|
||||
}
|
||||
"@
|
||||
|
||||
# 预先验证证书 SHA1
|
||||
$normalizedExpectedSha1 = Normalize-Sha1 -InputSha1 $ExpectedCertificateSHA1
|
||||
if ($normalizedExpectedSha1) {
|
||||
if ($normalizedExpectedSha1.Length -ne 40) {
|
||||
Write-Host "ERROR: CERTUM_CERTIFICATE_SHA1 is invalid after normalization"
|
||||
Write-Host "Raw length: $($ExpectedCertificateSHA1.Length), normalized length: $($normalizedExpectedSha1.Length)"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# === 认证重试循环(最多 10 次) ===
|
||||
$maxAttempts = 10
|
||||
$authSuccess = $false
|
||||
|
||||
for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
|
||||
Write-Host ""
|
||||
Write-Host "=========================================="
|
||||
Write-Host "=== AUTHENTICATION ATTEMPT $attempt / $maxAttempts ==="
|
||||
Write-Host "=========================================="
|
||||
Write-Host ""
|
||||
|
||||
# 每次重试都重新生成 TOTP(确保验证码有效)
|
||||
$otp = Get-TotpCode -Secret $Base32 -Digits $Digits -Period $Period -Algorithm $Algorithm
|
||||
Write-Host "Generated TOTP code successfully (masked) using $Algorithm algorithm"
|
||||
Write-Host ""
|
||||
|
||||
# 终止之前可能残留的 SimplySign Desktop 进程
|
||||
Get-Process -Name "SimplySignDesktop" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
# 启动 SimplySign Desktop
|
||||
Write-Host "Launching SimplySign Desktop..."
|
||||
Write-Host "Registry pre-configuration should auto-open login dialog"
|
||||
$proc = Start-Process -FilePath $ExePath -PassThru
|
||||
Write-Host "Process started with ID: $($proc.Id)"
|
||||
Write-Host ""
|
||||
|
||||
# 等待应用初始化
|
||||
Write-Host "Waiting for SimplySign Desktop to initialize..."
|
||||
Start-Sleep -Seconds 10
|
||||
|
||||
# Allow our process to set foreground window
|
||||
[Win32]::AllowSetForegroundWindow($proc.Id) | Out-Null
|
||||
|
||||
# Create WScript.Shell for window interaction
|
||||
$wshell = New-Object -ComObject WScript.Shell
|
||||
|
||||
# 尝试聚焦 SimplySign Desktop 窗口
|
||||
Write-Host "Attempting to focus SimplySign Desktop window..."
|
||||
$focused = $false
|
||||
|
||||
# Method 1: Use Win32 API to find and activate window
|
||||
$mainWindowHandle = $proc.MainWindowHandle
|
||||
if ($mainWindowHandle -ne $null -and $mainWindowHandle -ne [IntPtr]::Zero) {
|
||||
[Win32]::ShowWindow($mainWindowHandle, [Win32]::SW_RESTORE) | Out-Null
|
||||
[Win32]::SetForegroundWindow($mainWindowHandle) | Out-Null
|
||||
$focused = $true
|
||||
Write-Host "Focused via MainWindowHandle"
|
||||
} else {
|
||||
Write-Host "MainWindowHandle not available yet, will try other methods..."
|
||||
}
|
||||
|
||||
# Method 2: Find window by title
|
||||
if (-not $focused) {
|
||||
$hwnd = [Win32]::FindWindow($null, "SimplySign Desktop")
|
||||
if ($hwnd -ne [IntPtr]::Zero) {
|
||||
[Win32]::ShowWindow($hwnd, [Win32]::SW_RESTORE) | Out-Null
|
||||
[Win32]::SetForegroundWindow($hwnd) | Out-Null
|
||||
$focused = $true
|
||||
Write-Host "Focused via FindWindow"
|
||||
}
|
||||
}
|
||||
|
||||
# Method 3: AppActivate with extended retries
|
||||
for ($i = 0; (-not $focused) -and ($i -lt 20); $i++) {
|
||||
Start-Sleep -Milliseconds 1000
|
||||
|
||||
# Refresh process handle
|
||||
$proc.Refresh()
|
||||
$mainWindowHandle = $proc.MainWindowHandle
|
||||
if ($mainWindowHandle -ne [IntPtr]::Zero) {
|
||||
[Win32]::ShowWindow($mainWindowHandle, [Win32]::SW_RESTORE) | Out-Null
|
||||
[Win32]::SetForegroundWindow($mainWindowHandle) | Out-Null
|
||||
$focused = $true
|
||||
Write-Host "Focused via MainWindowHandle (attempt $($i + 1))"
|
||||
break
|
||||
}
|
||||
|
||||
$focused = $wshell.AppActivate($proc.Id)
|
||||
if (-not $focused) {
|
||||
$focused = $wshell.AppActivate('SimplySign Desktop')
|
||||
}
|
||||
if (-not $focused) {
|
||||
$focused = $wshell.AppActivate('SimplySign')
|
||||
}
|
||||
Write-Host "Focus attempt $($i + 1): $focused"
|
||||
}
|
||||
|
||||
if (-not $focused) {
|
||||
Write-Host "WARNING: Could not bring SimplySign Desktop to foreground via window handle"
|
||||
Write-Host "SimplySign Desktop may be running as a background/tray process - proceeding with credential injection anyway"
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
|
||||
# Small delay to ensure window is ready for input
|
||||
Start-Sleep -Milliseconds 400
|
||||
|
||||
# 注入凭据: Username + TAB + TOTP + ENTER
|
||||
Write-Host "Injecting credentials into login dialog..."
|
||||
Write-Host "Sending: Username -> TAB -> TOTP -> ENTER"
|
||||
|
||||
$wshell.SendKeys($UserId)
|
||||
Start-Sleep -Milliseconds 200
|
||||
$wshell.SendKeys("{TAB}")
|
||||
Start-Sleep -Milliseconds 200
|
||||
$wshell.SendKeys($otp)
|
||||
Start-Sleep -Milliseconds 200
|
||||
$wshell.SendKeys("{ENTER}")
|
||||
|
||||
Write-Host "Credentials injected successfully"
|
||||
Write-Host ""
|
||||
|
||||
# 等待认证处理
|
||||
Write-Host "Waiting for authentication to complete..."
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
# 验证证书是否可用
|
||||
if ($normalizedExpectedSha1) {
|
||||
Write-Host "Validating certificate availability for expected signing certificate"
|
||||
$ready = $false
|
||||
$withPrivateKey = $false
|
||||
|
||||
for ($i = 0; $i -lt 15; $i++) {
|
||||
$matched = Find-CertificateByThumbprint -Thumbprint $normalizedExpectedSha1
|
||||
if ($matched.Count -gt 0) {
|
||||
$ready = $true
|
||||
$withPrivateKey = ($matched | Where-Object { $_.HasPrivateKey }).Count -gt 0
|
||||
if ($withPrivateKey) {
|
||||
Write-Host "Certificate is available and has private key"
|
||||
break
|
||||
}
|
||||
}
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
|
||||
if ($ready -and $withPrivateKey) {
|
||||
$authSuccess = $true
|
||||
Write-Host "SUCCESS: Authentication verified - certificate with private key is available"
|
||||
break
|
||||
}
|
||||
|
||||
# 认证失败,准备重试
|
||||
if (-not $ready) {
|
||||
Write-Host "WARNING: Target certificate was not found after attempt $attempt"
|
||||
} elseif (-not $withPrivateKey) {
|
||||
Write-Host "WARNING: Target certificate found but no private key available after attempt $attempt"
|
||||
}
|
||||
} else {
|
||||
# 没有指定证书 SHA1,无法验证,假设成功
|
||||
$authSuccess = $true
|
||||
break
|
||||
}
|
||||
|
||||
# 如果不是最后一次尝试,等待后重试
|
||||
if ($attempt -lt $maxAttempts) {
|
||||
Write-Host "Authentication attempt $attempt failed, will retry in 5 seconds..."
|
||||
# 终止当前 SimplySign Desktop 进程
|
||||
$stillRunning = Get-Process -Id $proc.Id -ErrorAction SilentlyContinue
|
||||
if ($stillRunning) {
|
||||
Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
Start-Sleep -Seconds 5
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $authSuccess) {
|
||||
Write-Host ""
|
||||
Write-Host "ERROR: Authentication failed after $maxAttempts attempts"
|
||||
Write-Host "All TOTP injection attempts were unsuccessful"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Verify SimplySign Desktop is still running
|
||||
$stillRunning = Get-Process -Id $proc.Id -ErrorAction SilentlyContinue
|
||||
if ($stillRunning) {
|
||||
Write-Host "SUCCESS: SimplySign Desktop is running"
|
||||
Write-Host "Authentication should be complete"
|
||||
Write-Host "Cloud certificate should now be available"
|
||||
} else {
|
||||
Write-Host "WARNING: SimplySign Desktop process has exited"
|
||||
Write-Host "This may indicate authentication failure"
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=== TOTP AUTHENTICATION COMPLETE ==="
|
||||
Write-Host "Registry pre-configuration + credential injection finished"
|
||||
138
.github/scripts/install-simplysign.sh
vendored
Normal file
138
.github/scripts/install-simplysign.sh
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Install SimplySign Desktop - Clean MSI Installation
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "=== INSTALLING SIMPLYSIGN DESKTOP ==="
|
||||
echo "Using proven installation method from successful testing..."
|
||||
|
||||
# Download SimplySign Desktop MSI
|
||||
CERTUM_INSTALLER="SimplySignDesktop.msi"
|
||||
CERTUM_DOWNLOAD_PAGE="https://pomoc.certum.pl/pl/oprogramowanie/procertum-smartsign/"
|
||||
FALLBACK_MSI_URL="https://files.certum.eu/software/SimplySignDesktop/Windows/9.4.3.90/SimplySignDesktop-9.4.3.90-64-bit-pl.msi"
|
||||
echo "Downloading SimplySign Desktop MSI..."
|
||||
|
||||
# Resolve the latest 64-bit MSI URL from Certum software page to avoid hardcoded version expiry.
|
||||
PAGE_CONTENT="$(curl -L "$CERTUM_DOWNLOAD_PAGE" --fail --max-time 60 || true)"
|
||||
|
||||
MSI_CANDIDATES="$(printf '%s' "$PAGE_CONTENT" | grep -oE 'https://(www\.)?files\.certum\.eu/software/SimplySignDesktop/Windows/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/SimplySignDesktop-[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+-64-bit[^"[:space:]]*\.msi' | sort -u || true)"
|
||||
|
||||
DOWNLOAD_URL=""
|
||||
if [ -n "$MSI_CANDIDATES" ]; then
|
||||
LATEST_VERSION="$(printf '%s\n' "$MSI_CANDIDATES" | sed -E 's#^.*/Windows/([0-9.]+)/.*$#\1#' | sort -V | tail -n1)"
|
||||
LATEST_VERSION_URLS="$(printf '%s\n' "$MSI_CANDIDATES" | grep "/Windows/${LATEST_VERSION}/" || true)"
|
||||
DOWNLOAD_URL="$(printf '%s\n' "$LATEST_VERSION_URLS" | grep -- '-64-bit-pl\.msi$' | head -n1 || true)"
|
||||
|
||||
if [ -z "$DOWNLOAD_URL" ]; then
|
||||
DOWNLOAD_URL="$(printf '%s\n' "$LATEST_VERSION_URLS" | head -n1)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$DOWNLOAD_URL" ]; then
|
||||
echo "WARNING: Could not resolve latest MSI URL from Certum page, using fallback URL"
|
||||
DOWNLOAD_URL="$FALLBACK_MSI_URL"
|
||||
fi
|
||||
|
||||
RESOLVED_VERSION="$(printf '%s' "$DOWNLOAD_URL" | sed -E 's#^.*/Windows/([0-9.]+)/.*$#\1#')"
|
||||
echo "Resolved SimplySign Desktop MSI version: $RESOLVED_VERSION"
|
||||
|
||||
if curl -L "$DOWNLOAD_URL" -o "$CERTUM_INSTALLER" --fail --max-time 60; then
|
||||
echo "✅ Downloaded SimplySign Desktop MSI ($(ls -lh "$CERTUM_INSTALLER" | awk '{print $5}'))"
|
||||
else
|
||||
echo "❌ Failed to download SimplySign Desktop"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install with proven method (matching successful test)
|
||||
echo "Installing SimplySign Desktop..."
|
||||
echo "Full command: msiexec /i \"$CERTUM_INSTALLER\" /quiet /norestart /l*v install.log ALLUSERS=1 REBOOT=ReallySuppress"
|
||||
|
||||
# Check for administrative privileges (like the successful test)
|
||||
ADMIN_RIGHTS=false
|
||||
if powershell -Command "([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)" 2>/dev/null; then
|
||||
echo "✅ Running with administrative privileges"
|
||||
ADMIN_RIGHTS=true
|
||||
else
|
||||
echo "⚠️ No explicit administrative privileges detected"
|
||||
fi
|
||||
|
||||
# Use the exact method that worked: PowerShell with admin privileges
|
||||
if [ "$ADMIN_RIGHTS" = true ]; then
|
||||
echo "Running MSI installation with administrator privileges..."
|
||||
powershell -Command "Start-Process -FilePath 'msiexec.exe' -ArgumentList '/i', '\"$CERTUM_INSTALLER\"', '/quiet', '/norestart', '/l*v', 'install.log', 'ALLUSERS=1', 'REBOOT=ReallySuppress' -Wait -NoNewWindow -PassThru" &
|
||||
INSTALL_PID=$!
|
||||
else
|
||||
echo "Running MSI installation without explicit admin elevation..."
|
||||
timeout 300 msiexec /i "$CERTUM_INSTALLER" /quiet /norestart /l*v install.log ALLUSERS=1 REBOOT=ReallySuppress &
|
||||
INSTALL_PID=$!
|
||||
fi
|
||||
|
||||
# Monitor with the same logic as successful test
|
||||
echo "Monitoring installation progress..."
|
||||
INSTALL_START_TIME=$(date +%s)
|
||||
sleep 10
|
||||
|
||||
# Check if msiexec process is actually running (like successful test)
|
||||
if kill -0 $INSTALL_PID 2>/dev/null; then
|
||||
echo "MSI installation process is running (PID: $INSTALL_PID)"
|
||||
|
||||
# Monitor for up to 3 minutes with status updates
|
||||
for i in {1..18}; do
|
||||
sleep 10
|
||||
CURRENT_TIME=$(date +%s)
|
||||
ELAPSED=$((CURRENT_TIME - INSTALL_START_TIME))
|
||||
|
||||
if kill -0 $INSTALL_PID 2>/dev/null; then
|
||||
echo "Installation still running after ${ELAPSED} seconds..."
|
||||
|
||||
# Check log file growth
|
||||
if [ -f "install.log" ]; then
|
||||
LOG_SIZE=$(stat -c%s "install.log" 2>/dev/null || stat -f%z "install.log" 2>/dev/null || echo 0)
|
||||
echo " Log file size: $LOG_SIZE bytes"
|
||||
fi
|
||||
else
|
||||
echo "MSI installation completed after ${ELAPSED} seconds"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Final wait if still running
|
||||
if kill -0 $INSTALL_PID 2>/dev/null; then
|
||||
echo "Installation taking longer, waiting for completion..."
|
||||
wait $INSTALL_PID 2>/dev/null || echo "Installation process ended"
|
||||
fi
|
||||
else
|
||||
echo "MSI installation process ended quickly"
|
||||
fi
|
||||
|
||||
# Quick success check using proven patterns
|
||||
INSTALLATION_SUCCESSFUL=false
|
||||
if [ -f "install.log" ]; then
|
||||
if grep -qi "Installation.*operation.*completed.*successfully\|Installation.*success.*or.*error.*status.*0\|MainEngineThread.*is.*returning.*0\|Windows.*Installer.*installed.*the.*product" install.log 2>/dev/null; then
|
||||
echo "✅ Installation successful (confirmed by log patterns)"
|
||||
INSTALLATION_SUCCESSFUL=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Verify installation directory
|
||||
INSTALL_PATH="/c/Program Files/Certum/SimplySign Desktop"
|
||||
if [ -d "$INSTALL_PATH" ]; then
|
||||
echo "✅ SimplySign Desktop installed successfully"
|
||||
echo "✅ Virtual card emulation now active for code signing"
|
||||
INSTALLATION_SUCCESSFUL=true
|
||||
|
||||
# Set output for GitHub Actions
|
||||
if [ -n "${GITHUB_OUTPUT:-}" ]; then
|
||||
echo "SIMPLYSIGN_PATH=$INSTALL_PATH" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$INSTALLATION_SUCCESSFUL" = false ]; then
|
||||
echo "❌ Installation verification failed"
|
||||
echo "Last 10 lines of install log:"
|
||||
tail -10 install.log 2>/dev/null || echo "No install log available"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🎉 SimplySign Desktop installation completed successfully!"
|
||||
182
.github/scripts/sign-windows.ps1
vendored
Normal file
182
.github/scripts/sign-windows.ps1
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
# Sign-Windows.ps1
|
||||
# Signs Windows EasyTier executables and libraries with a Certum SimplySign cloud certificate.
|
||||
|
||||
param(
|
||||
[string]$TargetDirectory = "sign_binaries",
|
||||
[string]$CertificateSHA1 = $env:CERTUM_CERTIFICATE_SHA1,
|
||||
[string]$TimestampServer = "http://time.certum.pl"
|
||||
)
|
||||
|
||||
function Get-LatestSignToolPath {
|
||||
$windowsKitsBin = Join-Path ${env:ProgramFiles(x86)} "Windows Kits\10\bin"
|
||||
if (Test-Path $windowsKitsBin) {
|
||||
$candidate = (
|
||||
Get-ChildItem -Path $windowsKitsBin -Recurse -File -Filter "signtool.exe" -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.FullName -match "\\x64\\signtool\.exe$" } |
|
||||
ForEach-Object {
|
||||
$version = [version]"0.0"
|
||||
if ($_.FullName -match "\\bin\\([^\\]+)\\x64\\signtool\.exe$") {
|
||||
try {
|
||||
$version = [version]$matches[1]
|
||||
} catch {
|
||||
$version = [version]"0.0"
|
||||
}
|
||||
}
|
||||
[PSCustomObject]@{
|
||||
Path = $_.FullName
|
||||
Version = $version
|
||||
}
|
||||
} |
|
||||
Sort-Object -Property Version -Descending |
|
||||
Select-Object -First 1
|
||||
)
|
||||
|
||||
if ($candidate) {
|
||||
return $candidate.Path
|
||||
}
|
||||
}
|
||||
|
||||
$cmd = Get-Command "signtool.exe" -ErrorAction SilentlyContinue
|
||||
if ($cmd) {
|
||||
return $cmd.Source
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Find-TargetCertificate {
|
||||
param([string]$Thumbprint)
|
||||
|
||||
$all = Get-ChildItem -Path "Cert:\CurrentUser\My", "Cert:\LocalMachine\My" -ErrorAction SilentlyContinue
|
||||
# 对证书库中的 Thumbprint 同样做规范化(去除不可见字符、统一大写),避免 BOM 或格式差异导致匹配失败
|
||||
return @($all | Where-Object {
|
||||
$normalizedStoreThumprint = ($_.Thumbprint -replace "[^a-fA-F0-9]", "").ToUpperInvariant()
|
||||
$normalizedStoreThumprint -eq $Thumbprint
|
||||
})
|
||||
}
|
||||
|
||||
function Show-PrivateKeyCertificateHints {
|
||||
$candidates = Get-ChildItem -Path "Cert:\CurrentUser\My", "Cert:\LocalMachine\My" -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.HasPrivateKey }
|
||||
|
||||
if (($null -eq $candidates) -or ($candidates.Count -eq 0)) {
|
||||
Write-Host "No certificates with private keys were found in Personal stores"
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "Certificates with private keys are present in Personal stores, but details are hidden for security"
|
||||
}
|
||||
|
||||
Write-Host "=== WINDOWS BINARY SIGNING (CERTUM SIMPLYSIGN) ==="
|
||||
Write-Host "Target directory: $TargetDirectory"
|
||||
|
||||
if (-not (Test-Path $TargetDirectory)) {
|
||||
Write-Host "ERROR: Target directory not found: $TargetDirectory"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not $CertificateSHA1) {
|
||||
Write-Host "ERROR: CERTUM_CERTIFICATE_SHA1 environment variable not provided"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$normalizedSha1 = ($CertificateSHA1 -replace "[^a-fA-F0-9]", "").ToUpperInvariant()
|
||||
if ($normalizedSha1.Length -ne 40) {
|
||||
Write-Host "ERROR: CERTUM_CERTIFICATE_SHA1 is invalid after normalization"
|
||||
Write-Host "Raw length: $($CertificateSHA1.Length), normalized length: $($normalizedSha1.Length)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Expected signing certificate thumbprint has been received (masked)"
|
||||
|
||||
$targetCerts = Find-TargetCertificate -Thumbprint $normalizedSha1
|
||||
if (($null -eq $targetCerts) -or ($targetCerts.Count -eq 0)) {
|
||||
Write-Host "ERROR: Target certificate not found in Cert:\CurrentUser\My or Cert:\LocalMachine\My"
|
||||
Write-Host "Authentication likely failed or CERTUM_CERTIFICATE_SHA1 is incorrect"
|
||||
Show-PrivateKeyCertificateHints
|
||||
exit 1
|
||||
}
|
||||
|
||||
$targetWithPrivateKey = @($targetCerts | Where-Object { $_.HasPrivateKey })
|
||||
if (($null -eq $targetWithPrivateKey) -or ($targetWithPrivateKey.Count -eq 0)) {
|
||||
Write-Host "ERROR: Target certificate exists but has no available private key"
|
||||
Write-Host "Signing cannot continue without private key access"
|
||||
Show-PrivateKeyCertificateHints
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Locating signtool..."
|
||||
$signTool = Get-LatestSignToolPath
|
||||
if (-not $signTool) {
|
||||
Write-Host "ERROR: signtool.exe not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Found signtool: $signTool"
|
||||
|
||||
Write-Host "Scanning for Windows binaries to sign (.exe, .dll)..."
|
||||
$filesToSign = Get-ChildItem -Path $TargetDirectory -Recurse -File |
|
||||
Where-Object { $_.Extension -iin @(".exe", ".dll") }
|
||||
|
||||
if (($null -eq $filesToSign) -or ($filesToSign.Count -eq 0)) {
|
||||
Write-Host "WARNING: No signable files (.exe, .dll) found to sign"
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host "Found $($filesToSign.Count) files to sign"
|
||||
$signedCount = 0
|
||||
$failedCount = 0
|
||||
|
||||
foreach ($file in $filesToSign) {
|
||||
Write-Host "=== Signing: $($file.Name) ==="
|
||||
Write-Host "Path: $($file.FullName)"
|
||||
|
||||
$attempts = @(
|
||||
@{ Name = "SHA1 thumbprint + /td SHA256"; Args = @("sign", "/sha1", $normalizedSha1, "/tr", $TimestampServer, "/td", "SHA256", "/fd", "SHA256", "/v", $file.FullName) },
|
||||
@{ Name = "SHA1 thumbprint in CurrentUser\\My"; Args = @("sign", "/sha1", $normalizedSha1, "/s", "My", "/tr", $TimestampServer, "/td", "SHA256", "/fd", "SHA256", "/v", $file.FullName) },
|
||||
@{ Name = "SHA1 thumbprint in LocalMachine\\My"; Args = @("sign", "/sha1", $normalizedSha1, "/sm", "/s", "My", "/tr", $TimestampServer, "/td", "SHA256", "/fd", "SHA256", "/v", $file.FullName) },
|
||||
@{ Name = "Auto-select cert (fallback)"; Args = @("sign", "/a", "/tr", $TimestampServer, "/td", "SHA256", "/fd", "SHA256", "/v", $file.FullName) }
|
||||
)
|
||||
|
||||
$signed = $false
|
||||
foreach ($attempt in $attempts) {
|
||||
Write-Host "Attempt: $($attempt.Name)"
|
||||
$signOutput = & $signTool @($attempt.Args) 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "SUCCESS: $($attempt.Name)"
|
||||
$signed = $true
|
||||
break
|
||||
}
|
||||
|
||||
Write-Host "FAILED: $($attempt.Name)"
|
||||
Write-Host "signtool returned a non-zero exit code; detailed output is hidden for security"
|
||||
}
|
||||
|
||||
if ($signed) {
|
||||
$signedCount++
|
||||
$verifyOutput = & $signTool verify /pa /v $file.FullName 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "VERIFIED: Signature verification successful"
|
||||
} else {
|
||||
Write-Host "WARNING: Signature verification failed"
|
||||
Write-Host "Detailed verification output is hidden for security"
|
||||
}
|
||||
} else {
|
||||
$failedCount++
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
Write-Host "=== SIGNING SUMMARY ==="
|
||||
Write-Host "Total files: $($filesToSign.Count)"
|
||||
Write-Host "Successfully signed: $signedCount"
|
||||
Write-Host "Failed to sign: $failedCount"
|
||||
|
||||
if ($failedCount -eq 0) {
|
||||
Write-Host "ALL WINDOWS BINARIES SIGNED SUCCESSFULLY"
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host "SOME WINDOWS BINARIES FAILED TO SIGN"
|
||||
exit 1
|
||||
510
.github/workflows/release.yml
vendored
Normal file
510
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,510 @@
|
||||
name: OpenP2P Release
|
||||
|
||||
on:
|
||||
#push:
|
||||
# branches: [master]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_type:
|
||||
description: '发布类型 (beta: 测试版, stable: 正式版)'
|
||||
type: choice
|
||||
options:
|
||||
- beta
|
||||
- stable
|
||||
default: beta
|
||||
required: true
|
||||
version:
|
||||
description: '正式版版本号 (e.g. v3.25.11),beta发布时可留空'
|
||||
type: string
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
BINARY_NAME: openp2p
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.os }}-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Windows
|
||||
- { os: windows, arch: amd64, runner: ubuntu-latest, goos: windows, goarch: amd64, ext: .exe }
|
||||
- { os: windows, arch: arm64, runner: ubuntu-latest, goos: windows, goarch: arm64, ext: .exe }
|
||||
- { os: windows, arch: i386, runner: ubuntu-latest, goos: windows, goarch: 386, ext: .exe }
|
||||
# Linux
|
||||
- { os: linux, arch: amd64, runner: ubuntu-latest, goos: linux, goarch: amd64, ext: '' }
|
||||
- { os: linux, arch: arm64, runner: ubuntu-latest, goos: linux, goarch: arm64, ext: '' }
|
||||
- { os: linux, arch: i386, runner: ubuntu-latest, goos: linux, goarch: 386, ext: '' }
|
||||
- { os: linux, arch: mips, runner: ubuntu-latest, goos: linux, goarch: mips, ext: '' }
|
||||
- { os: linux, arch: mips64, runner: ubuntu-latest, goos: linux, goarch: mips64, ext: '' }
|
||||
# Darwin
|
||||
- { os: darwin, arch: amd64, runner: ubuntu-latest, goos: darwin, goarch: amd64, ext: '' }
|
||||
- { os: darwin, arch: arm64, runner: ubuntu-latest, goos: darwin, goarch: arm64, ext: '' }
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
CGO_ENABLED: '0'
|
||||
GOPROXY: https://goproxy.io,direct
|
||||
run: |
|
||||
OUTPUT_NAME="${{ env.BINARY_NAME }}-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }}"
|
||||
go build -trimpath -ldflags="-s -w" -o "$OUTPUT_NAME" cmd/openp2p.go
|
||||
echo "OUTPUT_NAME=$OUTPUT_NAME" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BINARY_NAME }}-${{ matrix.os }}-${{ matrix.arch }}
|
||||
path: ${{ env.OUTPUT_NAME }}
|
||||
retention-days: 7
|
||||
|
||||
# build-android:
|
||||
# name: Build Android APK
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v6
|
||||
#
|
||||
# - name: Setup Go
|
||||
# uses: actions/setup-go@v5
|
||||
# with:
|
||||
# go-version: '1.23'
|
||||
#
|
||||
# - name: Setup JDK
|
||||
# uses: actions/setup-java@v4
|
||||
# with:
|
||||
# java-version: '17'
|
||||
# distribution: 'temurin'
|
||||
#
|
||||
# - name: Setup Android SDK & NDK
|
||||
# uses: android-actions/setup-android@v3
|
||||
# with:
|
||||
# packages: 'build-tools;30.0.3 ndk;21.4.7075529 platform-tools platforms;android-31'
|
||||
#
|
||||
# - name: Setup Android Environment
|
||||
# run: |
|
||||
# echo "$ANDROID_HOME/ndk/21.4.7075529" >> $GITHUB_PATH
|
||||
# echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/21.4.7075529" >> $GITHUB_ENV
|
||||
#
|
||||
# - name: Build Go mobile library (gomobile bind)
|
||||
# env:
|
||||
# GOPROXY: https://goproxy.io,direct
|
||||
# run: |
|
||||
# # Install gomobile and gobind at the same pinned commit to avoid @latest resolution
|
||||
# go install golang.org/x/mobile/cmd/gomobile@7c4916698cc93475ebfea76748ee0faba2deb2a5
|
||||
# go install golang.org/x/mobile/cmd/gobind@7c4916698cc93475ebfea76748ee0faba2deb2a5
|
||||
# gomobile init
|
||||
# go get -v golang.org/x/mobile/bind@7c4916698cc93475ebfea76748ee0faba2deb2a5
|
||||
#
|
||||
# cd core
|
||||
# gomobile bind -target android -v -androidapi 16
|
||||
#
|
||||
# # Copy artifacts to app libs
|
||||
# mkdir -p ../app/app/libs
|
||||
# cp openp2p.aar openp2p-sources.jar ../app/app/libs/
|
||||
# echo "Go mobile library built and copied to app/app/libs/"
|
||||
# ls -la ../app/app/libs/
|
||||
#
|
||||
# - name: Build unsigned APK
|
||||
# working-directory: app
|
||||
# run: |
|
||||
# chmod +x gradlew
|
||||
# ./gradlew assembleRelease
|
||||
#
|
||||
# # Find the built APK
|
||||
# APK_PATH=$(find . -name "*.apk" -path "*/release/*" | head -1)
|
||||
# if [ -z "$APK_PATH" ]; then
|
||||
# APK_PATH=$(find . -name "*.apk" | head -1)
|
||||
# fi
|
||||
#
|
||||
# if [ -n "$APK_PATH" ]; then
|
||||
# cp "$APK_PATH" ../openp2p-android.apk
|
||||
# echo "APK built: $APK_PATH"
|
||||
# else
|
||||
# echo "ERROR: No APK found"
|
||||
# exit 1
|
||||
# fi
|
||||
#
|
||||
# - name: Upload APK artifact
|
||||
# uses: actions/upload-artifact@v4
|
||||
# with:
|
||||
# name: openp2p-android-apk
|
||||
# path: openp2p-android.apk
|
||||
# retention-days: 7
|
||||
|
||||
sign:
|
||||
name: Sign Artifacts (Certum SimplySign)
|
||||
needs: [build]
|
||||
runs-on: windows-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Download Windows artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: openp2p-windows-*
|
||||
path: sign_binaries/windows
|
||||
merge-multiple: true
|
||||
|
||||
# - name: Download Android APK
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: openp2p-android-apk
|
||||
# path: sign_binaries/android
|
||||
|
||||
# - name: Setup JDK (for jarsigner)
|
||||
# uses: actions/setup-java@v4
|
||||
# with:
|
||||
# java-version: '17'
|
||||
# distribution: 'temurin'
|
||||
|
||||
- name: Setup Certum Code Signing (Windows)
|
||||
shell: bash
|
||||
run: |
|
||||
echo "=== SETTING UP CERTUM CODE SIGNING FOR WINDOWS ==="
|
||||
echo "Installing SimplySign Desktop and configuring for automatic authentication"
|
||||
|
||||
chmod +x ./.github/scripts/install-simplysign.sh
|
||||
./.github/scripts/install-simplysign.sh
|
||||
|
||||
echo "Configuring registry for automatic login dialog..."
|
||||
powershell -ExecutionPolicy Bypass -File "./.github/scripts/configure-simplysign-registry.ps1"
|
||||
|
||||
echo "Certum signing environment ready"
|
||||
|
||||
- name: Authenticate Certum (Windows)
|
||||
shell: bash
|
||||
env:
|
||||
CERTUM_OTP_URI: ${{ secrets.CERTUM_OTP_URI }}
|
||||
CERTUM_USERNAME: ${{ secrets.CERTUM_USERNAME }}
|
||||
CERTUM_CERTIFICATE_SHA1: ${{ secrets.CERTUM_CERTIFICATE_SHA1 }}
|
||||
CERTUM_EXE_PATH: ${{ secrets.CERTUM_EXE_PATH }}
|
||||
run: |
|
||||
echo "=== CERTUM AUTHENTICATION ==="
|
||||
echo "Authenticating with Certum cloud certificate using TOTP"
|
||||
|
||||
for attempt in 1 2 3; do
|
||||
echo "Authentication attempt ${attempt}/3"
|
||||
if powershell -ExecutionPolicy Bypass -File "./.github/scripts/connect-simplySign-enhanced.ps1"; then
|
||||
echo "Authentication completed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$attempt" -lt 3 ]; then
|
||||
echo "Authentication attempt failed, retrying in 10 seconds..."
|
||||
sleep 10
|
||||
fi
|
||||
done
|
||||
|
||||
echo "ERROR: Certum authentication failed after 3 attempts"
|
||||
exit 1
|
||||
|
||||
- name: Verify Certificate and Sign Windows Binaries
|
||||
shell: bash
|
||||
env:
|
||||
CERTUM_CERTIFICATE_SHA1: ${{ secrets.CERTUM_CERTIFICATE_SHA1 }}
|
||||
run: |
|
||||
echo "=== CERTIFICATE VERIFICATION AND WINDOWS BINARY SIGNING ==="
|
||||
echo "Allowing connection to stabilize..."
|
||||
sleep 10
|
||||
|
||||
echo "Comprehensive certificate availability check..."
|
||||
echo ""
|
||||
|
||||
echo "Skipping certificate store dump to avoid exposing certificate metadata in logs"
|
||||
|
||||
echo ""
|
||||
echo "=== PKCS#11 Library Check ==="
|
||||
if [ -f "/c/Windows/System32/SimplySignPKCS.dll" ]; then
|
||||
echo "PKCS#11 library present: /c/Windows/System32/SimplySignPKCS.dll"
|
||||
ls -la "/c/Windows/System32/SimplySignPKCS.dll"
|
||||
else
|
||||
echo "PKCS#11 library not found"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== SimplySign Desktop Status ==="
|
||||
powershell -Command "
|
||||
Write-Host 'SimplySign Desktop process status:'
|
||||
Get-Process -Name '*SimplySign*' -ErrorAction SilentlyContinue |
|
||||
Select-Object Name, Id, MainWindowTitle, Responding |
|
||||
Format-Table -AutoSize
|
||||
"
|
||||
|
||||
echo ""
|
||||
echo "Certificate debugging completed - proceeding to signing..."
|
||||
echo ""
|
||||
|
||||
powershell -ExecutionPolicy Bypass -File "./.github/scripts/sign-windows.ps1" -TargetDirectory "sign_binaries/windows"
|
||||
|
||||
echo "Windows binary signing completed"
|
||||
|
||||
# - name: Sign Android APK (jarsigner + PKCS#11)
|
||||
# shell: pwsh
|
||||
# run: |
|
||||
# Write-Host "=== SIGNING ANDROID APK WITH CERTUM CLOUD CERTIFICATE (PKCS#11) ==="
|
||||
#
|
||||
# # Create PKCS#11 config file for Certum SimplySign
|
||||
# $pkcs11Config = @"
|
||||
# name = CertumSimplySign
|
||||
# library = C:\Program Files\Certum\SimplySign Desktop\cryptoCertum3PKCS.dll
|
||||
# slot = 0
|
||||
# "@
|
||||
# $pkcs11Config | Out-File -FilePath "pkcs11.cfg" -Encoding ASCII
|
||||
#
|
||||
# Write-Host "PKCS#11 config created"
|
||||
#
|
||||
# # Find APK files
|
||||
# $apkFiles = Get-ChildItem -Path "sign_binaries/android" -Recurse -Include *.apk
|
||||
#
|
||||
# if ($apkFiles.Count -eq 0) {
|
||||
# Write-Host "No APK files found to sign"
|
||||
# exit 0
|
||||
# }
|
||||
#
|
||||
# # Certum SimplySign default key alias is "1"
|
||||
# $keyAlias = "1"
|
||||
# Write-Host "Using key alias: $keyAlias"
|
||||
#
|
||||
# foreach ($apk in $apkFiles) {
|
||||
# Write-Host "Signing APK: $($apk.FullName)"
|
||||
# try {
|
||||
# & jarsigner -verbose `
|
||||
# -keystore NONE `
|
||||
# -storetype PKCS11 `
|
||||
# -providerClass sun.security.pkcs11.SunPKCS11 `
|
||||
# -providerArg pkcs11.cfg `
|
||||
# -tsa http://time.certum.pl `
|
||||
# -signedjar "$($apk.DirectoryName)\signed-$($apk.Name)" `
|
||||
# "$($apk.FullName)" `
|
||||
# $keyAlias
|
||||
#
|
||||
# # Replace original with signed version
|
||||
# Move-Item -Path "$($apk.DirectoryName)\signed-$($apk.Name)" -Destination $apk.FullName -Force
|
||||
# Write-Host " OK: APK signed successfully"
|
||||
# } catch {
|
||||
# Write-Host " WARNING: Failed to sign APK - $($_.Exception.Message)"
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# Write-Host "=== ANDROID APK SIGNING COMPLETE ==="
|
||||
# continue-on-error: true
|
||||
|
||||
- name: Verify Windows Signatures
|
||||
shell: pwsh
|
||||
run: |
|
||||
$signedFiles = Get-ChildItem -Path "sign_binaries/windows" -Recurse -Include *.exe
|
||||
foreach ($file in $signedFiles) {
|
||||
$result = Get-AuthenticodeSignature -FilePath $file.FullName
|
||||
$status = if ($result.Status -eq "Valid") { "VALID" } else { "INVALID/UNSIGNED ($($result.Status))" }
|
||||
Write-Host "$($file.Name): $status"
|
||||
}
|
||||
continue-on-error: true
|
||||
|
||||
# - name: Verify APK Signature
|
||||
# shell: pwsh
|
||||
# run: |
|
||||
# $apkFiles = Get-ChildItem -Path "sign_binaries/android" -Recurse -Include *.apk
|
||||
# foreach ($apk in $apkFiles) {
|
||||
# Write-Host "Verifying: $($apk.Name)"
|
||||
# & jarsigner -verify -verbose -certs "$($apk.FullName)" 2>&1 | Select-Object -First 10
|
||||
# }
|
||||
# continue-on-error: true
|
||||
|
||||
- name: Upload signed Windows artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: signed-windows-artifacts
|
||||
path: sign_binaries/windows
|
||||
retention-days: 7
|
||||
|
||||
# - name: Upload signed Android APK
|
||||
# uses: actions/upload-artifact@v4
|
||||
# with:
|
||||
# name: signed-android-apk
|
||||
# path: sign_binaries/android
|
||||
# retention-days: 7
|
||||
|
||||
release:
|
||||
name: Create Release
|
||||
needs: [build, sign]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: |
|
||||
RELEASE_TYPE="${{ inputs.release_type }}"
|
||||
if [ "$RELEASE_TYPE" = "stable" ]; then
|
||||
VERSION="${{ inputs.version }}"
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "ERROR: stable release requires a version number"
|
||||
exit 1
|
||||
fi
|
||||
IS_BETA="false"
|
||||
else
|
||||
VERSION="beta"
|
||||
IS_BETA="true"
|
||||
fi
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "is_beta=$IS_BETA" >> $GITHUB_OUTPUT
|
||||
echo "Version: $VERSION, Is Beta: $IS_BETA, Release Type: $RELEASE_TYPE"
|
||||
|
||||
# Try to download signed Windows artifacts first, fall back to unsigned
|
||||
- name: Download signed Windows artifacts
|
||||
id: download-signed-win
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: signed-windows-artifacts
|
||||
path: release_binaries
|
||||
continue-on-error: true
|
||||
|
||||
- name: Download unsigned Windows artifacts (fallback)
|
||||
if: steps.download-signed-win.outcome != 'success'
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: openp2p-windows-*
|
||||
path: release_binaries
|
||||
merge-multiple: true
|
||||
|
||||
# Try to download signed Android APK first, fall back to unsigned
|
||||
# - name: Download signed Android APK
|
||||
# id: download-signed-android
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: signed-android-apk
|
||||
# path: release_binaries
|
||||
# continue-on-error: true
|
||||
#
|
||||
# - name: Download unsigned Android APK (fallback)
|
||||
# if: steps.download-signed-android.outcome != 'success'
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: openp2p-android-apk
|
||||
# path: release_binaries
|
||||
|
||||
- name: Download Linux artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: openp2p-linux-*
|
||||
path: release_binaries
|
||||
merge-multiple: true
|
||||
|
||||
- name: Download Darwin artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: openp2p-darwin-*
|
||||
path: release_binaries
|
||||
merge-multiple: true
|
||||
|
||||
- name: Package release assets
|
||||
env:
|
||||
VERSION: ${{ steps.version.outputs.version }}
|
||||
run: |
|
||||
mkdir -p release_assets
|
||||
cd release_binaries
|
||||
chmod +x * 2>/dev/null || true
|
||||
|
||||
for file in *; do
|
||||
if [ -f "$file" ]; then
|
||||
if [[ "$file" == *.exe ]]; then
|
||||
zip "../release_assets/${file%.exe}-${VERSION}.zip" "$file"
|
||||
elif [[ "$file" == *.apk ]]; then
|
||||
# APK files: rename with version, no compression needed
|
||||
cp "$file" "../release_assets/${file%.apk}-${VERSION}.apk"
|
||||
else
|
||||
tar czf "../release_assets/${file}-${VERSION}.tar.gz" "$file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
cd ../release_assets
|
||||
echo "=== Release Assets ==="
|
||||
ls -la
|
||||
|
||||
- name: Generate release notes
|
||||
id: notes
|
||||
env:
|
||||
VERSION: ${{ steps.version.outputs.version }}
|
||||
IS_BETA: ${{ steps.version.outputs.is_beta }}
|
||||
run: |
|
||||
if [ "$IS_BETA" = "true" ]; then
|
||||
cat > release_notes.md << EOF
|
||||
## OpenP2P Beta Release (latest unstable)
|
||||
|
||||
Built from commit \`${{ github.sha }}\` on $(date -u +"%Y-%m-%d %H:%M UTC").
|
||||
|
||||
### Supported Platforms
|
||||
| OS | Architectures |
|
||||
|---|---|
|
||||
| Windows | amd64, arm64, i386 |
|
||||
| Linux | amd64, arm64, i386, mips, mips64 |
|
||||
| Darwin (macOS) | amd64, arm64 |
|
||||
| Android | amd64, arm64 |
|
||||
|
||||
> **Note**: This is a pre-release build and may be unstable. This release is automatically updated on every push to master.
|
||||
EOF
|
||||
else
|
||||
cat > release_notes.md << EOF
|
||||
## OpenP2P $VERSION
|
||||
|
||||
### Supported Platforms
|
||||
| OS | Architectures |
|
||||
|---|---|
|
||||
| Windows | amd64, arm64, i386 |
|
||||
| Linux | amd64, arm64, i386, mips, mips64 |
|
||||
| Darwin (macOS) | amd64, arm64 |
|
||||
| Android | amd64, arm64 |
|
||||
EOF
|
||||
fi
|
||||
|
||||
- name: Delete existing Beta Release
|
||||
if: steps.version.outputs.is_beta == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Delete existing beta release if it exists
|
||||
gh release delete beta --yes --cleanup-tag 2>/dev/null || true
|
||||
|
||||
- name: Create Beta Release
|
||||
if: steps.version.outputs.is_beta == 'true'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: "Beta (latest unstable)"
|
||||
tag_name: beta
|
||||
body_path: release_notes.md
|
||||
prerelease: true
|
||||
files: release_assets/*
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create Stable Release
|
||||
if: steps.version.outputs.is_beta == 'false'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: ${{ steps.version.outputs.version }}
|
||||
tag_name: ${{ steps.version.outputs.version }}
|
||||
body_path: release_notes.md
|
||||
prerelease: false
|
||||
make_latest: true
|
||||
files: release_assets/*
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
171
.github/workflows/signfile.yml
vendored
Normal file
171
.github/workflows/signfile.yml
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
name: Sign External Binaries
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
url_x86:
|
||||
description: 'X86 (i386) 二进制文件下载地址'
|
||||
type: string
|
||||
required: false
|
||||
default: 'https://console.openpxp.com/download/v1/latest/openp2p386-latest.exe'
|
||||
url_x64:
|
||||
description: 'X64 (amd64) 二进制文件下载地址'
|
||||
type: string
|
||||
required: false
|
||||
default: 'https://console.openpxp.com/download/v1/latest/openp2p64-latest.exe'
|
||||
url_arm:
|
||||
description: 'ARM (arm64) 二进制文件下载地址'
|
||||
type: string
|
||||
required: false
|
||||
default: 'https://console.openpxp.com/download/v1/latest/openp2parm64-latest.exe'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sign:
|
||||
name: Sign Binaries (Certum SimplySign)
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Validate inputs
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -z "${{ inputs.url_x86 }}" ] && [ -z "${{ inputs.url_x64 }}" ] && [ -z "${{ inputs.url_arm }}" ]; then
|
||||
echo "ERROR: 至少需要提供一个二进制文件下载地址"
|
||||
exit 1
|
||||
fi
|
||||
echo "=== 输入的下载地址 ==="
|
||||
[ -n "${{ inputs.url_x86 }}" ] && echo "X86: ${{ inputs.url_x86 }}"
|
||||
[ -n "${{ inputs.url_x64 }}" ] && echo "X64: ${{ inputs.url_x64 }}"
|
||||
[ -n "${{ inputs.url_arm }}" ] && echo "ARM: ${{ inputs.url_arm }}"
|
||||
|
||||
- name: Download binaries
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p sign_binaries
|
||||
|
||||
download_file() {
|
||||
local url="$1"
|
||||
local label="$2"
|
||||
if [ -z "$url" ]; then
|
||||
echo "跳过 ${label}: 未提供下载地址"
|
||||
return
|
||||
fi
|
||||
echo "正在下载 ${label}: ${url}"
|
||||
# 从 URL 中提取文件名
|
||||
local filename=$(basename "$url" | sed 's/[?#].*//')
|
||||
# 如果文件名为空或不合理,使用 label 作为文件名
|
||||
if [ -z "$filename" ] || [ "$filename" = "/" ]; then
|
||||
filename="${label}-binary.exe"
|
||||
fi
|
||||
curl -fSL --retry 3 --retry-delay 5 -o "sign_binaries/${filename}" "$url"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "下载成功: ${filename}"
|
||||
else
|
||||
echo "ERROR: 下载失败 ${label}: ${url}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
download_file "${{ inputs.url_x86 }}" "x86"
|
||||
download_file "${{ inputs.url_x64 }}" "x64"
|
||||
download_file "${{ inputs.url_arm }}" "arm"
|
||||
|
||||
echo ""
|
||||
echo "=== 已下载的文件 ==="
|
||||
ls -la sign_binaries/
|
||||
|
||||
- name: Setup Certum Code Signing (Windows)
|
||||
shell: bash
|
||||
run: |
|
||||
echo "=== SETTING UP CERTUM CODE SIGNING FOR WINDOWS ==="
|
||||
echo "Installing SimplySign Desktop and configuring for automatic authentication"
|
||||
|
||||
chmod +x ./.github/scripts/install-simplysign.sh
|
||||
./.github/scripts/install-simplysign.sh
|
||||
|
||||
echo "Configuring registry for automatic login dialog..."
|
||||
powershell -ExecutionPolicy Bypass -File "./.github/scripts/configure-simplysign-registry.ps1"
|
||||
|
||||
echo "Certum signing environment ready"
|
||||
|
||||
- name: Authenticate Certum (Windows)
|
||||
shell: bash
|
||||
env:
|
||||
CERTUM_OTP_URI: ${{ secrets.CERTUM_OTP_URI }}
|
||||
CERTUM_USERNAME: ${{ secrets.CERTUM_USERNAME }}
|
||||
CERTUM_CERTIFICATE_SHA1: ${{ secrets.CERTUM_CERTIFICATE_SHA1 }}
|
||||
CERTUM_EXE_PATH: ${{ secrets.CERTUM_EXE_PATH }}
|
||||
run: |
|
||||
echo "=== CERTUM AUTHENTICATION ==="
|
||||
echo "Authenticating with Certum cloud certificate using TOTP"
|
||||
|
||||
for attempt in 1 2 3; do
|
||||
echo "Authentication attempt ${attempt}/3"
|
||||
if powershell -ExecutionPolicy Bypass -File "./.github/scripts/connect-simplySign-enhanced.ps1"; then
|
||||
echo "Authentication completed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$attempt" -lt 3 ]; then
|
||||
echo "Authentication attempt failed, retrying in 10 seconds..."
|
||||
sleep 10
|
||||
fi
|
||||
done
|
||||
|
||||
echo "ERROR: Certum authentication failed after 3 attempts"
|
||||
exit 1
|
||||
|
||||
- name: Sign Binaries
|
||||
shell: bash
|
||||
env:
|
||||
CERTUM_CERTIFICATE_SHA1: ${{ secrets.CERTUM_CERTIFICATE_SHA1 }}
|
||||
run: |
|
||||
echo "=== SIGNING BINARIES ==="
|
||||
echo "Allowing connection to stabilize..."
|
||||
sleep 10
|
||||
|
||||
echo "=== PKCS#11 Library Check ==="
|
||||
if [ -f "/c/Windows/System32/SimplySignPKCS.dll" ]; then
|
||||
echo "PKCS#11 library present: /c/Windows/System32/SimplySignPKCS.dll"
|
||||
else
|
||||
echo "PKCS#11 library not found"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== SimplySign Desktop Status ==="
|
||||
powershell -Command "
|
||||
Write-Host 'SimplySign Desktop process status:'
|
||||
Get-Process -Name '*SimplySign*' -ErrorAction SilentlyContinue |
|
||||
Select-Object Name, Id, MainWindowTitle, Responding |
|
||||
Format-Table -AutoSize
|
||||
"
|
||||
|
||||
echo ""
|
||||
echo "Proceeding to signing..."
|
||||
echo ""
|
||||
|
||||
powershell -ExecutionPolicy Bypass -File "./.github/scripts/sign-windows.ps1" -TargetDirectory "sign_binaries"
|
||||
|
||||
echo "Binary signing completed"
|
||||
|
||||
- name: Verify Signatures
|
||||
shell: pwsh
|
||||
run: |
|
||||
$signedFiles = Get-ChildItem -Path "sign_binaries" -Recurse -File
|
||||
foreach ($file in $signedFiles) {
|
||||
$result = Get-AuthenticodeSignature -FilePath $file.FullName
|
||||
$status = if ($result.Status -eq "Valid") { "VALID" } else { "INVALID/UNSIGNED ($($result.Status))" }
|
||||
Write-Host "$($file.Name): $status"
|
||||
}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload signed artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: signed-binaries
|
||||
path: sign_binaries/
|
||||
retention-days: 30
|
||||
Reference in New Issue
Block a user