Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion scripts/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,24 @@ function Install-ViaBinary {
$expectedLine = $checksums | Where-Object { $_ -match $archiveName }
if ($expectedLine) {
$expectedChecksum = ($expectedLine -split "\s+")[0]
$actualChecksum = (Get-FileHash -Path $archivePath -Algorithm SHA256).Hash.ToLower()

# Compute SHA256 hash - use Get-FileHash if available (PS 4.0+),
# otherwise fall back to .NET cryptography for edge cases where
# the cmdlet is unavailable (corrupted install, restricted context, etc.)
if (Get-Command Get-FileHash -ErrorAction SilentlyContinue) {
$actualChecksum = (Get-FileHash -Path $archivePath -Algorithm SHA256).Hash.ToLower()
} else {
# Fallback using .NET for environments where Get-FileHash is unavailable
$sha256 = [System.Security.Cryptography.SHA256]::Create()
$fileStream = [System.IO.File]::OpenRead($archivePath)
try {
$hashBytes = $sha256.ComputeHash($fileStream)
$actualChecksum = [System.BitConverter]::ToString($hashBytes).Replace("-", "").ToLower()
} finally {
$fileStream.Close()
$sha256.Dispose()
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

if ($actualChecksum -ne $expectedChecksum) {
Stop-WithError "Checksum mismatch!`n Expected: $expectedChecksum`n Got: $actualChecksum"
Expand Down
55 changes: 55 additions & 0 deletions scripts/test-hash-fallback.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Test script to verify .NET SHA256 fallback works correctly
# This ensures the fallback path produces valid SHA256 hashes even when Get-FileHash is unavailable

$testFile = "$env:TEMP\gentle-ai-hash-test.txt"
# Use fixed content for deterministic testing
$testContent = "Gentle AI SHA256 fallback test"

try {
# Create test file with UTF-8 encoding (no BOM)
[System.IO.File]::WriteAllText($testFile, $testContent, [System.Text.UTF8Encoding]::new($false))

# Calculate hash using .NET fallback (the path we're testing)
$sha256 = [System.Security.Cryptography.SHA256]::Create()
$fileStream = [System.IO.File]::OpenRead($testFile)
try {
$hashBytes = $sha256.ComputeHash($fileStream)
$fallbackHash = [System.BitConverter]::ToString($hashBytes).Replace("-", "").ToLower()
} finally {
$fileStream.Close()
$sha256.Dispose()
}

# Verify the hash is valid (64 hex characters for SHA256)
if ($fallbackHash -match '^[a-f0-9]{64}$') {
Write-Host "PASS: .NET fallback produces valid SHA256 hash" -ForegroundColor Green
Write-Host "Hash: $fallbackHash"

# If Get-FileHash is available, verify both methods match
if (Get-Command Get-FileHash -ErrorAction SilentlyContinue) {
$standardHash = (Get-FileHash -Path $testFile -Algorithm SHA256).Hash.ToLower()
if ($standardHash -eq $fallbackHash) {
Write-Host "PASS: .NET fallback matches Get-FileHash" -ForegroundColor Green
} else {
Write-Host "FAIL: Hash mismatch between Get-FileHash and .NET fallback" -ForegroundColor Red
Write-Host "Get-FileHash: $standardHash"
Write-Host ".NET fallback: $fallbackHash"
exit 1
}
} else {
Write-Host "INFO: Get-FileHash not available, skipping comparison test" -ForegroundColor Yellow
}

exit 0
} else {
Write-Host "FAIL: .NET fallback produced invalid hash format" -ForegroundColor Red
Write-Host "Got: $fallbackHash"
Write-Host "Expected: 64 hex characters"
exit 1
}
} finally {
# Cleanup
if (Test-Path $testFile) {
Remove-Item -Path $testFile -Force
}
}