Skip to content

Instantly share code, notes, and snippets.

@javiercn
Last active November 8, 2023 13:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save javiercn/9f2657f88498ce1b0b8c99d326131b54 to your computer and use it in GitHub Desktop.
Save javiercn/9f2657f88498ce1b0b8c99d326131b54 to your computer and use it in GitHub Desktop.
dotnet-dev-certs diagnostics
Param(
[switch]$TryCreateCertificate
)
function Get-DevCertDiagnostics() {
$localHostCurrentUserPersonal = Get-ChildItem Cert:\CurrentUser\My -SSLServerAuthentication -DnsName localhost;
$localHostCurrentUserTrustedRoot = Get-ChildItem Cert:\CurrentUser\Root -SSLServerAuthentication -DnsName localhost;
$withOidCurrentUserPersonal = GetCertsWithOid(Get-ChildItem Cert:\CurrentUser\My);
$withOidCurrentUserTrustedRoot = GetCertsWithOid(Get-ChildItem Cert:\CurrentUser\Root);
$allData = [ordered]@{
LocalhostCertificatesOnPersonalStore = $localHostCurrentUserPersonal | %{ GetCertData($_) };
LocalhostCertificatesOnTrustedRoot = $localHostCurrentUserTrustedRoot | %{ GetCertData($_) };
CertificatesWithAspNetOidOnPersonalStore = $withOidCurrentUserPersonal | %{ GetCertData($_) };
CertificatesWithAspNetOidOnTrustedRoot = $withOidCurrentUserTrustedRoot | %{ GetCertData($_) };
}
PrintDiagnostics($allData);
# return $allData;
}
function PrintDiagnostics ($allData) {
Write-Output "Localhost certificates on the current user store:";
$allData.LocalhostCertificatesOnPersonalStore | Format-List;
Write-Output "Localhost certificates on the trust root for the current user:";
$allData.LocalhostCertificatesOnTrustedRoot | Format-List;
Write-Output "Certificates with the ASP.NET Core Oid on the current user store:";
$allData.CertificatesWithAspNetOidOnPersonalStore | Format-List;
Write-Output "Certificates with the ASP.NET Core Oid trust root for the current user:";
$allData.CertificatesWithAspNetOidOnTrustedRoot | Format-List;
Write-Output "Specific checks:";
$oidPersonalCount = ($allData.CertificatesWithAspNetOidOnPersonalStore | Measure-Object).Count;
Write-Output "Certificates with our OID on CurrentUser\My: $oidPersonalCount";
if ($oidPersonalCount -gt 1) {
Write-Output "There should be at most 1 certificate with the ASP.NET Core OID on CurrentUser\My. Manually remove one or all of them and run dotnet-dev-certs again";
}
$oidPersonalTrustedCount = ($allData.CertificatesWithAspNetOidOnTrustedRoot | Measure-Object).Count;
Write-Output "Certificates with our OID on CurrentUser\Root: $oidPersonalTrustedCount";
if ($oidPersonalTrustedCount -gt 1) {
Write-Output "There should be at most 1 certificate with the ASP.NET Core OID on CurrentUser\Root. Manually remove one or all of them and run dotnet-dev-certs again";
}
if (($oidPersonalCount -le 1) -and ($oidPersonalTrustedCount -le 1)) {
Write-Output "The number of certificates in the store looks correct. You could try running this script with -TryCreateCertificate to generate a certificate equivalent to the one 'dotnet dev-certs https' creates. Use this flag at your own risk";
}
}
function GetCertsWithOid ($certificates) {
$results = @();
foreach ($cert in $certificates) {
foreach ($ext in $cert.Extensions) {
if ($ext.Oid.Value -eq "1.3.6.1.4.1.311.84.1.1") {
$results+=$cert;
break;
}
}
}
return $results;
}
function GetCertData ($certificate) {
$data = [ordered]@{
Subject = $certificate.Subject;
DnsNameList = $certificate.DnsNameList;
Issuer = $certificate.Issuer;
NotBefore = $certificate.NotBefore;
NotAfter = $certificate.NotAfter;
Thumbprint = $certificate.Thumbprint;
HasPrivateKey = $certificate.HasPrivateKey;
}
for ($i = 0; $i -lt $certificate.Extensions.Count; $i++) {
$extension = $certificate.Extensions[$i];
$data["Extension-$i-Oid"] = $extension.Oid.Value;
$data["Extension-$i-FriendlyName"] = $extension.Oid.FriendlyName;
$data["Extension-$i-AspNetDevCertOid"] = $extension.Oid.Value -eq "1.3.6.1.4.1.311.84.1.1"
}
return New-Object pscustomobject -Property $data;
}
Get-DevCertDiagnostics
function TryCreateAspNetCoreCertUsingPowershell () {
$ekuOidCollection = [System.Security.Cryptography.OidCollection]::new();
$ekuOidCollection.Add([System.Security.Cryptography.Oid]::new("1.3.6.1.5.5.7.3.1","Server Authentication"));
$sanBuilder = [System.Security.Cryptography.X509Certificates.SubjectAlternativeNameBuilder]::new();
$sanBuilder.AddDnsName("localhost");
$certificateExtensions = @(
# Subject Alternative Name
$sanBuilder.Build($true),
# ASP.NET Core OID
[System.Security.Cryptography.X509Certificates.X509Extension]::new(
"1.3.6.1.4.1.311.84.1.1",
[System.Text.Encoding]::ASCII.GetBytes("ASP.NET Core HTTPS development certificate"),
$false),
# KeyUsage
[System.Security.Cryptography.X509Certificates.X509KeyUsageExtension]::new(
[System.Security.Cryptography.X509Certificates.X509KeyUsageFlags]::KeyEncipherment,
$true),
# Enhanced key usage
[System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension]::new(
$ekuOidCollection,
$true),
# Basic constraints
[System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension]::new($false,$false,0,$true))
$parameters = @{
Subject = "localhost";
KeyAlgorithm = "RSA";
KeyLength = 2048;
CertStoreLocation = "Cert:\CurrentUser\My";
KeyExportPolicy = "Exportable";
NotBefore = Get-Date;
NotAfter = (Get-Date).AddYears(1);
HashAlgorithm = "SHA256";
Extension = $certificateExtensions;
SuppressOid = @("2.5.29.14");
FriendlyName = "ASP.NET Core HTTPS development certificate"
}
New-SelfSignedCertificate @parameters
}
if($TryCreateCertificate){
TryCreateAspNetCoreCertUsingPowershell
}
# Trust the cert using powershel
# Put the cert into the $cert variable with Get-ChildItem Cert:\CurrentUser\My\<<Thumbprint>>
# Export-Certificate -Cert $cert -FilePath <<TempPath>> -Type CERT
# Import-Certificate <<TempPath>> -CertStoreLocation Cert:\CurrentUser\Root\
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment