証明書から有効期限を取得する
·
2分で読める
Available in:
日本語
·
English
·
Español
·
Français
·
Deutsch
·
Português
·
한국어
·
Русский
·
中文
·
العربية
·
हिन्दी
·
Polski
·
Türkçe
·
Bahasa Indonesia
·
Nederlands
弊社が使用しているドメインの証明書の現在のステータスを確認するのに役立つ Web アプリがいくつかあります。
1 日に 1 回実行され、確認する必要があるいくつかのドメインをチェックする Azure 関数を作成しました。これは、証明書の有効期限が 30 日未満の場合に電子メールを送信する、非常にシンプルなコンソール アプリケーションです。
関数がどのように動作するかのロジック自体は示されませんが、証明書の基本チェックを行う関数と取得するデータを示したいと思います。
関数
static async Task<X509Certificate2> CheckCertificateAsync(string urlPath)
{
var certificate = new X509Certificate2();
var httpClientHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (request, cert, chain, policyErrors) =>
{
certificate = new X509Certificate2(cert);
return true;
}
};
using HttpClient httpClient = new HttpClient(httpClientHandler);
await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, urlPath));
return certificate;
}
このメソッド CheckCertificateAsync は X509Certificate2 証明書を返します。これにより、有効期限の確認など、さまざまな操作が可能になります。
シリアル化された結果
これは certificate オブジェクトのシリアル化された値です。
{
"Archived":false,
"Extensions":[
{
"KeyUsages":160,
"Critical":true,
"Oid":{
"Value":"2.5.29.15",
"FriendlyName":"Key Usage"
},
"RawData":"AwIFoA=="
},
{
"EnhancedKeyUsages":[
{
"Value":"1.3.6.1.5.5.7.3.1",
"FriendlyName":"Server Authentication"
},
{
"Value":"1.3.6.1.5.5.7.3.2",
"FriendlyName":"Client Authentication"
}
],
"Critical":false,
"Oid":{
"Value":"2.5.29.37",
"FriendlyName":"Enhanced Key Usage"
},
"RawData":"MBQGCCsGAQUFBwMBBggrBgEFBQcDAg=="
},
{
"CertificateAuthority":false,
"HasPathLengthConstraint":false,
"PathLengthConstraint":0,
"Critical":true,
"Oid":{
"Value":"2.5.29.19",
"FriendlyName":"Basic Constraints"
},
"RawData":"MAA="
},
{
"SubjectKeyIdentifier":"634E1585565AA49402C21642A4A5979A38025797",
"Critical":false,
"Oid":{
"Value":"2.5.29.14",
"FriendlyName":"Subject Key Identifier"
},
"RawData":"BBRjThWFVlqklALCFkKkpZeaOAJXlw=="
},
{
"Critical":false,
"Oid":{
"Value":"2.5.29.35",
"FriendlyName":"Authority Key Identifier"
},
"RawData":"MBaAFBQusxe3WFbLrlAJQOYfr52LFMLG"
},
{
"Critical":false,
"Oid":{
"Value":"1.3.6.1.5.5.7.1.1",
"FriendlyName":"Authority Information Access"
},
"RawData":"MEcwIQYIKwYBBQUHMAGGFWh0dHA6Ly9yMy5vLmxlbmNyLm9yZzAiBggrBgEFBQcwAoYWaHR0cDovL3IzLmkubGVuY3Iub3JnLw=="
},
{
"Critical":false,
"Oid":{
"Value":"2.5.29.17",
"FriendlyName":"Subject Alternative Name"
},
"RawData":"MB6CHGJsb2cuZW1pbGlhbm9tb250ZXNkZW9jYS5jb20="
},
{
"Critical":false,
"Oid":{
"Value":"2.5.29.32",
"FriendlyName":"Certificate Policies"
},
"RawData":"MEMwCAYGZ4EMAQIBMDcGCysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3Jn"
},
{
"Critical":false,
"Oid":{
"Value":"1.3.6.1.4.1.11129.2.4.2",
"FriendlyName":"SCT List"
},
"RawData":"BIH0APIAdwBByMqx3yJGShDGoToJQodeTjGLGwPr60vHaPCQYpYG9gAAAYCeJIwYAAAEAwBIMEYCIQCG8sf4iBitUjNCc1dsxVd5mdRQCKapRqqnTHKxSKHjHgIhAJFGNXEZkCHKygT1T7bE4orpd6p2l1+GmifMEIuRsgHbAHcARqVV63X6kSAwtaKJafTzfREsQXS+/Um4havy/HD+bUcAAAGAniSMNgAABAMASDBGAiEAoxv1LBn/vfyR7s67kRLB/n1tq3eicuA/8/V0S2YzQCYCIQDXaS3FZbdIVNxQvKxPFxM1awBO/sGxBXafz0lspOoWSA=="
}
],
"FriendlyName":"",
"HasPrivateKey":false,
"PrivateKey":null,
"IssuerName":{
"Name":"CN=R3, O=Let's Encrypt, C=US",
"Oid":{
"Value":null,
"FriendlyName":null
},
"RawData":"MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJSMw=="
},
"NotAfter":"2022-08-05T10:50:35+01:00",
"NotBefore":"2022-05-07T10:50:36+01:00",
"PublicKey":{
"EncodedKeyValue":{
"Oid":{
"Value":"1.2.840.113549.1.1.1",
"FriendlyName":"RSA"
},
"RawData":"MIIBCgKCAQEAq8cbDO3GAfjqqbPPCBdPost8NMRmEubv85gXecll7mZMH5qSfTPuB/ouFWL3tPMf1U8usWeoSUK/48yatzBGwmj1KKlkaW9MS2QkydztRp+kH8LvbzbQvGknuOLWGHBALLT17o/3DYxuA5LnXdY+vLvJWygQoFr2N/XhnhUjcm6OaQEJpIykydfbBQGQSEuQIIw4egpgdHkYJjCOYAsXuSSggN8/FADTCec0RzVjfFTSoJ3hV9HLE9M8MCSXjuo0AJ/MbAxq91S8XmDcRjHCCd7Zw+NjHo8cxZCQ6NqGvn3xwx8ahmmbC+CyDEcIyJJZK2Yv+qE4oS8QZfaX/RaHMwIDAQAB"
},
"EncodedParameters":{
"Oid":{
"Value":"1.2.840.113549.1.1.1",
"FriendlyName":"RSA"
},
"RawData":"BQA="
},
"Key":{
"Key":{
"Algorithm":{
"Algorithm":"RSA"
},
"AlgorithmGroup":{
"AlgorithmGroup":"RSA"
},
"ExportPolicy":0,
"Handle":{
"IsInvalid":false,
"IsClosed":false
},
"IsEphemeral":true,
"IsMachineKey":false,
"KeyName":null,
"KeySize":2048,
"KeyUsage":16777215,
"ParentWindowHandle":{
"value":0
},
"Provider":{
"Provider":"Microsoft Software Key Storage Provider"
},
"ProviderHandle":{
"IsInvalid":false,
"IsClosed":false
},
"UIPolicy":{
"ProtectionLevel":0,
"FriendlyName":null,
"Description":null,
"UseContext":null,
"CreationTitle":null
},
"UniqueName":null
},
"LegalKeySizes":[
{
"MinSize":512,
"MaxSize":16384,
"SkipSize":64
}
],
"KeyExchangeAlgorithm":"RSA",
"SignatureAlgorithm":"RSA",
"KeySize":2048
},
"Oid":{
"Value":"1.2.840.113549.1.1.1",
"FriendlyName":"RSA"
}
},
"RawData":"MIIFQDCCBCigAwIBAgISBNwTmwP/RTcrEeIgAdMrpaFtMA0GCSqGSIb3DQEBCwUAMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJSMzAeFw0yMjA1MDcwOTUwMzZaFw0yMjA4MDUwOTUwMzVaMCcxJTAjBgNVBAMTHGJsb2cuZW1pbGlhbm9tb250ZXNkZW9jYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrxxsM7cYB+Oqps88IF0+iy3w0xGYS5u/zmBd5yWXuZkwfmpJ9M+4H+i4VYve08x/VTy6xZ6hJQr/jzJq3MEbCaPUoqWRpb0xLZCTJ3O1Gn6Qfwu9vNtC8aSe44tYYcEAstPXuj/cNjG4Dkudd1j68u8lbKBCgWvY39eGeFSNybo5pAQmkjKTJ19sFAZBIS5AgjDh6CmB0eRgmMI5gCxe5JKCA3z8UANMJ5zRHNWN8VNKgneFX0csT0zwwJJeO6jQAn8xsDGr3VLxeYNxGMcIJ3tnD42MejxzFkJDo2oa+ffHDHxqGaZsL4LIMRwjIklkrZi/6oTihLxBl9pf9FoczAgMBAAGjggJZMIICVTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFGNOFYVWWqSUAsIWQqSll5o4AleXMB8GA1UdIwQYMBaAFBQusxe3WFbLrlAJQOYfr52LFMLGMFUGCCsGAQUFBwEBBEkwRzAhBggrBgEFBQcwAYYVaHR0cDovL3IzLm8ubGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRwOi8vcjMuaS5sZW5jci5vcmcvMCcGA1UdEQQgMB6CHGJsb2cuZW1pbGlhbm9tb250ZXNkZW9jYS5jb20wTAYDVR0gBEUwQzAIBgZngQwBAgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwggEGBgorBgEEAdZ5AgQCBIH3BIH0APIAdwBByMqx3yJGShDGoToJQodeTjGLGwPr60vHaPCQYpYG9gAAAYCeJIwYAAAEAwBIMEYCIQCG8sf4iBitUjNCc1dsxVd5mdRQCKapRqqnTHKxSKHjHgIhAJFGNXEZkCHKygT1T7bE4orpd6p2l1+GmifMEIuRsgHbAHcARqVV63X6kSAwtaKJafTzfREsQXS+/Um4havy/HD+bUcAAAGAniSMNgAABAMASDBGAiEAoxv1LBn/vfyR7s67kRLB/n1tq3eicuA/8/V0S2YzQCYCIQDXaS3FZbdIVNxQvKxPFxM1awBO/sGxBXafz0lspOoWSDANBgkqhkiG9w0BAQsFAAOCAQEAjSEID5MWonbSiyHbmPYWO8ImCCOjkLGxgY8WJODbrWxFy+xU44UwrWOCkqYZUlv2LRmPqSyZDrIeeHK9VMbGh71oXX+XovikgAr6PpI0Mp897nPWj0XvOBaSYG0s+f+CXMtyt0tWCsQOcl+iT82+Ja71f8gbVL6l7xESewEE78pTKEH8EqD22r8VSD7FNICD8EYQr13v3AuVWObSU/R8Td6SrSVEknw1HgJS4e9nvmrMxBGKOJ+aWrAGiUydehg8M9o2gbGckMhz6D7cwB5l618cYaXKkW1dEOYZHl++qUj1/VPK+FNkiDZOPVNN//PbZuOLwAUIlZvhqGWX5/9PBg==",
"SerialNumber":"04DC139B03FF45372B11E22001D32BA5A16D",
"SignatureAlgorithm":{
"Value":"1.2.840.113549.1.1.11",
"FriendlyName":"sha256RSA"
},
"SubjectName":{
"Name":"CN=blog.emilianomontesdeoca.com",
"Oid":{
"Value":null,
"FriendlyName":null
},
"RawData":"MCcxJTAjBgNVBAMTHGJsb2cuZW1pbGlhbm9tb250ZXNkZW9jYS5jb20="
},
"Thumbprint":"28CF960F772ABFF22AA193C291492C27F8E13D4D",
"Version":3,
"Handle":{
"value":2658150705632
},
"Issuer":"CN=R3, O=Let's Encrypt, C=US",
"Subject":"CN=blog.emilianomontesdeoca.com"
}
有効期限
有効期限を知るには、このオブジェクト内にある NotAfter と NotBefore を確認する必要があります。
"NotAfter":"2022-08-05T10:50:35+01:00",
"NotBefore":"2022-05-07T10:50:36+01:00",
コンソール アプリケーション
次のスニペットは、.NET 6 上に構築された単純なコンソール アプリケーションであり、次の結果が生成され、必要な認定を確認できます。
using Newtonsoft.Json;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text.Json;
var url = "https://blog.emilianomontesdeoca.com/";
static async Task<X509Certificate2> CheckCertificateAsync(string urlPath)
{
var certificate = new X509Certificate2();
var httpClientHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (request, cert, chain, policyErrors) =>
{
certificate = new X509Certificate2(cert);
return true;
}
};
using HttpClient httpClient = new HttpClient(httpClientHandler);
await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, urlPath));
return certificate;
}
var cert = await CheckCertificateAsync(url);
var serializedValue = JsonConvert.SerializeObject(cert);
Console.WriteLine(serializedValue);
Console.ReadLine();
デモプロジェクト
コンソール アプリケーションは、私の Github の expiration-date-certificate というリポジトリにあります。