c-hive.psm1
|
function Test-IsNumeric { <# .SYNOPSIS Returns if a specific value is numeric or not .EXAMPLE Test-IsNumeric -Value "1" # Returns $true Test-IsNumeric -Value "a" # Returns $false #> param( [Parameter(Mandatory = $true)] [string]$Value ) Write-Verbose "Executing: Test-IsNumeric" return $Value.Trim() -match '^-?\d+$' } function Get-IsValidCsr{ param($base64Csr) $pemHeader = "-----BEGIN CERTIFICATE REQUEST-----`n" $pemFooter = "`n-----END CERTIFICATE REQUEST-----" # Insert line breaks every 64 chars (optional but recommended) $wrappedCsr = ($base64Csr -split '(.{64})' | Where-Object {$_ -ne ''}) -join "`n" $pem = $pemHeader + $wrappedCsr + $pemFooter $stringReader = New-Object Org.BouncyCastle.Utilities.IO.Pem.PemReader([System.IO.StringReader]::new($pem)) try { $csr = $stringReader.ReadPemObject() if ($csr.Type -eq "CERTIFICATE REQUEST") { return $true } else { return $false } } catch { return $false } } function Convert-CSR2Object{ param($CSR) add-type -path ".\BouncyCastle.Cryptography.dll" $base64 = ($CSR -replace "-----.*-----", "") -replace "\s", "" $bytes = [Convert]::FromBase64String($base64) return [Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest]::new($bytes) } function Get-Subject{ param($csr_object) $subject = $csr_object.GetCertificationRequestInfo().Subject $oids = $subject.GetOidList() $values = $subject.GetValueList() # Initialize empty hashtable $subjectHash = @{} for ($i = 0; $i -lt $oids.Count; $i++) { $oid = $oids[$i].Id $value = $values[$i].ToString() switch ($oid) { "2.5.4.3" { $subjectHash["CommonName"] = $value } "2.5.4.10" { $subjectHash["Organization"] = $value } "2.5.4.11" { $subjectHash["OrganizationalUnit"] = $value } "2.5.4.6" { $subjectHash["Country"] = $value } "2.5.4.7" { $subjectHash["Locality"] = $value } "2.5.4.8" { $subjectHash["StateOrProvince"] = $value } "2.5.4.9" { $subjectHash["StreetAddress"] = $value } "1.2.840.113549.1.9.1" { $subjectHash["EmailAddress"] = $value } "0.9.2342.19200300.100.1.25" { $subjectHash["DomainComponent"] = $value } "0.9.2342.19200300.100.1.1" { $subjectHash["UserID"] = $value } "2.5.4.12" { $subjectHash["Title"] = $value } "2.5.4.15" { $subjectHash["BusinessCategory"] = $value } "2.5.4.17" { $subjectHash["PostalCode"] = $value } "2.5.4.5" { $subjectHash["SerialNumber"] = $value } "2.5.4.44" { $subjectHash["GenerationQualifier"] = $value } "2.5.4.42" { $subjectHash["GivenName"] = $value } "2.5.4.4" { $subjectHash["Surname"] = $value } "2.5.4.43" { $subjectHash["Initials"] = $value } "2.5.4.65" { $subjectHash["Pseudonym"] = $value } "1.2.840.113549.1.9.2" { $subjectHash["UnstructuredName"] = $value } default { $subjectHash["OID_$oid"] = $value } } } # Create a clean output object $subjectObject = [pscustomobject]$subjectHash return $subjectObject } function Get-SAN{ param($csr_object) $extRequestOidString = "1.2.840.113549.1.9.14" $csr_object_attributes = $csr_object.GetCertificationRequestInfo().Attributes $sanEntries = @() foreach ($attr in $csr_object_attributes) { $oid = $attr[0] # DerObjectIdentifier if ($oid.Id -eq $extRequestOidString) { $values = $attr[1] # DerSet $extAsn1 = $values[0] # Extensions ASN.1 object $extensions = [Org.BouncyCastle.Asn1.X509.X509Extensions]::GetInstance($extAsn1) $sanOid = [Org.BouncyCastle.Asn1.X509.X509Extensions]::SubjectAlternativeName $sanExtension = $extensions.GetExtension($sanOid) if ($sanExtension -ne $null) { $generalNames = [Org.BouncyCastle.Asn1.X509.GeneralNames]::GetInstance($sanExtension.GetParsedValue()) foreach ($generalName in $generalNames.GetNames()) { $entry = [PSCustomObject]@{ TagNo = $generalName.TagNo Type = "" Value = $null } switch ($generalName.TagNo) { 1 { # Email (RFC822Name) $entry.Type = "Email" $entry.Value = [string]$generalName.Name } 2 { # DNS Name $entry.Type = "DNS" $entry.Value = [string]$generalName.Name } 3 { # X400Address $entry.Type = "X400Address" $entry.Value = [string]$generalName.Name } 4 { # DirectoryName $entry.Type = "DirectoryName" $entry.Value = [string]$generalName.Name } 5 { # EdiPartyName $entry.Type = "EdiPartyName" $entry.Value = [string]$generalName.Name } 6 { # UniformResourceIdentifier $entry.Type = "URI" $entry.Value = [string]$generalName.Name } 7 { # IP Address $entry.Type = "IPAddress" $ipBytes = $generalName.Name.GetOctets() $entry.Value = [System.Net.IPAddress]::new($ipBytes).ToString() } 8 { # RegisteredID $entry.Type = "RegisteredID" $entry.Value = [string]$generalName.Name } default { $entry.Type = "Other" $entry.Value = [string]$generalName.Name } } $sanEntries += $entry } } } } return $sanEntries } function Get-Key{ param($csr_object) if ($Null -ne $csr_object.GetPublicKey().modulus) { #RSA $key = [PSCustomObject]@{ Type = "RSA" Len = $csr_object.GetPublicKey().modulus.bitlength } } else { #EC $key = [PSCustomObject]@{ Type = "EC" Len = $csr_object.GetPublicKey().parameters.curve.fieldSize } } return $key } function Get-KeyUsage{ param($csr_object) $extRequestOidString = "1.2.840.113549.1.9.14" $csrAttributes = $csr_object.GetCertificationRequestInfo().Attributes $keyUsageResult = @() foreach ($attr in $csrAttributes) { $oid = $attr[0] # DerObjectIdentifier if ($oid.Id -eq $extRequestOidString) { $values = $attr[1] # DerSet $extAsn1 = $values[0] # ASN.1 encoded extensions $extensions = [Org.BouncyCastle.Asn1.X509.X509Extensions]::GetInstance($extAsn1) $keyUsageOid = [Org.BouncyCastle.Asn1.X509.X509Extensions]::KeyUsage $keyUsageExt = $extensions.GetExtension($keyUsageOid) if ($keyUsageExt -ne $null) { $keyUsage = [Org.BouncyCastle.Asn1.X509.KeyUsage]::GetInstance($keyUsageExt.GetParsedValue()) $flags = $keyUsage.IntValue if ($flags -band [Org.BouncyCastle.Asn1.X509.KeyUsage]::DigitalSignature) { $keyUsageResult += "DigitalSignature" } if ($flags -band [Org.BouncyCastle.Asn1.X509.KeyUsage]::NonRepudiation) { $keyUsageResult += "NonRepudiation" } if ($flags -band [Org.BouncyCastle.Asn1.X509.KeyUsage]::KeyEncipherment) { $keyUsageResult += "KeyEncipherment" } if ($flags -band [Org.BouncyCastle.Asn1.X509.KeyUsage]::DataEncipherment) { $keyUsageResult += "DataEncipherment" } if ($flags -band [Org.BouncyCastle.Asn1.X509.KeyUsage]::KeyAgreement) { $keyUsageResult += "KeyAgreement" } if ($flags -band [Org.BouncyCastle.Asn1.X509.KeyUsage]::KeyCertSign) { $keyUsageResult += "KeyCertSign" } if ($flags -band [Org.BouncyCastle.Asn1.X509.KeyUsage]::CrlSign) { $keyUsageResult += "CrlSign" } if ($flags -band [Org.BouncyCastle.Asn1.X509.KeyUsage]::EncipherOnly) { $keyUsageResult += "EncipherOnly" } if ($flags -band [Org.BouncyCastle.Asn1.X509.KeyUsage]::DecipherOnly) { $keyUsageResult += "DecipherOnly" } } } } return $keyUsageResult } function Get-EnhancedKeyUsage{ param ($csr_object) $ekuList = @() $extRequestOidString = "1.2.840.113549.1.9.14" $csrAttributes = $csr_object.GetCertificationRequestInfo().Attributes foreach ($attr in $csrAttributes) { $oid = $attr[0] if ($oid.Id -eq $extRequestOidString) { $values = $attr[1] $extAsn1 = $values[0] $extensions = [Org.BouncyCastle.Asn1.X509.X509Extensions]::GetInstance($extAsn1) $ekuOid = [Org.BouncyCastle.Asn1.X509.X509Extensions]::ExtendedKeyUsage $ekuExtension = $extensions.GetExtension($ekuOid) if ($ekuExtension -ne $null) { $eku = [Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage]::GetInstance($ekuExtension.GetParsedValue()) foreach ($keyPurposeId in $eku.GetAllUsages()) { $oidString = $keyPurposeId.Id $friendlyName = switch ($oidString) { "1.3.6.1.5.5.7.3.1" { "Server Authentication" } "1.3.6.1.5.5.7.3.2" { "Client Authentication" } "1.3.6.1.5.5.7.3.3" { "Code Signing" } "1.3.6.1.5.5.7.3.4" { "Email Protection" } "1.3.6.1.5.5.7.3.8" { "Time Stamping" } "1.3.6.1.5.5.7.3.9" { "OCSP Signing" } "1.3.6.1.4.1.311.10.3.4" { "Encrypting File System" } default { "Unknown EKU: $oidString" } } $ekuList += $friendlyName } } } } return $ekuList } function Get-CryptographicServiceProvider{ param($csr_object) $cspList = @() $attributes = $csr_object.GetCertificationRequestInfo().Attributes $msCspOid = "1.3.6.1.4.1.311.13.2.2" foreach ($attr in $attributes) { $oid = $attr.AttrType if ($oid.Id -eq $msCspOid) { $attrValues = $attr.AttrValues foreach ($val in $attrValues) { $asn1Str = [Org.BouncyCastle.Asn1.DerUtf8String]::GetInstance($val) if ($asn1Str.GetString() -match "Provider\s*=") { $provider = $asn1Str.GetString().Split("=")[1].Trim() $cspList += $provider } } } } return $csrList } function Get-CertExtensions{ param ($csr_object) $extensionsList = @() $attrs = $csr_object.GetCertificationRequestInfo().Attributes $extRequestOid = "1.2.840.113549.1.9.14" # PKCS #9 extensionRequest OID foreach ($attr in $attrs) { if ($attr.AttrType.Id -eq $extRequestOid) { $attrValues = $attr.AttrValues foreach ($val in $attrValues) { # Get X509Extensions object from ASN1 $exts = [Org.BouncyCastle.Asn1.X509.X509Extensions]::GetInstance($val) # Extract all extensions from X509Extensions $oids = $exts.GetExtensionOids() foreach ($oid in $oids) { $extension = $exts.GetExtension($oid) $oidStr = $oid.Id try { $extName = [Org.BouncyCastle.Asn1.X509.X509ExtensionUtilities]::GetExtensionName($oid) } catch { $extName = "Unknown" } $obj = [PSCustomObject]@{ ExtensionOID = $oidStr ExtensionName = $extName ExtensionValue = $extension } $extensionsList += $obj } } } } return $extensionsList } function Test-CSR { param ( $csr ) $result = [PSCustomObject]@{ isValid = $false subject = @() san = @() key = @() keyusage = @() EnhancedKeyUsage = @() CryptographicServiceProvider = @() CertExtensions = @() csr = $csr } $result.isValid = Get-IsValidCsr -base64Csr $csr if ($result.isValid) { $csr_object = Convert-CSR2Object -CSR $csr $result.subject = get-subject $csr_object $result.san = get-san $csr_object $result.key = get-key -csr_object $csr_object $result.keyusage = get-keyusage -csr_object $csr_object $result.EnhancedKeyUsage = Get-EnhancedKeyUsage -csr_object $csr_object $result.CryptographicServiceProvider = Get-CryptographicServiceProvider -csr_object $csr_object $result.CertExtensions = Get-CertExtensions -csr_object $csr_object } return $result } Export-ModuleMember * # SIG # Begin signature block # MIIFfwYJKoZIhvcNAQcCoIIFcDCCBWwCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCMRJfjb5qTJ+r9 # 6Ox/pysQsUVHMW/rQoStt22oOWvLwqCCAvwwggL4MIIB4KADAgECAhARXeApLbab # i0U384S48TtIMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCHZpdmFYaXRlMCAX # DTI1MDUyNjA5NTEyN1oYDzIxMjQwNTI2MTAwMTI4WjATMREwDwYDVQQDDAh2aXZh # WGl0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL65W+H9E82gU7ZH # /XSJbAxPvFtzHVRoUHA045konf474KBkaDc4ztYlgRvkZldzFykjg8jeuSa0ANlm # VX1HoObUVYagSax/fWPSOkqDN4aTolX8GaI98ZOey9a9OYUI3F5mznkeksWUqbT7 # cgCX2Y/Qtnh557nSuplxmmtTGEzrDzj5evvnAyGGH1mcJxD3DeJGv3olsK9J982q # 0s+t9bCSSWPx2vapiR9VmCTKZJMi4YlNXrM+UFEd7R1KQR5M/KPY+rg5UJ0kU8Hz # q0z9z6L3mbk+b28uI9EwGbvuXPtqUCi5P9YrdpKjOR16kaBJ9Od1+mphUaxNfc75 # eb8Uzd0CAwEAAaNGMEQwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF # BwMDMB0GA1UdDgQWBBQjLXXsxxmYhIvcsrZywbsrsjn9ajANBgkqhkiG9w0BAQsF # AAOCAQEAtVY7rYwe8G/F+95Lc47UpZD1ICAg/sS/yRZjKhoos/iufKV478RsZyDX # dAj5unm7XqGZSAyW4hHOdWYQdF//emNpXyOmNSkPuwpebhKtAwddvUwlGzFbsh4g # 5ULVgmvnf2J3eqKQpOulecCH8MJqCrRAi8pgBjl5/cmr6ZMULLAswmEkCTNgvx7g # qVFvJ+Zcbxu2gOiA9EzTzMWM8thrkOGWYYu/i0b63BxKXAenkBKJtjugFb2iefGb # mhfcelCGo/Gx7XD7AdYM3ov5YTYpnTDmCCTch9dR8vz7FPgwV0HPYfIZ1b1INC4y # C6I3Hf8ZXMzquofQpd9zlu7qqnKF/DGCAdkwggHVAgEBMCcwEzERMA8GA1UEAwwI # dml2YVhpdGUCEBFd4CkttpuLRTfzhLjxO0gwDQYJYIZIAWUDBAIBBQCggYQwGAYK # KwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIB # BDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg # bYuesEJaFfRFK65YGHfVTq4o9t2VXAQsakcxH2YIQmEwDQYJKoZIhvcNAQEBBQAE # ggEAjeVyUwrT/dLkQ1QwdqJq/WP+D3nEs6wIrGlzCaHnzxr5EHcHfa4dhKlU7MGR # Mw9YJSmbUH7+lVKPPebEjDbnvwimDLNIvzwr0rVXdPeYh0IxpNGOSQtjl3RB4+Oi # w9ArpV8KKs0bKyy+fb9xiu8AKrlyyN/TNmBFjR7DZ47dtHQPFEgLt+HAJMsIi3H4 # iD01qcDOi8e5TQpfbInUCaulyzzWVAX/wQiSu+7ST42or4xt5ssvFXklwehvW3/p # DamNltCVDKe9703OvX6+HOt0ZkZ5P/8NHciXoz52H/P5Fpr7MFRBdVrJc+pNQVoE # UbUaRF0jEFyuUwdm+WcQ3IN7aA== # SIG # End signature block |