Public/Import-GamAuthSecure.ps1

function Import-GamAuthSecure {
<#
.SYNOPSIS
    Decrypts AES-encrypted files back into individual GAM7 config and auth files.
.DESCRIPTION
    Decrypts encrypted GAM config files using AES-256 decryption with a provided key.
    Restores sensitive files from encrypted backups for use with GAM.
.EXAMPLE
    Import-GamAuthSecure -KeyFile ./gam-encryption.key
.OUTPUTS
    Decrypted files in the specified output directory (default: ./gam-restored)
#>

  [CmdletBinding()]
  param(
    [Parameter()]
    [string]$InputDir = (Join-Path (Get-Location) 'gam-secure-export'),

    [Parameter()]
    [string]$KeyFile = (Join-Path (Get-Location) 'gam-encryption.key'),

    [Parameter()]
    [string]$OutputDir = (Join-Path (Get-Location) 'gam-restored'),

    [Parameter()]
    [switch]$RestoreToGamDir,

    [Parameter()]
    [switch]$Force
  )

  $activity = 'Import-GamAuthSecure'

  if (-not (Test-Path $KeyFile)) {
    Write-Warning "Encryption key not found: $KeyFile"
    return
  }

  Write-Progress -Activity $activity -Status 'Loading encryption key...' -PercentComplete 10

  $keyBase64 = [System.IO.File]::ReadAllText($KeyFile).Trim()
  [byte[]]$key = [Convert]::FromBase64String($keyBase64)

  if ($key.Length -notin @(16, 24, 32)) {
    Write-Warning "Invalid key length: $($key.Length) bytes. Must be 16, 24, or 32."
    return
  }

  if ($RestoreToGamDir) {
    $OutputDir = $env:GAMCFGDIR
    if (-not $OutputDir) {
      $OutputDir = Join-Path $HOME '.gam'
    }
    Write-Warning "Restoring directly to GAM config directory: $OutputDir"
  }

  Write-Verbose "$activity : $InputDir -> $OutputDir"

  if (-not (Test-Path $InputDir)) {
    Write-Warning "Input directory not found: $InputDir"
    return
  }

  if (-not (Test-Path $OutputDir)) {
    New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
  }

  Write-Progress -Activity $activity -Status 'Decrypting files...' -PercentComplete 30

  $decryptFile = {
    param([string]$SourcePath, [string]$DestPath, [byte[]]$AesKey)
    $encryptedBytes = [System.IO.File]::ReadAllBytes($SourcePath)
    $rawBytes = Unprotect-GamData -CipherBytes $encryptedBytes -AesKey $AesKey
    [System.IO.File]::WriteAllBytes($DestPath, $rawBytes)
  }

  $restored = 0
  $encryptedFiles = Get-ChildItem -Path $InputDir -Filter '*.encrypted' -Recurse

  foreach ($ef in $encryptedFiles) {
    $relativePath = $ef.FullName.Substring($InputDir.TrimEnd([IO.Path]::DirectorySeparatorChar).Length + 1)
    $originalName = $relativePath -replace '\.encrypted$', ''
    $destPath = Join-Path $OutputDir $originalName

    $destDir = Split-Path $destPath -Parent
    if (-not (Test-Path $destDir)) {
      New-Item -ItemType Directory -Path $destDir -Force | Out-Null
    }

    if ((Test-Path $destPath) -and -not $Force) {
      Write-Warning "Skipping (exists): $destPath. Use -Force to overwrite."
      continue
    }

    & $decryptFile $ef.FullName $destPath $key
    $restored++
  }

  Write-Progress -Activity $activity -Completed

  [PSCustomObject]@{
    InputDir   = $InputDir
    OutputDir  = $OutputDir
    FilesCount = $restored
    Restored   = 'Yes'
  } | Format-List
}