Files
windows-builder/includes/utils/oobe-certs/create-oobe-public-private-key.ps1
2026-06-02 03:37:09 -07:00

224 lines
8.7 KiB
PowerShell

# Requires running as Administrator for cryptographic operations
Add-Type -AssemblyName System.Security
function Write-ByteArrayToFile {
param(
[string]$Path,
[byte[]]$ByteArray
)
try {
[System.IO.File]::WriteAllBytes($Path, $ByteArray)
Write-Host "Successfully wrote $($ByteArray.Length) bytes to $Path" -ForegroundColor Green
return $true
}
catch {
Write-Error "Failed to write file $Path : $($_.Exception.Message)"
return $false
}
}
function Generate-OEMKeys {
param(
[string]$OutputPath = ".",
[string]$PublicKeyName = "pubkey.blob",
[string]$PrivateKeyName = "prvkey.blob",
[int]$KeySize = 2048
)
# Resolve the output path to absolute path
$ResolvedOutputPath = Resolve-Path $OutputPath -ErrorAction SilentlyContinue
if (-not $ResolvedOutputPath) {
$ResolvedOutputPath = New-Item -ItemType Directory -Path $OutputPath -Force | Select-Object -ExpandProperty FullName
} else {
$ResolvedOutputPath = $ResolvedOutputPath.Path
}
$PublicKeyPath = Join-Path $ResolvedOutputPath $PublicKeyName
$PrivateKeyPath = Join-Path $ResolvedOutputPath $PrivateKeyName
Write-Host "Generating OEM public/private key pair..." -ForegroundColor Cyan
Write-Host "Output Folder: $ResolvedOutputPath" -ForegroundColor Yellow
Write-Host "Key Size: $KeySize bits" -ForegroundColor Yellow
Write-Host "Provider: MS_ENH_RSA_AES_PROV" -ForegroundColor Yellow
Write-Host "Algorithm: RSA Key Exchange" -ForegroundColor Yellow
try {
# Create RSA crypto service provider with specified parameters
$cspParams = New-Object System.Security.Cryptography.CspParameters
$cspParams.ProviderType = 24 # PROV_RSA_AES
$cspParams.KeyContainerName = "OEMDecryptContainer"
$cspParams.KeyNumber = 1 # AT_KEYEXCHANGE
$cspParams.Flags = [System.Security.Cryptography.CspProviderFlags]::UseMachineKeyStore
# Create RSA provider with enhanced AES provider
$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider($KeySize, $cspParams)
Write-Host "RSA key generated successfully" -ForegroundColor Green
# Export public key blob (OOBE public key format)
Write-Host "`nExporting public key..." -ForegroundColor Cyan
$publicKeyBlob = $rsa.ExportCspBlob($false)
Write-Host "Public key blob size: $($publicKeyBlob.Length) bytes" -ForegroundColor Gray
# Export private key blob
Write-Host "Exporting private key..." -ForegroundColor Cyan
$privateKeyBlob = $rsa.ExportCspBlob($true)
Write-Host "Private key blob size: $($privateKeyBlob.Length) bytes" -ForegroundColor Gray
# Write keys to files
Write-Host "`nWriting keys to files..." -ForegroundColor Cyan
$publicResult = Write-ByteArrayToFile -Path $PublicKeyPath -ByteArray $publicKeyBlob
$privateResult = Write-ByteArrayToFile -Path $PrivateKeyPath -ByteArray $privateKeyBlob
if ($publicResult -and $privateResult) {
Write-Host "`nKey generation completed successfully!" -ForegroundColor Green
Write-Host "Public key saved to: $PublicKeyPath" -ForegroundColor White
Write-Host "Private key saved to: $PrivateKeyPath" -ForegroundColor White
# Display key information
Write-Host "`nKey Information:" -ForegroundColor Yellow
Write-Host "Key Size: $KeySize bits" -ForegroundColor Gray
Write-Host "Public Key Format: PUBLICKEYBLOB" -ForegroundColor Gray
Write-Host "Private Key Format: PRIVATEKEYBLOB" -ForegroundColor Gray
Write-Host "Compatible with: Windows OOBE Registration" -ForegroundColor Gray
return @{
PublicKeyPath = $PublicKeyPath
PrivateKeyPath = $PrivateKeyPath
OutputFolder = $ResolvedOutputPath
}
} else {
Write-Error "Failed to write one or more key files"
return $false
}
}
catch {
Write-Error "Key generation failed: $($_.Exception.Message)"
Write-Host "Ensure you are running PowerShell as Administrator" -ForegroundColor Red
return $false
}
finally {
# Clean up
if ($rsa) {
$rsa.Dispose()
}
}
}
function Get-KeyInformation {
param(
[string]$KeyPath
)
if (-not (Test-Path $KeyPath)) {
Write-Error "Key file not found: $KeyPath"
return
}
try {
$keyBlob = [System.IO.File]::ReadAllBytes($KeyPath)
Write-Host "Key File: $KeyPath" -ForegroundColor Cyan
Write-Host "File Size: $($keyBlob.Length) bytes" -ForegroundColor Gray
# Try to import and display basic info
$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider
$rsa.ImportCspBlob($keyBlob)
Write-Host "Key Size: $($rsa.KeySize) bits" -ForegroundColor Gray
Write-Host "Public Only: $($rsa.PublicOnly)" -ForegroundColor Gray
$rsa.Dispose()
}
catch {
Write-Warning "Could not parse key file (may be normal for blob format): $($_.Exception.Message)"
}
}
function Show-FolderContents {
param([string]$FolderPath)
Write-Host "`nFolder Contents:" -ForegroundColor Cyan
Write-Host "================" -ForegroundColor Cyan
$files = Get-ChildItem -Path $FolderPath
foreach ($file in $files) {
Write-Host " $($file.Name) ($([math]::Round($file.Length/1KB, 2)) KB)" -ForegroundColor White
}
}
function Find-GeneratedKeys {
param(
[string]$SearchRoot = ".",
[string]$PublicKeyName = "pubkey.blob",
[string]$PrivateKeyName = "prvkey.blob"
)
$searchPath = Resolve-Path $SearchRoot
Write-Host "Searching for generated key files in: $searchPath" -ForegroundColor Cyan
$foundPublic = Get-ChildItem -Path $searchPath -Filter $PublicKeyName -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
$foundPrivate = Get-ChildItem -Path $searchPath -Filter $PrivateKeyName -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if ($foundPublic -or $foundPrivate) {
Write-Host "`nFound key files:" -ForegroundColor Yellow
if ($foundPublic) {
Write-Host " Public Key: $($foundPublic.FullName)" -ForegroundColor Green
} else {
Write-Host " Public Key: Not found" -ForegroundColor Red
}
if ($foundPrivate) {
Write-Host " Private Key: $($foundPrivate.FullName)" -ForegroundColor Green
} else {
Write-Host " Private Key: Not found" -ForegroundColor Red
}
} else {
Write-Host "No key files found in search path" -ForegroundColor Red
}
return @{
PublicKey = $foundPublic
PrivateKey = $foundPrivate
}
}
# Main execution
Write-Host "Windows OOBE OEM Key Generator" -ForegroundColor Magenta
Write-Host "================================" -ForegroundColor Magenta
# Get the current directory for reference
$currentDir = Get-Location
Write-Host "Current directory: $currentDir" -ForegroundColor Gray
# Generate the keys in the current directory
$result = Generate-OEMKeys -OutputPath "."
if ($result) {
Write-Host "`nVerifying generated keys..." -ForegroundColor Cyan
Get-KeyInformation -KeyPath $result.PublicKeyPath
Get-KeyInformation -KeyPath $result.PrivateKeyPath
# Show what's in the folder
Show-FolderContents -FolderPath $result.OutputFolder
Write-Host "`nNext Steps:" -ForegroundColor Yellow
Write-Host "1. Use the public key file for OOBE registration: $($result.PublicKeyPath)" -ForegroundColor White
Write-Host "2. Place the public key file in %systemroot%\system32\Oobe\Info\" -ForegroundColor White
Write-Host "3. Configure your Oobe.xml with registration settings" -ForegroundColor White
Write-Host "4. Keep the private key file secure: $($result.PrivateKeyPath)" -ForegroundColor Red
Write-Host "`nAll files are located in: $($result.OutputFolder)" -ForegroundColor Green
} else {
Write-Host "Key generation failed. Please check the errors above." -ForegroundColor Red
}
# Search for the generated files to confirm their location
Write-Host "`nConfirming file locations..." -ForegroundColor Cyan
Find-GeneratedKeys -SearchRoot "."
# Copy public key to the OOBE Info directory
$oobeInfoPath = ".\..\..\`$OEM`$\`$`$\System32\Oobe\Info"
write-Host "`nCopying public key to OOBE Info directory: $oobeInfoPath" -ForegroundColor Cyan
copy-item -Path $result.PublicKeyPath -Destination $oobeInfoPath -Force
Write-Host "Public key copied successfully." -ForegroundColor Green