Get-CipherSuite.ps1

<#PSScriptInfo
.VERSION 1.0.0
.GUID 3f8b2a1c-7d4e-4f9a-b5c6-8e2d1a0f3b7c
.AUTHOR Petar Ivanov
.COMPANYNAME
.COPYRIGHT (c) 2025 Petar Ivanov. All rights reserved.
.TAGS TLS SSL Cipher Security Network Certificate HTTPS
.LICENSEURI
.PROJECTURI
.ICONURI
.EXTERNALMODULEDEPENDENCIES
.REQUIREDSCRIPTS
.EXTERNALSCRIPTDEPENDENCIES
.RELEASENOTES
    Initial release - Analyzes TLS/SSL cipher suites on remote endpoints.
.PRIVATEDATA
#>


<#
.SYNOPSIS
    TLS Cipher Suite Analyzer - Tests SSL/TLS cipher suites on remote endpoints.
 
.DESCRIPTION
    This script connects to specified endpoints and analyzes the negotiated TLS/SSL
    cipher suites. It reports the protocol version, cipher algorithm, hash algorithm,
    and key exchange details. It also validates if the cipher suite is in the approved list.
 
.PARAMETER Endpoints
    One or more hostnames or URLs to test.
 
.PARAMETER Port
    The port to connect to. Default is 443.
 
.PARAMETER TestAllVersions
    If specified, tests all TLS/SSL protocol versions (SSL3, TLS 1.0, 1.1, 1.2, 1.3).
 
.EXAMPLE
    .\Get-CipherSuite.ps1 -Endpoints "google.com"
     
.EXAMPLE
    .\Get-CipherSuite.ps1 -Endpoints "google.com","microsoft.com" -Port 443 -TestAllVersions
 
.NOTES
    Author: Petar Ivanov
    Date: November 27, 2025
    Version: 1.0.0
#>


param(
    [Parameter(Mandatory=$true, Position=0)]
    [string[]]$Endpoints,
    
    [Parameter(Mandatory=$false)]
    [int]$Port = 443,
    
    [Parameter(Mandatory=$false)]
    [switch]$TestAllVersions
)

function Get-EndpointCipherSuite {
    param(
        [string]$Endpoint,
        [int]$Port,
        [object]$SpecificProtocol = $null
    )
    
    $cleanEndpoint = $Endpoint -replace '^https?://', '' -replace '/$', ''
    
    if ($null -eq $SpecificProtocol) {
        Write-Host "`nTesting: $cleanEndpoint`:$Port (Default/Best Available)" -ForegroundColor Cyan
    }
    else {
        Write-Host "`nTesting: $cleanEndpoint`:$Port ($SpecificProtocol)" -ForegroundColor Cyan
    }
    Write-Host ("-" * 60)
    
    try {
        $tcpClient = New-Object System.Net.Sockets.TcpClient
        $tcpClient.Connect($cleanEndpoint, $Port)
        
        if ($null -eq $SpecificProtocol) {
            $sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream(), $false)
            $sslStream.AuthenticateAsClient($cleanEndpoint)
        }
        else {
            $sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream(), $false, 
                { param($sender, $certificate, $chain, $sslPolicyErrors) return $true })
            $sslStream.AuthenticateAsClient($cleanEndpoint, $null, $SpecificProtocol, $false)
        }
        
        $sslProtocol = $sslStream.SslProtocol
        $cipherAlgorithm = $sslStream.CipherAlgorithm
        $cipherStrength = $sslStream.CipherStrength
        $hashAlgorithm = $sslStream.HashAlgorithm
        $keyExchangeAlgorithm = $sslStream.KeyExchangeAlgorithm
        $keyExchangeStrength = $sslStream.KeyExchangeStrength
        
        # Map key exchange enum to readable name
        $keyExchangeName = switch ($keyExchangeAlgorithm) {
            ([System.Security.Authentication.ExchangeAlgorithmType]::None) { "None" }
            ([System.Security.Authentication.ExchangeAlgorithmType]::RsaSign) { "RSA" }
            ([System.Security.Authentication.ExchangeAlgorithmType]::RsaKeyX) { "RSA" }
            ([System.Security.Authentication.ExchangeAlgorithmType]::DiffieHellman) { "DH" }
            44550 { "ECDHE" }  # ECDH Ephemeral
            default { $keyExchangeAlgorithm.ToString() }
        }
        
        Write-Host "SSL/TLS Protocol: $sslProtocol" -ForegroundColor Green
        Write-Host "Cipher Algorithm: $cipherAlgorithm ($cipherStrength bits)" -ForegroundColor Green
        Write-Host "Hash Algorithm: $hashAlgorithm" -ForegroundColor Green
        Write-Host "Key Exchange: $keyExchangeName ($keyExchangeStrength bits)" -ForegroundColor Green
        
        # Check if this is an approved cipher suite based on the components
        $isAllowed = $false
        
        if ($sslProtocol -eq 'Tls13') {
            # TLS 1.3 - check based on cipher and hash
            if (($cipherAlgorithm -like "*Aes256*" -and $hashAlgorithm -eq "Sha384") -or
                ($cipherAlgorithm -like "*Aes128*" -and $hashAlgorithm -eq "Sha256")) {
                $isAllowed = $true
                $cipherSuiteName = if ($cipherAlgorithm -like "*Aes256*") { "TLS_AES_256_GCM_SHA384" } else { "TLS_AES_128_GCM_SHA256" }
            }
            else {
                $cipherSuiteName = "TLS_1.3 (${cipherAlgorithm}_${hashAlgorithm})"
            }
            Write-Host "Cipher Suite: $cipherSuiteName" -ForegroundColor $(if ($isAllowed) { "Green" } else { "Yellow" })
        }
        else {
            # TLS 1.2 - check based on key exchange, cipher, and hash
            # Approved: ECDHE + (AES256 or AES128) + (SHA384 or SHA256)
            if ($keyExchangeName -eq "ECDHE") {
                if (($cipherAlgorithm -like "*Aes256*" -and $hashAlgorithm -eq "Sha384") -or
                    ($cipherAlgorithm -like "*Aes128*" -and $hashAlgorithm -eq "Sha256")) {
                    $isAllowed = $true
                }
            }
            
            # Construct standard cipher suite name
            if ($keyExchangeName -eq "ECDHE" -and $cipherAlgorithm -like "*Aes256*" -and $hashAlgorithm -eq "Sha384") {
                $cipherSuiteName = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
            }
            elseif ($keyExchangeName -eq "ECDHE" -and $cipherAlgorithm -like "*Aes128*" -and $hashAlgorithm -eq "Sha256") {
                $cipherSuiteName = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
            }
            else {
                $cipherSuiteName = "TLS_${keyExchangeName}_WITH_${cipherAlgorithm}_${hashAlgorithm}"
            }
            

            Write-Host "Cipher Suite (approx): $cipherSuiteName" -ForegroundColor $(if ($isAllowed) { "Green" } else { "Yellow" })
        }
        
        $sslStream.Close()
        $tcpClient.Close()
        
        Write-Host "Status: $(if ($isAllowed) { 'ENABLED [OK] (APPROVED)' } else { 'ENABLED [WARNING] (NON-APPROVED)' })" -ForegroundColor $(if ($isAllowed) { "Green" } else { "DarkYellow" })
        Write-Host "Cipher Suite Security: $(if ($isAllowed) { 'APPROVED [OK]' } else { 'NOT IN APPROVED LIST [X]' })" -ForegroundColor $(if ($isAllowed) { "Green" } else { "Red" })
        
        return @{Connected = $true; Approved = $isAllowed}
    }
    catch {
        Write-Host "Status: DISABLED [X]" -ForegroundColor Red
        return @{Connected = $false; Approved = $false}
    }
}

Write-Host "`n========================================" -ForegroundColor Magenta
Write-Host " TLS Cipher Suite Analyzer" -ForegroundColor Magenta
Write-Host "========================================" -ForegroundColor Magenta

foreach ($endpoint in $Endpoints) {
    if ($TestAllVersions) {
        Write-Host "`n$('=' * 60)" -ForegroundColor White
        Write-Host "ENDPOINT: $endpoint`:$Port - Testing All TLS Versions" -ForegroundColor White
        Write-Host "$('=' * 60)" -ForegroundColor White
        
        $protocols = @(
            @{Name = "SSL 3.0"; Value = [System.Security.Authentication.SslProtocols]::Ssl3},
            @{Name = "TLS 1.0"; Value = [System.Security.Authentication.SslProtocols]::Tls},
            @{Name = "TLS 1.1"; Value = [System.Security.Authentication.SslProtocols]::Tls11},
            @{Name = "TLS 1.2"; Value = [System.Security.Authentication.SslProtocols]::Tls12},
            @{Name = "TLS 1.3"; Value = [System.Security.Authentication.SslProtocols]::Tls13}
        )
        
        $results = @()
        foreach ($protocol in $protocols) {
            $result = Get-EndpointCipherSuite -Endpoint $endpoint -Port $Port -SpecificProtocol $protocol.Value
            
            $results += [PSCustomObject]@{
                Protocol = $protocol.Name
                Status = if ($result.Connected) { "ENABLED [OK]" } else { "DISABLED [X]" }
                Color = if ($result.Connected) { "Green" } else { "Red" }
            }
        }
        
        Write-Host "`n$('-' * 60)" -ForegroundColor White
        Write-Host "SUMMARY - Supported TLS Versions on $endpoint`:$Port" -ForegroundColor White
        Write-Host "$('-' * 60)" -ForegroundColor White
        foreach ($result in $results) {
            Write-Host "$($result.Protocol.PadRight(15)): " -NoNewline -ForegroundColor Yellow
            Write-Host $result.Status -ForegroundColor $result.Color
        }
    }
    else {
        Get-EndpointCipherSuite -Endpoint $endpoint -Port $Port
    }
}

Write-Host "`n========================================" -ForegroundColor Magenta
Write-Host "Testing Complete!" -ForegroundColor Magenta
Write-Host "========================================`n" -ForegroundColor Magenta