The type or namespace name 'ICertificatePolicy' could not be found (Extracting Thumbprint for SHA256)

See original GitHub issue

FYI - I’m not sure if this is the best way to extract the SHA256 Thumbprint, but this has worked for me on Windows. If there is a better/recommended method that works on standard PowerShell for Windows as well PowerShell Core, I am definitely open to suggestion.

Steps to reproduce

Function Get-SSLThumbprint256 {
    param(
    [Parameter(
        Position=0,
        Mandatory=$true,
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true)
    ]
    [Alias('FullName')]
    [String]$URL
    )

add-type @"
        using System.Net;
        using System.Security.Cryptography.X509Certificates;
            public class IDontCarePolicy : ICertificatePolicy {
            public IDontCarePolicy() {}
            public bool CheckValidationResult(
                ServicePoint sPoint, X509Certificate cert,
                WebRequest wRequest, int certProb) {
                return true;
            }
        }
"@
    [System.Net.ServicePointManager]::CertificatePolicy = new-object IDontCarePolicy

    # Need to connect using simple GET operation for this to work
    Invoke-RestMethod -Uri $URL -Method Get | Out-Null

    $ENDPOINT_REQUEST = [System.Net.Webrequest]::Create("$URL")
    $CERT = $ENDPOINT_REQUEST.ServicePoint.Certificate
    # https://stackoverflow.com/a/22251597
    $BYTES = $cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert)
    Set-content -value $BYTES -encoding byte -path $ENV:TMP\cert-temp
    $SSL_THUMBPRINT = (Get-FileHash -Path $ENV:TMP\cert-temp -Algorithm SHA256).Hash
    return $SSL_THUMBPRINT -replace '(..(?!$))','$1:'
}

Expected behavior

The ability to extract the SHA256 SSL Thumbprint from a given endpoint. An example is provided below which works on standard Windows PowerShell 5.1 (5.1.17134.112 )

Get-SSLThumbprint256 -URL "https://google.com:443"
B9:B0:D3:46:36:83:13:6F:9E:32:80:61:0C:EC:0D:D2:1F:65:BE:3C:2F:81:92:CF:7B:C8:90:F1:71:2A:1C:F5

Actual behavior

When performing this on latest PowerShell Core, the following error is thrown:

Get-SSLThumbprint256 -URL "https://google.com:443"
add-type : (3) : The type or namespace name 'ICertificatePolicy' could not be found (are you missing a using directive or an assembly reference?)
(2) :         using System.Security.Cryptography.X509Certificates;
(3) : >>>             public class IDontCarePolicy : ICertificatePolicy {
(4) :             public IDontCarePolicy() {}
At line:13 char:1
+ add-type @"
+ ~~~~~~~~~~~
+ CategoryInfo          : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Exception
+ FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

add-type : Cannot add type. Compilation errors occurred.
At line:13 char:1
+ add-type @"
+ ~~~~~~~~~~~
+ CategoryInfo          : InvalidData: (:) [Add-Type], InvalidOperationException
+ FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.AddTypeCommand

new-object : Cannot find type [IDontCarePolicy]: verify that the assembly containing this type is loaded.
At line:25 char:59
+ ... .ServicePointManager]::CertificatePolicy = new-object IDontCarePolicy
+                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

You cannot call a method on a null-valued expression.
At line:33 char:5
+     $BYTES = $cert.Export([Security.Cryptography.X509Certificates.X50 ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Set-Content : Cannot bind parameter 'Encoding'. Cannot convert the "byte" value of type "System.String" to type "System.Text.Encoding".
At line:34 char:41
+     Set-content -value $BYTES -encoding byte -path /tmp/cert-temp
+                                         ~~~~
+ CategoryInfo          : InvalidArgument: (:) [Set-Content], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.SetContentCommand

Get-FileHash : Cannot find path '/tmp/cert-temp' because it does not exist.
At line:35 char:24
+ ... UMBPRINT = (Get-FileHash -Path /tmp/cert-temp -Algorithm SHA256).Hash ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (/tmp/cert-temp:String) [Get-FileHash], ItemNotFoundException
+ FullyQualifiedErrorId : FileNotFound,Microsoft.PowerShell.Commands.GetFileHashCommand

Environment data

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      6.0.2
PSEdition                      Core
GitCommitId                    v6.0.2
OS                             Darwin 17.6.0 Darwin Kernel Version 17.6.0: Tue May  8 15:22:16 PDT 2018; root:xnu-4570.61.1~1/RELEASE_X86_64
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
markekrauscommented, Jun 18, 2018

ICertificatePolicy and CertificatePolicy are absolute. You can see the warning here https://docs.microsoft.com/en-us/dotnet/api/system.net.servicepointmanager.certificatepolicy?view=netframework-4.7.2 That API is no longer included in .NET Core.

Instead us the ServerCertificateValidationCallback API https://docs.microsoft.com/en-us/dotnet/api/system.net.servicepointmanager.servercertificatevalidationcallback?view=netcore-2.1#System_Net_ServicePointManager_ServerCertificateValidationCallback .

Here is quick and dirty way to do this that works in both Windows PowerShell and PowerShell Core.

$Code = @'
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace CertificateCapture
{
    public class Utility
    {
         public static Func<HttpRequestMessage,X509Certificate2,X509Chain,SslPolicyErrors,Boolean> ValidationCallback = 
            (message, cert, chain, errors) => {
                var newCert = new X509Certificate2(cert);
                var newChain = new X509Chain();
                newChain.Build(newCert);
                CapturedCertificates.Add(new CapturedCertificate(){
                    Certificate =  newCert,
                    CertificateChain = newChain,
                    PolicyErrors = errors,
                    URI = message.RequestUri
                });
                return true; 
            };
        public static List<CapturedCertificate> CapturedCertificates = new List<CapturedCertificate>();
    }

    public class CapturedCertificate 
    {
        public X509Certificate2 Certificate { get; set; }
        public X509Chain CertificateChain { get; set; }
        public SslPolicyErrors PolicyErrors { get; set; }
        public Uri URI { get; set; }
    }
}
'@

if ($PSEdition -ne 'Core'){
    Add-Type -AssemblyName System.Net.Http
    Add-Type $Code -ReferencedAssemblies System.Net.Http
} else {
    Add-Type $Code
}

$Certs = [CertificateCapture.Utility]::CapturedCertificates

$Handler = [System.Net.Http.HttpClientHandler]::new()
$Handler.ServerCertificateCustomValidationCallback = [CertificateCapture.Utility]::ValidationCallback
$Client = [System.Net.Http.HttpClient]::new($Handler)

$Url = 'https://google.com/'

$Result = $Client.GetAsync($Url).Result

$Certs[-1].Certificate.Thumbprint
1reaction
rmbolgercommented, Jun 18, 2018

Lol, I knew @markekraus would be all over this. You are awesome.

@lamw, here’s some additional code to get the SHA256 thumbprint without needing the output file step and given the $Certs output from Mark’s example.

$sha256 = [Security.Cryptography.SHA256]::Create()
$certBytes = $Certs[-1].Certificate.GetRawCertData()
$hash = $sha256.ComputeHash($certBytes)
$thumbprint = [BitConverter]::ToString($hash).Replace('-',':')
Read more comments on GitHub >

github_iconTop Results From Across the Web

William Lam (@lamw.bsky.social
The type or namespace name 'ICertificatePolicy' could not be found (Extracting Thumbprint for... FYI - I'm not sure if this is the best...
Read more >
Powershell - error CS0246: The type or namespace name ' ...
Was able to resolve the issue and found 2 solutions to my problem. Changed the gitlab-runner pointing from pwsh to powershell which will...
Read more >
The type or namespace name 'ICertificatePolicy' could not ...
Hi, I receive the following when using that code. I am using visual studio code and powershell 7.2.3. error message: Add-Type: (5,36): error ......
Read more >
Retrieving SHA256 thumbprint (fingerprint) for SAML SSO ...
Note: The thumbprint is used to identify the certificate and it is not related to the signing algorithm. I've reached out to our...
Read more >
PowerValidatedSolutions.psm1 1.3.0
Write -Warning "Removing Identity Source from vCenter Server ($($vcfVcenterDetails.fqdn)) named ($domain), does not exist: SKIPPED" }
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found