Certificate Request Toolkit
<# .SYNOPSIS Certificate Request Toolkit .DESCRIPTION This script provides a comprehensive set of tools for creating, managing, and analyzing certificate requests (CSRs) and certificates. It includes features for generating CSRs, analyzing existing CSRs and certificates, and performing related tasks. .NOTES File Name : CertRequestToolkit.ps1 Author : [Your Name] Prerequisite : PowerShell V5.1 or later, OpenSSL (optional for some features) Version : 1.0 Date : [Current Date] .EXAMPLE .\CertRequestToolkit.ps1 #> # Check if OpenSSL is available $openSSLAvailable = $null -ne (Get-Command openssl -ErrorAction SilentlyContinue) function Show-Menu { Clear-Host Write-Host "=== Certificate Request Toolkit ===" -ForegroundColor Cyan Write-Host "1. Generate CSR" Write-Host "2. Analyze CSR" Write-Host "3. Analyze Certificate" Write-Host "4. Generate Self-Signed Certificate" Write-Host "5. Convert Certificate Format" Write-Host "6. Check Certificate Expiration" Write-Host "7. Verify Certificate Chain" Write-Host "8. Extract Public Key from Certificate" Write-Host "9. Exit" } function Generate-CSR { $subject = Read-Host "Enter the subject (e.g., CN=example.com,O=MyOrg,C=US)" $keySize = Read-Host "Enter key size (2048 or 4096, default is 2048)" if ([string]::IsNullOrWhiteSpace($keySize)) { $keySize = 2048 } $sanNames = @() do { $san = Read-Host "Enter Subject Alternative Name (or press Enter to finish)" if (-not [string]::IsNullOrWhiteSpace($san)) { $sanNames += $san } } while (-not [string]::IsNullOrWhiteSpace($san)) $outputPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\certificate_request.csr" if ($openSSLAvailable) { $configPath = Join-Path -Path $env:TEMP -ChildPath "openssl_config.cnf" $config = @" [req] distinguished_name = req_distinguished_name req_extensions = v3_req prompt = no [req_distinguished_name] $subject [v3_req] keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth subjectAltName = @alt_names [alt_names] "@ for ($i = 0; $i -lt $sanNames.Count; $i++) { $config += "DNS.$($i+1) = $($sanNames[$i])`n" } $config | Out-File -FilePath $configPath -Encoding ASCII $keyPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\private_key.pem" & openssl req -new -newkey rsa:$keySize -nodes -keyout $keyPath -out $outputPath -config $configPath Remove-Item -Path $configPath Write-Host "CSR generated and saved to: $outputPath" -ForegroundColor Green Write-Host "Private key saved to: $keyPath" -ForegroundColor Green } else { Write-Host "OpenSSL is not available. Using .NET to generate CSR (limited functionality)." -ForegroundColor Yellow $rsa = [System.Security.Cryptography.RSA]::Create($keySize) $req = New-Object -TypeName System.Security.Cryptography.X509Certificates.CertificateRequest( $subject, $rsa, [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) foreach ($san in $sanNames) { $req.CertificateExtensions.Add( [System.Security.Cryptography.X509Certificates.X509SubjectAlternativeNameExtension]::new( $san, $false)) } $csr = $req.CreateSigningRequest() [System.IO.File]::WriteAllBytes($outputPath, $csr) Write-Host "CSR generated and saved to: $outputPath" -ForegroundColor Green Write-Host "Note: Private key is not saved separately when using .NET method." -ForegroundColor Yellow } } function Analyze-CSR { $csrPath = Read-Host "Enter the path to the CSR file" if (-not (Test-Path $csrPath)) { Write-Host "CSR file not found." -ForegroundColor Red return } if ($openSSLAvailable) { Write-Host "`nCSR Analysis:" -ForegroundColor Yellow & openssl req -in $csrPath -noout -text } else { Write-Host "OpenSSL is not available. Limited analysis will be performed." -ForegroundColor Yellow $csrContent = Get-Content $csrPath -Raw $csrBytes = [System.Convert]::FromBase64String(($csrContent -replace "-----BEGIN CERTIFICATE REQUEST-----", "" -replace "-----END CERTIFICATE REQUEST-----", "").Trim()) $csr = New-Object System.Security.Cryptography.X509Certificates.X509CertificateRequest(,$csrBytes) Write-Host "`nCSR Subject: $($csr.Subject)" -ForegroundColor Yellow Write-Host "Public Key Algorithm: $($csr.PublicKey.Oid.FriendlyName)" -ForegroundColor Yellow Write-Host "Public Key Size: $($csr.PublicKey.Key.KeySize) bits" -ForegroundColor Yellow } } function Analyze-Certificate { $certPath = Read-Host "Enter the path to the certificate file" if (-not (Test-Path $certPath)) { Write-Host "Certificate file not found." -ForegroundColor Red return } if ($openSSLAvailable) { Write-Host "`nCertificate Analysis:" -ForegroundColor Yellow & openssl x509 -in $certPath -noout -text } else { Write-Host "OpenSSL is not available. Limited analysis will be performed." -ForegroundColor Yellow $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath) Write-Host "`nCertificate Subject: $($cert.Subject)" -ForegroundColor Yellow Write-Host "Issuer: $($cert.Issuer)" -ForegroundColor Yellow Write-Host "Valid From: $($cert.NotBefore)" -ForegroundColor Yellow Write-Host "Valid To: $($cert.NotAfter)" -ForegroundColor Yellow Write-Host "Serial Number: $($cert.SerialNumber)" -ForegroundColor Yellow Write-Host "Thumbprint: $($cert.Thumbprint)" -ForegroundColor Yellow } } function Generate-SelfSignedCertificate { $subject = Read-Host "Enter the subject (e.g., CN=example.com)" $validityDays = Read-Host "Enter validity period in days (default is 365)" if ([string]::IsNullOrWhiteSpace($validityDays)) { $validityDays = 365 } $outputPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\self_signed_certificate.pfx" $password = Read-Host "Enter a password for the PFX file" -AsSecureString $cert = New-SelfSignedCertificate -Subject $subject -CertStoreLocation Cert:\CurrentUser\My ` -KeyExportPolicy Exportable -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA ` -HashAlgorithm SHA256 -NotAfter (Get-Date).AddDays($validityDays) Export-PfxCertificate -Cert $cert -FilePath $outputPath -Password $password Remove-Item $cert.PSPath Write-Host "Self-signed certificate generated and saved to: $outputPath" -ForegroundColor Green } function Convert-CertificateFormat { if (-not $openSSLAvailable) { Write-Host "This feature requires OpenSSL, which is not available." -ForegroundColor Red return } $inputPath = Read-Host "Enter the path to the input certificate file" if (-not (Test-Path $inputPath)) { Write-Host "Input file not found." -ForegroundColor Red return } $outputFormat = Read-Host "Enter the desired output format (PEM, DER, P12)" $outputPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\converted_certificate.$($outputFormat.ToLower())" switch ($outputFormat.ToUpper()) { "PEM" { & openssl x509 -in $inputPath -outform PEM -out $outputPath } "DER" { & openssl x509 -in $inputPath -outform DER -out $outputPath } "P12" { $password = Read-Host "Enter a password for the P12 file" -AsSecureString $plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) & openssl pkcs12 -export -in $inputPath -out $outputPath -password pass:$plainPassword } default { Write-Host "Unsupported output format." -ForegroundColor Red; return } } Write-Host "Certificate converted and saved to: $outputPath" -ForegroundColor Green } function Check-CertificateExpiration { $certPath = Read-Host "Enter the path to the certificate file" if (-not (Test-Path $certPath)) { Write-Host "Certificate file not found." -ForegroundColor Red return } $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath) $daysUntilExpiration = ($cert.NotAfter - (Get-Date)).Days Write-Host "`nCertificate Expiration Information:" -ForegroundColor Yellow Write-Host "Subject: $($cert.Subject)" Write-Host "Expiration Date: $($cert.NotAfter)" Write-Host "Days Until Expiration: $daysUntilExpiration" if ($daysUntilExpiration -le 30) { Write-Host "Warning: Certificate will expire soon!" -ForegroundColor Red } } function Verify-CertificateChain { $certPath = Read-Host "Enter the path to the certificate file" if (-not (Test-Path $certPath)) { Write-Host "Certificate file not found." -ForegroundColor Red return } $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath) $chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain $chainBuilt = $chain.Build($cert) Write-Host "`nCertificate Chain Verification:" -ForegroundColor Yellow if ($chainBuilt) { Write-Host "Certificate chain is valid." -ForegroundColor Green Write-Host "`nCertificate Chain:" foreach ($element in $chain.ChainElements) { Write-Host " Subject: $($element.Certificate.Subject)" Write-Host " Issuer: $($element.Certificate.Issuer)" Write-Host " Valid From: $($element.Certificate.NotBefore)" Write-Host " Valid To: $($element.Certificate.NotAfter)" Write-Host "" } } else { Write-Host "Certificate chain is not valid." -ForegroundColor Red Write-Host "`nChain Status:" foreach ($status in $chain.ChainStatus) { Write-Host " $($status.StatusInformation)" } } } function Extract-PublicKey { if (-not $openSSLAvailable) { Write-Host "This feature requires OpenSSL, which is not available." -ForegroundColor Red return } $certPath = Read-Host "Enter the path to the certificate file" if (-not (Test-Path $certPath)) { Write-Host "Certificate file not found." -ForegroundColor Red return } $outputPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\public_key.pem" & openssl x509 -in $certPath -pubkey -noout > $outputPath Write-Host "Public key extracted and saved to: $outputPath" -ForegroundColor Green } # Main program loop do { Show-Menu $choice = Read-Host "`nEnter your choice (1-9)" switch ($choice) { "1" { Generate-CSR } "2" { Analyze-CSR } "3" { Analyze-Certificate } "4" { Generate-SelfSignedCertificate } "5" { Convert-CertificateFormat } "6" { Check-CertificateExpiration } "7" { Verify-CertificateChain } "8" { Extract-PublicKey } "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break } default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red } } if ($choice -ne "9") { Read-Host "`nPress Enter to continue..." } } while ($choice -ne "9")
This Certificate Request Toolkit includes:
- A menu-driven interface for easy navigation.
- Functions for various certificate-related tasks:
- Generating Certificate Signing Requests (CSRs)
- Analyzing CSRs
- Analyzing certificates
- Generating self-signed certificates
- Converting certificate formats
- Checking certificate expiration
- Verifying certificate chains
- Extracting public keys from certificates
- Support for both OpenSSL (when available) and .NET methods for certain operations.
- Comprehensive error handling and user guidance.
Key features:
- CSR generation with customizable subject, key size, and Subject Alternative Names (SANs)
- Detailed analysis of CSRs and certificates
- Self-signed certificate generation for testing purposes
- Certificate format conversion (requires OpenSSL)
- Certificate expiration checking
- Certificate chain verification
- Public key extraction from certificates (requires OpenSSL)
- Fallback to .NET methods when OpenSSL is not available for some features
This tool is particularly useful for:
- System administrators managing SSL/TLS certificates
- Security professionals working with digital certificates
- Developers needing to generate CSRs or analyze certificates
- IT professionals troubleshooting certificate-related issues
To use this script effectively:
- Run the script in PowerShell
- Ensure OpenSSL is installed and available in the system PATH for full functionality
- Use the menu to navigate between different certificate-related tasks
- Follow the prompts to provide necessary information for each operation
This comprehensive toolkit provides a wide range of certificate management and analysis capabilities, making it a valuable resource for anyone working with digital certificates in a Windows environment.