Logo address

証明書

証明書を読む

現在 Plan9 環境で証明書を扱うには2つのアプローチがある。1つは Plan9 起原のツールを使うこと、2つ目は Golang を使うことである。unix でポピュラーな Openssl は使えない。

前者は良くできてはいるが、Plan9 の開発者が Bell-Labs を辞めて Google に移り Golang に移っているので停滞感が否めない。Golang を使う場合には Golang のインストールが必要である。インストールの方法は
http:/golang/index.html
に書いてある。

証明書の例

次のサイトに証明書の例があるので、それを基に解説する。

[1] X509 certificate examples for testing and verification
https://fm4dd.com/openssl/certexamples.shtm

ここには
Root CA: DER Format (960 bytes) / PEM Format (1354 bytes).
とあり、クリックすると DER 形式と PEM 形式のファイルをダウンロードできるようになっている。ダウンロードされたファイルは各々

である。このうち frank4dd-cacert.pem を利用する。この内容は
-----BEGIN CERTIFICATE-----
MIIDvDCCAyWgAwIBAgIJAMbHBAm8IlugMA0GCSqGSIb3DQEBBQUAMIGbMQswCQYD
VQQGEwJKUDEOMAwGA1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNV
BAoTCEZyYW5rNEREMRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMT
D0ZyYW5rNEREIFdlYiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRk
ZC5jb20wHhcNMDcxMjA3MTAyMTQ2WhcNMTcxMjA0MTAyMTQ2WjCBmzELMAkGA1UE
BhMCSlAxDjAMBgNVBAgTBVRva3lvMRAwDgYDVQQHEwdDaHVvLWt1MREwDwYDVQQK
EwhGcmFuazRERDEYMBYGA1UECxMPV2ViQ2VydCBTdXBwb3J0MRgwFgYDVQQDEw9G
cmFuazRERCBXZWIgQ0ExIzAhBgkqhkiG9w0BCQEWFHN1cHBvcnRAZnJhbms0ZGQu
Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7r7yPJdXmDL2/+L2iogxQ
rLML+10EwAY9lJRCHGPqSJ8if7teqnXgFr6MAEiCwTcLvk4h1UxLrDXmxooegNg1
zx/OODbcc++SfFCGmflwj/wjLpYRwPgux7/QIgrUqzsj2HtdRFd+WPVD4AOtY9gn
xjNXFpVe1zmgAm/UFLdMewIDAQABo4IBBDCCAQAwHQYDVR0OBBYEFGLze+0G1LHV
nH9I5e/FyRVh/dkRMIHQBgNVHSMEgcgwgcWAFGLze+0G1LHVnH9I5e/FyRVh/dkR
oYGhpIGeMIGbMQswCQYDVQQGEwJKUDEOMAwGA1UECBMFVG9reW8xEDAOBgNVBAcT
B0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNEREMRgwFgYDVQQLEw9XZWJDZXJ0IFN1
cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdlYiBDQTEjMCEGCSqGSIb3DQEJARYU
c3VwcG9ydEBmcmFuazRkZC5jb22CCQDGxwQJvCJboDAMBgNVHRMEBTADAQH/MA0G
CSqGSIb3DQEBBQUAA4GBALosLpHduFOY30wKS2WQ32RzRgh0ZWNlLXWHkQYmzTHN
okwYLy0wGfIqzD1ovLMjDuPMC3MBmQPg8zhd+BY2sgRhgdEBmYWTiw71eZLLmI/e
dQbu1z6rOXJb8EegubJNkYTcuxsKLijIfJDnK2noqPt03puJEsBxosN14XPEhIEO
-----END CERTIFICATE-----

図1 frank4dd-cacert.pem

となっている。

補足
frank4dd-cacert.pem だけでなく、openssl が使えれば、例えば

openssl s_client -connect amazon.co.jp:443 -showcerts
で手に入る。標準出力に結果が表示される。amazon.co.jp の場合には3つの証明書が表示される。

Golang で書いた getcert.go を後に紹介する。pem 形式のファイルが欲しいだけなら、こちらの方が使いやすいと思う。

DER と PEM との関係

現在使われている証明書には2つの形式がある。DER 形式と PEM 形式である。DER 形式は binary データを含む。他方 PEM 形式はそれを base64 でエンコードしたテキスト表現である。エンコードされた結果は
-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----
に囲まれたテキストに含まれている。従って BEGINEND の2つの行で囲まれたテキストを base64 でデコードした結果は frank4dd-cacert.der と一致していなくてはならない。

証明書を cert.dercert.pem とすれば openssl を利用した相互変換は

openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM
および
openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
でやっていける。Plan9 の場合には
auth/pemencode CERTIFICATE cert.der > cert.pem
および
auth/pemdecode CERTIFICATE cert.pem > cert.der
である。Plan9 の方がシンプルでかつ拡張性を持っている。

SSL Finger Print

いわゆる SSL finger print は DER ファイルのハッシュ値である(らしい)1。SHA1 hash が使われることが多いようだ。

Openssl でも ssh1sum でも同様に得られる:

mbook$ openssl x509 -sha1 -fingerprint -noout -in frank4dd-cacert.pem
SHA1 Fingerprint=3A:AC:53:D7:C4:51:DC:06:25:C9:D2:4E:8E:D4:EC:1E:98:8F:93:A5
mbook$ sha1sum frank4dd-cacert.der
3aac53d7c451dc0625c9d24e8ed4ec1e988f93a5	frank4dd-cacert.der
mbook$

最近は SHA256 が使われるケースがある。openssl のオプション sha1sha256 に置き換えればよいだけだが、OS のコマンドとしての sha256sum はサポートされていない。Golang で書いた sha256sum コマンドを後に紹介する。


注1. らしいと書いたのは、まだ未確認だから。これに関する記述が rfc8122 あるが、まだ読んでいない。rfc8122 には
fingerprint:SHA-1 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB
の例あり。値には大文字を要求。":" で区切る。
フォーマットは openssl のと少し違う。

Openssl による証明書の表示

unix 上で コマンド

openssl x509 -text -noout -in frank4dd-cacert.pem
で証明書を見ると:
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            c6:c7:04:09:bc:22:5b:a0
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=JP, ST=Tokyo, L=Chuo-ku, O=Frank4DD, OU=WebCert Support, CN=Frank4DD Web CA/emailAddress=support@frank4dd.com
        Validity
            Not Before: Dec  7 10:21:46 2007 GMT
            Not After : Dec  4 10:21:46 2017 GMT
        Subject: C=JP, ST=Tokyo, L=Chuo-ku, O=Frank4DD, OU=WebCert Support, CN=Frank4DD Web CA/emailAddress=support@frank4dd.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:bb:af:bc:8f:25:d5:e6:0c:bd:bf:f8:bd:a2:a2:
                    0c:50:ac:b3:0b:fb:5d:04:c0:06:3d:94:94:42:1c:
                    63:ea:48:9f:22:7f:bb:5e:aa:75:e0:16:be:8c:00:
                    48:82:c1:37:0b:be:4e:21:d5:4c:4b:ac:35:e6:c6:
                    8a:1e:80:d8:35:cf:1f:ce:38:36:dc:73:ef:92:7c:
                    50:86:99:f9:70:8f:fc:23:2e:96:11:c0:f8:2e:c7:
                    bf:d0:22:0a:d4:ab:3b:23:d8:7b:5d:44:57:7e:58:
                    f5:43:e0:03:ad:63:d8:27:c6:33:57:16:95:5e:d7:
                    39:a0:02:6f:d4:14:b7:4c:7b
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                62:F3:7B:ED:06:D4:B1:D5:9C:7F:48:E5:EF:C5:C9:15:61:FD:D9:11
            X509v3 Authority Key Identifier:
                keyid:62:F3:7B:ED:06:D4:B1:D5:9C:7F:48:E5:EF:C5:C9:15:61:FD:D9:11
                DirName:/C=JP/ST=Tokyo/L=Chuo-ku/O=Frank4DD/OU=WebCert Support/CN=Frank4DD Web CA/emailAddress=support@frank4dd.com
                serial:C6:C7:04:09:BC:22:5B:A0

            X509v3 Basic Constraints:
                CA:TRUE
    Signature Algorithm: sha1WithRSAEncryption
        ba:2c:2e:91:dd:b8:53:98:df:4c:0a:4b:65:90:df:64:73:46:
        08:74:65:63:65:2d:75:87:91:06:26:cd:31:cd:a2:4c:18:2f:
        2d:30:19:f2:2a:cc:3d:68:bc:b3:23:0e:e3:cc:0b:73:01:99:
        03:e0:f3:38:5d:f8:16:36:b2:04:61:81:d1:01:99:85:93:8b:
        0e:f5:79:92:cb:98:8f:de:75:06:ee:d7:3e:ab:39:72:5b:f0:
        47:a0:b9:b2:4d:91:84:dc:bb:1b:0a:2e:28:c8:7c:90:e7:2b:
        69:e8:a8:fb:74:de:9b:89:12:c0:71:a2:c3:75:e1:73:c4:84:
        81:0e

図2: Openssl による表示例

が表示される。

この証明書は Issuer(発行者) 欄に書かれた組織から Subject(主体者) 欄に書かれた組織に対して発行されている。この場合には両組織は同じであるから自己証明書ということになる。CA:TRUE となっているから、Frank4DD は CA ビジネスを行っていることが判る。

Issuer 欄も Subject 欄も複数の項目から構成されている。これらの項目の集合は IssuerSubject を一意に定めるための情報であり "Distinguished Names" と呼ばれている(rfc5280)。

Email Address が含まれているのは、連絡用と言うより、情報の一意性を担保するための情報で、良いアイデアだと思う。

これと同等な内容を Plan9 側から見るにはどうしたら良いかがここでのテーマである。

なお Openssl では Serial Number を16進数で表示しているが、感心しない。この部分は発行書が管理しているはずて、人間にとって解りやすい10進数が好まれるであろう。実際日本の官庁では10進数で管理している[1]。

[1] 登記官証明書の入手
https://crca1.moj.go.jp/toukikan.html

Plan9 のツール

Plan9 には証明書を見るツールが既に存在する。単に

auth/pemdecode CERTIFICATE frank4dd-cacert.pem|auth/asn1dump
を実行すればよい。しかしこれが表示する情報は過剰である。Openssl が示す情報は良くまとまっている。これに近いツールは(残念ながら)自分で作らなくてはならない。ライブラリは揃っているので、次の簡単なプログラムで十分である:
#include <u.h>
#include <libc.h>
#include <mp.h>
#include <libsec.h>

void
usage(void)
{
	fprint(2, "usage: X509dump [file]\n");
	exits("usage");
}

// Ref: /sys/src/cmd/auth/x5092pub.c

ulong
readfile(uchar **b, char *file)
{
	int fd = 0;
	int tot,n;
	uchar *buf;
	if(file != nil && *file != 0)
		fd = open(file, OREAD);
	buf = nil;
	tot = 0;
	for(;;){
		buf = realloc(buf, tot+8192);
		if(buf == nil)
			sysfatal("realloc: %r");
		if((n = read(fd, buf+tot, 8192)) < 0)
			sysfatal("read: %r");
		if(n == 0)
			break;
		tot += n;
	}
	*b = buf;
	return tot;
}

void
main(int argc, char *argv[])
{
	uchar *b;
	ulong n;
	ARGBEGIN{
	default:
		usage();
	}ARGEND
	if(argc > 1)
		usage();

	fmtinstall('B', mpfmt);
	fmtinstall('H', encodefmt);
	fmtinstall('[', encodefmt);

	n = readfile(&b, argv[0]);
	X509dump(b, n);
}

譜1 x509dump.c

これを x509dump としてインストールすると
auth/pemdecode CERTIFICATE frank4dd-cacert.pem|x509dump
によって証明書に含まれる情報が得られる。その出力は
begin X509dump
serial -1
issuer support@frank4dd.com, Frank4DD Web CA, WebCert Support, Frank4DD, Chuo-ku, Tokyo, JP
validity 071207102146Z 171204102146Z
subject support@frank4dd.com, Frank4DD Web CA, WebCert Support, Frank4DD, Chuo-ku, Tokyo, JP
sigalg=4 digest=D628DC3FC5B3E6747C1091D78A6DDFF1FE48A6DB
publickey_alg=0 pubkey[140] 30818902818100BBAFBC8F25D5E60CBDBFF8BDA2A20C50ACB30BFB5D04C0063D9494421C63EA489F227FBB5EAA75E016BE8C004882C1370BBE4E21D54C4BAC35E6C68A1E80D835CF1FCE3836DC73EF927C508699F9708FFC232E9611C0F82EC7BFD0220AD4AB3B23D87B5D44577E58F543E003AD63D827C6335716955ED739A0026FD414B74C7B0203010001
rsa pubkey e=10001 n(1024)=BBAFBC8F25D5E60CBDBFF8BDA2A20C50ACB30BFB5D04C0063D9494421C63EA489F227FBB5EAA75E016BE8C004882C1370BBE4E21D54C4BAC35E6C68A1E80D835CF1FCE3836DC73EF927C508699F9708FFC232E9611C0F82EC7BFD0220AD4AB3B23D87B5D44577E58F543E003AD63D827C6335716955ED739A0026FD414B74C7B
self-signed X509rsaverifydigest returns: nil (meaning ok)
publickey_thumbprint sha256=FgWC1VleYWrHcK+uMN+Du76qssJoX8LOra7enlkC/x8=
cert_thumbprint sha256=bpmiR5xCdVi4ES6aC+3rKFrBvrRJmz2mR+qGXH3sApg=
cert_thumbprint sha1=3AAC53D7C451DC0625C9D24E8ED4EC1E988F93A5
end X509dump

図3 x509dump による表示例

である。素っ気ないので説明が必要である。

時刻表記

validity
071207102146Z

2007-12-07 10:21:46 GMT
と読む。

Golang のソースコードを読むと1071207102146Z の表現形式は ASN1 に基づいているが、2050 年問題が発生する。


注1: $GOROOT/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go

数字の表現

数字は原則として 16進数表記で正規表現で言えば [0-9A-F]+ で表されている。
例えば cert_thumbprintsha1 の "3AAC5⋯" がそうである。これは40個の16進数の並びであるので 160 bit のデータであり sha1 の定義に沿っている。他方 sha256 は 256 bit のはずで base64 でエンコードされている。
mbook$ echo 'bpmiR5xCdVi4ES6aC+3rKFrBvrRJmz2mR+qGXH3sApg=' |base64 -D|wc
       0       2      32
mbook$
ゆえ 256 bit である。

thumbprint に関しては

SUM(1)
    SYNOPSIS
    sum [ -5r ] [ file ... ]
    md5sum [ file ... ]
    sha1sum [ -2 bits ] [ file ... ]
sha256 は
    sha1sum -2 256 [file]

問題点

疑問

Golang

Golang は広範な OS で利用できるプログラミング言語であり、Plan9 でも使える。以下は Plan9 で作った golang のプログラムであるが、他の OS でもそのまま使える。

pemdump.go

pemdump.go による

pemdump frank4dd-cacert.pem
の実行結果は
Raw 308203bc30820325a003020102020900c6c70409bc225ba0300d06092a864886f70d010105050030819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d301e170d3037313230373130323134365a170d3137313230343130323134365a30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b0203010001a382010430820100301d0603551d0e0416041462f37bed06d4b1d59c7f48e5efc5c91561fdd9113081d00603551d230481c83081c5801462f37bed06d4b1d59c7f48e5efc5c91561fdd911a181a1a4819e30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d820900c6c70409bc225ba0300c0603551d13040530030101ff300d06092a864886f70d010105050003818100ba2c2e91ddb85398df4c0a4b6590df64734608746563652d7587910626cd31cda24c182f2d3019f22acc3d68bcb3230ee3cc0b73019903e0f3385df81636b2046181d1019985938b0ef57992cb988fde7506eed73eab39725bf047a0b9b24d9184dcbb1b0a2e28c87c90e72b69e8a8fb74de9b8912c071a2c375e173c484810e
RawTBSCertificate 30820325a003020102020900c6c70409bc225ba0300d06092a864886f70d010105050030819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d301e170d3037313230373130323134365a170d3137313230343130323134365a30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b0203010001a382010430820100301d0603551d0e0416041462f37bed06d4b1d59c7f48e5efc5c91561fdd9113081d00603551d230481c83081c5801462f37bed06d4b1d59c7f48e5efc5c91561fdd911a181a1a4819e30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d820900c6c70409bc225ba0300c0603551d13040530030101ff
RawSubjectPublicKeyInfo 30819f300d06092a864886f70d010101050003818d0030818902818100bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b0203010001
RawSubject 30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d
RawIssuer 30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d
Signature ba2c2e91ddb85398df4c0a4b6590df64734608746563652d7587910626cd31cda24c182f2d3019f22acc3d68bcb3230ee3cc0b73019903e0f3385df81636b2046181d1019985938b0ef57992cb988fde7506eed73eab39725bf047a0b9b24d9184dcbb1b0a2e28c87c90e72b69e8a8fb74de9b8912c071a2c375e173c484810e
SignatureAlgorithm SHA1-RSA
PublicKeyAlgorithm RSA
PublicKey N=bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b
PublicKey E=10001
Version 3
SerialNumber 14323421579732736928 (c6c70409bc225ba0)
Issuer CN=Frank4DD Web CA,OU=WebCert Support,O=Frank4DD,L=Chuo-ku,ST=Tokyo,C=JP,1.2.840.113549.1.9.1=#0c14737570706f7274406672616e6b3464642e636f6d
Subject CN=Frank4DD Web CA,OU=WebCert Support,O=Frank4DD,L=Chuo-ku,ST=Tokyo,C=JP,1.2.840.113549.1.9.1=#0c14737570706f7274406672616e6b3464642e636f6d
NotBefore 2007-12-07 10:21:46 +0000 UTC
NotAfter 2017-12-04 10:21:46 +0000 UTC
KeyUsage 0
IsCA true
SubjectKeyId 62f37bed06d4b1d59c7f48e5efc5c91561fdd911
AuthorityKeyId 62f37bed06d4b1d59c7f48e5efc5c91561fdd911
DNSNames []
EmailAddresses []
IPAddresses []
URIs []
Extensions 0 Id=2.5.29.14 (Subject Key Id) Critical=false Value=041462f37bed06d4b1d59c7f48e5efc5c91561fdd911
Extensions 1 Id=2.5.29.35 (Authority Key Id) Critical=false Value=3081c5801462f37bed06d4b1d59c7f48e5efc5c91561fdd911a181a1a4819e30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d820900c6c70409bc225ba0
Extensions 2 Id=2.5.29.19 (Basic Constraints) Critical=false Value=30030101ff

図4: pemdump frank4dd-cacert.pem

である。Serial Number は10進数で表示し、参考のために16進数も表示した。

Openssl で得られる情報はほぼ pemdump でも得られているが、Extensions は表示が Openssl に一致していない。理由は pemdump が頑張りきっていないところにあるようだ。

Id とは Object Id のことであって、これらが何を意味しているかは
http://www.oid-info.com
に公開されている。それによると(例えば)

1.2.840.113549.1.9.1 Email Address
2.5.29.14 Subject key identifier
2.5.29.35 Authority key identifier
2.5.29.19 Basic constraints
などとなっている。この情報を "( )" の中に示しておいた。
実際 Email Address の部分を解析すると support@frank4dd.com となっていることが判る。
さらに Extensions 1 の長い文字列を解析すると、
JP
Tokyo
Chuo-ku
Frank4DD
WebCert Support
Frank4DD Web CA
support@frank4dd.com

の文字列が含まれていることが判る。

ASN.1 / DER

用語で頭の中が混乱する!

ASN.1

ASN.1 については文献[1]が良いかも
ASN.1 はデータ交換に必要な膨大な用語と記法を定義している。文献[2,2a]を見よ
エンコードの方法は ASN.1 の外

ASN.1 / DER

ASN.1 DER encoding
octet データ列での encode の方法を定めている。文献[3]

CPU の仕様に依存しないデータ表現

これらを TLV (Tag Length Value) とも言う。
"octets" となっているから 8 bits 単位の処理を前提としているのだろう。
Identifier octets の各 bit の意味は文献[6]を見よ。
Length octets の扱いも面倒。

Identifier octets
以下、各 octet を、(習慣に従って)先頭から b8,b7,...,b1 とする。
b8,b7 Class

観測によると、殆どが Universal である。

b6 が重要

b5,...,b1 は Tag number の bit 表現である。Tag bits 11111 は特殊。Tag number 30 を超えた場合に用意されている。

X.680 には表 "Universal class tag assignments" がある。この表によると 36 まで割り当てられており、37 以上は reserved となっている。しかし、もはや使われていないものもあり、実際には 30 までで間に合っている。

注: X.680 へは文献[2]から辿っていける。

最も短いデータは論理値である。この場合、Identifier、Length、Contents 全て 1 octet。primitive。

整数。primitive。これも複雑(そうでもない)。

どうやら ASN.1 は個別のデータ表現を定めているだけで、全体構成を論じていない。

例1:

Raw 308203bc308....
先頭の 30 は "universal constructed sequence" である。byte 列はこれに属する。次の 82 は Length octets の始まりである。この部分が

例えば 82 は次の 2 octet がデータの長さを表していることを意味する。このケースでは (03bc)16 = (956)10 である。すなわち 03bc に続く 956 octet はデータであることを主張している。実際 Raw の部分は 960 B であり、ここから 308203bc を差し引けば 956 B である。

例2: Extensions 0

Value=041462f37b...
先頭の 04 は "universal primitive octet string" を意味する。データ長は次の 14 によって表されている。これは 10進数で 20 である。実際 62f37b... がデータであり 20 B あることが確認できる。
この部分は Openssl を使ったときに "Key Identifier" として表示された
62:F3:7B:...
に対応していることに注目しよう。

例3: Extensions 1

Value=3081c5801462f37bed06d4b1d59c7f48e ...
先頭の 30 は "universal constructed sequence" であった。次に続く 81 は次の 1 octet すなわち c5 がデータの長さを表している。データの長さは (c5)16 すなわち (197)10 である。実際の Value の16進文字列としての長さは 400 であり、これは 3081c5 の長さ 3 と 197 の和 200 の 2 倍である。この長い16進文字列の中に(Openssl で表示されている)keyid, DirName, serial の情報が含まれている。

"Id" とは何か? (⇒ Object Id)

"octet string" と "constructed sequence" との違い
観察によると "octet string" は印字不能文字を含んでいる (primitive)
他方 "constructed sequence" は内部構造を持ったデータ
primitive になるまで分解可能なのだろう

3081c5 に続く 80 は何を意味しているか?
"Context-specific" + "primitive" + "tag 0" と考えてよいか? ⇒ YES

B.3. STANDARD X.509 V3 CERTIFICATE EXTENSION REFERENCE
https://access.redhat.com/documentation/en-us/red_hat_certificate_system/9/html/administration_guide/standard_x.509_v3_certificate_extensions

ASN.1 DER encoding is a tag, length, value encoding system for each element.
rfc5280

   Certificate  ::=  SEQUENCE  {
        tbsCertificate       TBSCertificate,
        signatureAlgorithm   AlgorithmIdentifier,
        signatureValue       BIT STRING  }

   TBSCertificate  ::=  SEQUENCE  {
        version         [0]  EXPLICIT Version DEFAULT v1,
        serialNumber         CertificateSerialNumber,
        signature            AlgorithmIdentifier,
        issuer               Name,
        validity             Validity,
        subject              Name,
        subjectPublicKeyInfo SubjectPublicKeyInfo,
        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
                             -- If present, version MUST be v2 or v3
        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
                             -- If present, version MUST be v2 or v3
        extensions      [3]  EXPLICIT Extensions OPTIONAL
                             -- If present, version MUST be v3
        }

図5: X.509 v3 certificate format (quoted from rfc5280)

つまり、署名は TBSCertificate に対して行う。

ASN.1 DER encoding of OID

OID: Object ID
10進数の非負整数を "." で区切って表されることが多い。例えば

1.1.19785.0.257.1.5
のように。(例は文献[2])

文献[6]の説明によると
この数字列を N0.N1.N2.N3. .... とすると

N0,N1 がイレギュラーなのは、N0,N1 を併せて 1 octet でコード化されるからである。

補注: Golang のソースコード

$GOROOT/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go
の中の関数 func isValidOID では N0==2 の場合に N1 の条件 N1<40 は外されている。Golang が正しい。文献[3]を見よ。

文献

[1] Introduction to ASN.1​
https://www.itu.int/en/ITU-T/asn1/Pages/introduction.aspx

[2] Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile
https://www.itu.int/rec/T-REC-X.680-202102-I

[2a] Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile
https://datatracker.ietf.org/doc/html/rfc5280

[3] X.690: Information technology – ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER)
and Distinguished Encoding Rules (DER)
https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf

[4] 抽象記法
http://www5d.biglobe.ne.jp/stssk/asn1/basic.html

[5] A Warm Welcome to ASN.1 and DER
https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/

[6] https://docs.microsoft.com/ja-jp/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN

[7] http://www.oid-info.com/cgi-bin/display?oid=2.5.4.6&a=display

[8] A Layman's Guide to a Subset of ASN.1, BER, and DER
https://luca.ntop.org/Teaching/Appunti/asn1.html

解析ツール

ASN1 形式の理解と解析のために役立ちそうなツールを作ったので紹介しておく。
Openssl ほど親切ではないが、その代わりに内部構造を忠実に見せてくれる。

asn1parse.go

asn1parse.go

使い方は3つあり

前者は PEM 形式のファイルを読み取り、内容を解析する。
後者は 16 進数表現の文字列を読み取り、内容を解析する。

"-D" はデバッグモードであり、解析の元になった 16 進数表現の文字列を表示しながら、解析していく。-D を指定しない場合には結果だけを表示する。

次に示すのは

asn1parse frank4dd-cacert.pem
の実行結果である。

今回の版では

X.509 v3 certificate format を基にコメントを "#" で入れておく。(全ては入れていない)

identifier Universal:Constructed:Sequence [1]	# certiticate の全体
  identifier Universal:Constructed:Sequence [1 1] # tbsCertificate
    identifier ContextSpecific:Constructed:0 [1 1 1]
      identifier Universal:Primitive:Integer [1 1 1 1]
      contents 02				# version
    identifier Universal:Primitive:Integer [1 1 2]
    contents 00c6c70409bc225ba0			# serialNumber
    identifier Universal:Constructed:Sequence [1 1 3]
      identifier Universal:Primitive:OID [1 1 3 1]
      contents "1.2.840.113549.1.1.5" (Sha1 With Rsa Encryption)
      identifier Universal:Primitive:Null [1 1 3 2]
      contents
    identifier Universal:Constructed:Sequence [1 1 4]
      identifier Universal:Constructed:Set [1 1 4 1]
        identifier Universal:Constructed:Sequence [1 1 4 1 1]
          identifier Universal:Primitive:OID [1 1 4 1 1 1]
          contents "2.5.4.6" (Country Name)
          identifier Universal:Primitive:PrintableString [1 1 4 1 1 2]
          contents JP
      identifier Universal:Constructed:Set [1 1 4 2]
        identifier Universal:Constructed:Sequence [1 1 4 2 1]
          identifier Universal:Primitive:OID [1 1 4 2 1 1]
          contents "2.5.4.8" (State or Province name)
          identifier Universal:Primitive:PrintableString [1 1 4 2 1 2]
          contents Tokyo
      identifier Universal:Constructed:Set [1 1 4 3]
        identifier Universal:Constructed:Sequence [1 1 4 3 1]
          identifier Universal:Primitive:OID [1 1 4 3 1 1]
          contents "2.5.4.7" (Locality Name)
          identifier Universal:Primitive:PrintableString [1 1 4 3 1 2]
          contents Chuo-ku
      identifier Universal:Constructed:Set [1 1 4 4]
        identifier Universal:Constructed:Sequence [1 1 4 4 1]
          identifier Universal:Primitive:OID [1 1 4 4 1 1]
          contents "2.5.4.10" (Organization Name)
          identifier Universal:Primitive:PrintableString [1 1 4 4 1 2]
          contents Frank4DD
      identifier Universal:Constructed:Set [1 1 4 5]
        identifier Universal:Constructed:Sequence [1 1 4 5 1]
          identifier Universal:Primitive:OID [1 1 4 5 1 1]
          contents "2.5.4.11" (Organization Unit Name)
          identifier Universal:Primitive:PrintableString [1 1 4 5 1 2]
          contents WebCert Support
      identifier Universal:Constructed:Set [1 1 4 6]
        identifier Universal:Constructed:Sequence [1 1 4 6 1]
          identifier Universal:Primitive:OID [1 1 4 6 1 1]
          contents "2.5.4.3" (Common Name)
          identifier Universal:Primitive:PrintableString [1 1 4 6 1 2]
          contents Frank4DD Web CA
      identifier Universal:Constructed:Set [1 1 4 7]
        identifier Universal:Constructed:Sequence [1 1 4 7 1]
          identifier Universal:Primitive:OID [1 1 4 7 1 1]
          contents "1.2.840.113549.1.9.1" (Email Address)
          identifier Universal:Primitive:IA5String [1 1 4 7 1 2]
          contents support@frank4dd.com
    identifier Universal:Constructed:Sequence [1 1 5]
      identifier Universal:Primitive:UTCTime [1 1 5 1]
      contents 071207102146Z
      identifier Universal:Primitive:UTCTime [1 1 5 2]
      contents 171204102146Z
    identifier Universal:Constructed:Sequence [1 1 6]
      identifier Universal:Constructed:Set [1 1 6 1]
        identifier Universal:Constructed:Sequence [1 1 6 1 1]
          identifier Universal:Primitive:OID [1 1 6 1 1 1]
          contents "2.5.4.6" (Country Name)
          identifier Universal:Primitive:PrintableString [1 1 6 1 1 2]
          contents JP
      identifier Universal:Constructed:Set [1 1 6 2]
        identifier Universal:Constructed:Sequence [1 1 6 2 1]
          identifier Universal:Primitive:OID [1 1 6 2 1 1]
          contents "2.5.4.8" (State or Province name)
          identifier Universal:Primitive:PrintableString [1 1 6 2 1 2]
          contents Tokyo
      identifier Universal:Constructed:Set [1 1 6 3]
        identifier Universal:Constructed:Sequence [1 1 6 3 1]
          identifier Universal:Primitive:OID [1 1 6 3 1 1]
          contents "2.5.4.7" (Locality Name)
          identifier Universal:Primitive:PrintableString [1 1 6 3 1 2]
          contents Chuo-ku
      identifier Universal:Constructed:Set [1 1 6 4]
        identifier Universal:Constructed:Sequence [1 1 6 4 1]
          identifier Universal:Primitive:OID [1 1 6 4 1 1]
          contents "2.5.4.10" (Organization Name)
          identifier Universal:Primitive:PrintableString [1 1 6 4 1 2]
          contents Frank4DD
      identifier Universal:Constructed:Set [1 1 6 5]
        identifier Universal:Constructed:Sequence [1 1 6 5 1]
          identifier Universal:Primitive:OID [1 1 6 5 1 1]
          contents "2.5.4.11" (Organization Unit Name)
          identifier Universal:Primitive:PrintableString [1 1 6 5 1 2]
          contents WebCert Support
      identifier Universal:Constructed:Set [1 1 6 6]
        identifier Universal:Constructed:Sequence [1 1 6 6 1]
          identifier Universal:Primitive:OID [1 1 6 6 1 1]
          contents "2.5.4.3" (Common Name)
          identifier Universal:Primitive:PrintableString [1 1 6 6 1 2]
          contents Frank4DD Web CA
      identifier Universal:Constructed:Set [1 1 6 7]
        identifier Universal:Constructed:Sequence [1 1 6 7 1]
          identifier Universal:Primitive:OID [1 1 6 7 1 1]
          contents "1.2.840.113549.1.9.1" (Email Address)
          identifier Universal:Primitive:IA5String [1 1 6 7 1 2]
          contents support@frank4dd.com
    identifier Universal:Constructed:Sequence [1 1 7]
      identifier Universal:Constructed:Sequence [1 1 7 1]
        identifier Universal:Primitive:OID [1 1 7 1 1]
        contents "1.2.840.113549.1.1.1" (RSA Encryption)
        identifier Universal:Primitive:Null [1 1 7 1 2]
        contents
      identifier Universal:Primitive:BitString [1 1 7 2]
      contents 0030818902818100bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b0203010001
    identifier ContextSpecific:Constructed:BitString [1 1 8]
      identifier Universal:Constructed:Sequence [1 1 8 1]
        identifier Universal:Constructed:Sequence [1 1 8 1 1]
          identifier Universal:Primitive:OID [1 1 8 1 1 1]
          contents "2.5.29.14" (Subject Key Id)
          identifier Universal:Primitive:OctetString [1 1 8 1 1 2]
          contents 041462f37bed06d4b1d59c7f48e5efc5c91561fdd911
        identifier Universal:Constructed:Sequence [1 1 8 1 2]
          identifier Universal:Primitive:OID [1 1 8 1 2 1]
          contents "2.5.29.35" (Authority Key Id)
          identifier Universal:Primitive:OctetString [1 1 8 1 2 2]
          contents 3081c5801462f37bed06d4b1d59c7f48e5efc5c91561fdd911a181a1a4819e30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d820900c6c70409bc225ba0
        identifier Universal:Constructed:Sequence [1 1 8 1 3]
          identifier Universal:Primitive:OID [1 1 8 1 3 1]
          contents "2.5.29.19" (Basic Constraints)
          identifier Universal:Primitive:OctetString [1 1 8 1 3 2]
          contents 30030101ff
  identifier Universal:Constructed:Sequence [1 2] # signatureAlgorithm
    identifier Universal:Primitive:OID [1 2 1]
    contents "1.2.840.113549.1.1.5" (Sha1 With Rsa Encryption)
    identifier Universal:Primitive:Null [1 2 2]
    contents
  identifier Universal:Primitive:BitString [1 3]
  contents 00ba2c2e91ddb85398df4c0a4b6590df64734608746563652d7587910626cd31cda24c182f2d3019f22acc3d68bcb3230ee3cc0b73019903e0f3385df81636b2046181d1019985938b0ef57992cb988fde7506eed73eab39725bf047a0b9b24d9184dcbb1b0a2e28c87c90e72b69e8a8fb74de9b8912c071a2c375e173c484810e

図6: asn1parse

TagNull

tag が Null となっている contents は、何も含まれていない、従って長さが 0 の contents である。

Use a null type to indicate the effective absence of a component of a sequence.(X.680)

   When any of these three OIDs appears within the ASN.1 type
   AlgorithmIdentifier, the parameters component of that type SHALL be
   the ASN.1 type NULL.

Null の使われ方
使うべき場面が指示されていることもある
例: RSA Certificate
https://datatracker.ietf.org/doc/html/rfc5280#page-10

Universal:Primitive:OctetString

図6に3箇所に現れる Universal:Primitive:OctetString はどれも内部構造を持っている。asn1parse を使って contents を調べると

[1 1 8 1 1 2]

identifier Universal:Primitive:OctetString
contents 62f37bed06d4b1d59c7f48e5efc5c91561fdd911
この結果に現れる 62f37bed06d4b...OctetString とされているがもはや内部構造を持たない。"Subject Key Id" として Openssl や pemdump に現れている値である。

[1 1 8 1 2 2]

identifier Universal:Constructed:Sequence
  identifier ContextSpecific:Primitive:0
  contents 62f37bed06d4b1d59c7f48e5efc5c91561fdd911
  identifier ContextSpecific:Constructed:Boolean
    identifier ContextSpecific:Constructed:OctetString
      identifier Universal:Constructed:Sequence
        identifier Universal:Constructed:Set
          identifier Universal:Constructed:Sequence
            identifier Universal:Primitive:OID
            contents "2.5.4.6" (Country Name)
            identifier Universal:Primitive:PrintableString
            contents JP
        identifier Universal:Constructed:Set
          identifier Universal:Constructed:Sequence
            identifier Universal:Primitive:OID
            contents "2.5.4.8" (State or Province name)
            identifier Universal:Primitive:PrintableString
            contents Tokyo
        identifier Universal:Constructed:Set
          identifier Universal:Constructed:Sequence
            identifier Universal:Primitive:OID
            contents "2.5.4.7" (Locality Name)
            identifier Universal:Primitive:PrintableString
            contents Chuo-ku
        identifier Universal:Constructed:Set
          identifier Universal:Constructed:Sequence
            identifier Universal:Primitive:OID
            contents "2.5.4.10" (Organization Name)
            identifier Universal:Primitive:PrintableString
            contents Frank4DD
        identifier Universal:Constructed:Set
          identifier Universal:Constructed:Sequence
            identifier Universal:Primitive:OID
            contents "2.5.4.11" (Organization Unit Name)
            identifier Universal:Primitive:PrintableString
            contents WebCert Support
        identifier Universal:Constructed:Set
          identifier Universal:Constructed:Sequence
            identifier Universal:Primitive:OID
            contents "2.5.4.3" (Common Name)
            identifier Universal:Primitive:PrintableString
            contents Frank4DD Web CA
        identifier Universal:Constructed:Set
          identifier Universal:Constructed:Sequence
            identifier Universal:Primitive:OID
            contents "1.2.840.113549.1.9.1" (Email Address)
            identifier Universal:Primitive:IA5String
            contents support@frank4dd.com
  identifier ContextSpecific:Primitive:Integer
  contents 00c6c70409bc225ba0
Constructed:Boolean はイメージが湧かないが...

rfc5280

   AuthorityKeyIdentifier ::= SEQUENCE {
      keyIdentifier             [0] KeyIdentifier           OPTIONAL,
      authorityCertIssuer       [1] GeneralNames            OPTIONAL,
      authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }

   KeyIdentifier ::= OCTET STRING

[1 1 8 1 3 2]

identifier Universal:Constructed:Sequence
  identifier Universal:Primitive:Boolean
  contents ff

BitString

図6の末尾

  identifier Universal:Primitive:BitString [1 3]
  contents 00ba2c2e91ddb85398df4c0a4b6590df64734608746563652d7587910626cd31cda24c182f2d3019f22acc3d68bcb3230ee3cc0b73019903e0f3385df81636b2046181d1019985938b0ef57992cb988fde7506eed73eab39725bf047a0b9b24d9184dcbb1b0a2e28c87c90e72b69e8a8fb74de9b8912c071a2c375e173c484810e
contentsBitString である。
BitString の最初の octet は最後の octet の中に含まれている使われていない bit 数を表している。従って 00 から 07 である。図6に現れた BitString はどれも 00 で始まっている。この場合には、続く全ての octet が有効な bit で構成されていると考えてよい。従って ba2c2e91ddb8... は signature の値である。

ここに signature の値が来るべきであることは、 X.509 v3 に

   Certificate  ::=  SEQUENCE  {
        tbsCertificate       TBSCertificate,
        signatureAlgorithm   AlgorithmIdentifier,
        signatureValue       BIT STRING  }
として要請されている。

X.509 v3 によると TBSCertificate の構造は

   TBSCertificate  ::=  SEQUENCE  {
        version         [0]  EXPLICIT Version DEFAULT v1,
        serialNumber         CertificateSerialNumber,
        signature            AlgorithmIdentifier,
        issuer               Name,
        validity             Validity,
        subject              Name,
        subjectPublicKeyInfo SubjectPublicKeyInfo,
        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
                             -- If present, version MUST be v2 or v3

        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
                             -- If present, version MUST be v2 or v3
        extensions      [3]  EXPLICIT Extensions OPTIONAL
                             -- If present, version MUST be v3
        }
となっている。これによると "subjectPublicKeyInfo" の位置は "[1 1 7]" に相当する。更に X.509 v3:
   SubjectPublicKeyInfo  ::=  SEQUENCE  {
        algorithm            AlgorithmIdentifier,
        subjectPublicKey     BIT STRING  }
により subjectPublicKey は "[1 1 7 2]" にあるはずで、図6の
      identifier Universal:Primitive:BitString [1 1 7 2]
      contents 0030818902818100bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b0203010001
contentssubjectPublicKey を表している。

subjectPublicKey の構造は X.509 v3 には示されていないようである。この部分は暗号方式に依存しているはず。rfc3279 には

   RSAPublicKey ::= SEQUENCE {
      modulus            INTEGER,    -- n
      publicExponent     INTEGER  }  -- e
とある。つまり
contents 0030818902818100bbafbc8f25...
は内部構造を持っており、その中には modulus npublicExponent e が含まれているはずである。

実際、BitString だから先頭の 00 を除外して asn1parse で調べると

identifier Universal:Constructed:Sequence
  identifier Universal:Primitive:Integer
  contents 00bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b
  identifier Universal:Primitive:Integer
  contents 010001
となっていて、Integer を表す contents が2つ含まれていることが判る。最初のは 00bbafbc8f25d5e6... でこれは PublicKey N であり、第2のは 10001 であり PublicKey E である。

まとめ


PKCS #1

RSA key に関しては
https://datatracker.ietf.org/doc/html/rfc3279#section-2.3.1
が詳しい

   The RSA public key MUST be encoded using the ASN.1 type RSAPublicKey:

      RSAPublicKey ::= SEQUENCE {
         modulus            INTEGER,    -- n
         publicExponent     INTEGER  }  -- e

   where modulus is the modulus n, and publicExponent is the public
   exponent e.  The DER encoded RSAPublicKey is the value of the BIT
   STRING subjectPublicKey.

[1] PKCS #1 v2.2
https://datatracker.ietf.org/doc/html/rfc8017

[2] RSA: Sign / Verify - Examples
https://cryptobook.nakov.com/digital-signatures/rsa-sign-verify-examples

問題は、コメント部分を如何に安全に挿入できるかだ。

Golang でサポートされている関数を使えば、もっとコードを短くできるのであろうが、ここでは全て手作りで asn1parse の中に収められている。その方がアルゴリズムを理解しやすいであろう。(多分エラーチェックは甘いだろう)

総評:
教育用あるいは研究用のツールとしてはこれで良いのだが、実用的なツールとしてはこの延長上に答えはなさそう。OID を解りやすい単語で表すのはデータベースを準備すれば足りる。問題は、X.509 の構造をコメントを加えて判りやすく示せないことにある。コメント部分を安全に挿入する方法がない。

データベースを作るには、例えば
https://opensource.apple.com/source/libsecurity_keychain/libsecurity_keychain-55029/lib/CertificateValues.cpp
からデータを抜き取るのが良さそう。(もっと良いサイトがあるだろう)
OID を含む Golang のコードはバラバラで、扱いにくい。

https://stackoverflow.com/questions/66515917/how-do-i-retrieve-subject-or-issuer-distinguished-name-from-a-certificate-with-a

Subject Key Identifier

鍵の ID
RSA の場合には公開鍵の N と E を基に sha1sum で ID を導出する。

図6 の

contents "2.5.29.14" (Subject Key Id)
contents "2.5.29.35" (Authority Key Id)
contents はどのように得られたのか?
frank4dd-cacert.pem の場合には共に
62f37bed06d4b1d59c7f48e5efc5c91561fdd911
が含まれている。Openssl も pemdump でも、この部分が共に
として表示されている。

rfc5280 に載っている。これによると CA certificate を含む場合に必須。そしてよく使われる2つの方法がある:

      (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
           value of the BIT STRING subjectPublicKey (excluding the tag,
           length, and number of unused bits).
      (2) The keyIdentifier is composed of a four-bit type field with
           the value 0100 followed by the least significant 60 bits of
           the SHA-1 hash of the value of the BIT STRING
           subjectPublicKey (excluding the tag, length, and number of
           unused bits).

図6 は次の内容を含んでいる。

      identifier Universal:Primitive:BitString [1 1 7 2]
      contents 0030818902818100bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b0203010001
(1) の方法であれば、この BitStringcontents から先頭の 00 を除いた sha1sum は
hexdecode 30818902818100bbafbc8f25d5e60cbd... |sha1sum
によって得られる
SHA1=62f37bed06d4b1d59c7f48e5efc5c91561fdd911
であり、実際、図 pemdump ではこれが "Subject Key Identifier" として表示されている。(hexdecode については次の「その他のツール」を見よ)
仮に (2) の方法を採用すれば "Subject Key Identifier" は次のようになるだろう:
4fc5c91561fdd911

その他のツール

Golang のソースコードは豊富なライブラリを含んでいる。コマンド化はされていないものの、それを基に簡単にコマンドを作成できたりする。公開鍵に関係する、そのようなコマンドを以下に紹介する。(コマンド名は僕の好みで付けている)

pemencode.go

pemencode.go
usage: pemencode tag cert.der
このプログラムは DER 形式のファイルを基に PEM 形式のファイルを作るのに使える。
tag は section label であり、"CERTIFICATE", "PRIVATE KEY", などを指定する。
短いプログラムであり、説明は要らないであろう。
もっとも Plan9 には auth/pemencode が既に存在する。

複数の証明書を含む場合、どのような仕様にすべきか、悩ましい...
注: pemencode は任意のファイルに対する base64 エンコーディングなのである。DER は特別扱いすべきか?

pemdecode.go

pemdecode.go
usage: pemdecode cert.pem [n]
   n is 1,2,...
   n: certificate number in cert.pem to be decoded
   if n is not given, all certificates will be decoded

このプログラムは PEM 形式のファイルから DER 形式のファイルを作るのに使える。
短いプログラムであり、説明は要らないであろう。
Plan9 には auth/pemdecode が既に存在するが複数の証明書を含む場合に対応していない。

hexdecode.go

hexdecode.go
usage: hexdecode hexstr

このプログラムは16進文字列を与え、それを decode した結果(binary)を標準出力に書き出す。

getcert.go

getcert.go
usage: getcert url
これは解析ツールと言うより https サーバーの証明書を得るためのツールである。
証明書は pem 形式で標準出力に書き出す。従って、例えば
getcert https://amazon.co.jp > amazon.pem
とすればよい。
Openssl を使うよりも面倒がなくて使いやすいと思う。

pemverify.go

pemverify.go
usage: pemverify cert.pem
これは certificate-chain を調べる。版番が 0.6 となっているのは、まだ不十分な面を残しているからである。

sha1sum.go / sha256sum.go

sha1sum.go
usage: sha1sum [file]

sha256sum.go

usage: sha256sum [file]

仕様を Plan9 の付属の sha1sum に合わせて複数のファイルをサポートすべきであるがサボられている。

Case Study

これまで frank4dd-cacert.pem を例に調べてきたが、この証明書は簡単な部類に属する。理由は frank4dd が root CA ビジネスを行っているために、この証明書は自己署名だからである。

一般の Web のサーバーに添えられる証明書の構造はもっと複雑である。ここでは Amazon.co.jp を例に証明書の構造を調べる。

Amazon.co.jp

Amazon.co.jp の公開鍵は

getcert https://amazon.co.jp > amazon.pem
とすれば手に入る。amazon.pem の大まかな構造は
cat amazon.pem
を実行すれば、以下の3つの証明書から構成されていることが判る。


subject issuer
1 *.peg.a2z.com DigiCert Global CA G2
2 DigiCert Global CA G2 DigiCert Global Root G2
3 DigiCert Global Root G2 VeriSign Class 3 PPCA1


注1: "VeriSign Class 3 PPCA" と書いたのは
VeriSign Class 3 Public Primary Certification Authority
のこと

amazon.pem の内部情報を知りたい場合には

pemdump amazon.pem
を実行すると次の結果を得る:
Raw 308208c1308207a9a00302010202100e4239ab85e2e6a27c52c6de9b9078d9300d06092a864886f70d01010b05003044310b300906035504061302555331153013060355040a130c446967694365727420496e63311e301c06035504031315446967694365727420476c6f62616c204341204732301e170d3231313030363030303030305a170d3232303931393233353935395a30183116301406035504030c0d2a2e7065672e61327a2e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100bfefee33c3647bea4353a956a1900b5dfacdc07ebf077fbc1447cd7b00fa98df2e9edcc2307f1f3d4e466f5fe8750592ec68813e8c2853ab26163e05d240f7421e0e5290156dc612d9a7799d5067c2687c4e6fd4dc33b7e05660c6d8f3deac4154aaf5af260edfed7f1f6c41ba2b7c5b54d277fb3eda3a2ea7300042ad339fc077ea4a62d7875821a660070d16b901dac9b4e50b4724a3dc76b78dd15f1359811c6a63287e23e30ad7d64e0198023c0a28257c9089422885374ec3c8270d8e60238ce11f2cefba189f481788235580e8c7c6762295f8ad11f4b2ebd281d857717bc824280cddbd6558178f8519bbae08c48427b8744de97da8b51dea8148c0a10203010001a38205d9308205d5301f0603551d23041830168014246e2b2dd06a925151256901aa9a47a689e74020301d0603551d0e041604149545143e3a401e9516f082ac457382586d9bf074308202a30603551d110482029a30820296820c616d617a6f6e2e636f2e756b82137565646174612e616d617a6f6e2e636f2e756b82107777772e616d617a6f6e2e636f2e756b82176f726967696e2d7777772e616d617a6f6e2e636f2e756b820d2a2e7065672e61327a2e636f6d820a616d617a6f6e2e636f6d8208616d7a6e2e636f6d82117565646174612e616d617a6f6e2e636f6d820d75732e616d617a6f6e2e636f6d820e7777772e616d617a6f6e2e636f6d820c7777772e616d7a6e2e636f6d8214636f72706f726174652e616d617a6f6e2e636f6d8211627579626f782e616d617a6f6e2e636f6d82116970686f6e652e616d617a6f6e2e636f6d820d79702e616d617a6f6e2e636f6d820f686f6d652e616d617a6f6e2e636f6d82156f726967696e2d7777772e616d617a6f6e2e636f6d82166f726967696e322d7777772e616d617a6f6e2e636f6d82216275636b6579652d72657461696c2d776562736974652e616d617a6f6e2e636f6d8212687564646c65732e616d617a6f6e2e636f6d8209616d617a6f6e2e6465820d7777772e616d617a6f6e2e646582146f726967696e2d7777772e616d617a6f6e2e6465820c616d617a6f6e2e636f2e6a708209616d617a6f6e2e6a70820d7777772e616d617a6f6e2e6a7082107777772e616d617a6f6e2e636f2e6a7082176f726967696e2d7777772e616d617a6f6e2e636f2e6a7082102a2e61612e7065672e61327a2e636f6d82102a2e61622e7065672e61327a2e636f6d82102a2e61632e7065672e61327a2e636f6d82186f726967696e2d7777772e616d617a6f6e2e636f6d2e617582117777772e616d617a6f6e2e636f6d2e617582102a2e627a2e7065672e61327a2e636f6d820d616d617a6f6e2e636f6d2e617582186f726967696e322d7777772e616d617a6f6e2e636f2e6a70300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b0601050507030230770603551d1f0470306e3035a033a031862f687474703a2f2f63726c332e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e63726c3035a033a031862f687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e63726c303e0603551d20043730353033060667810c0102013029302706082b06010505070201161b687474703a2f2f7777772e64696769636572742e636f6d2f435053307406082b0601050507010104683066302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d303e06082b060105050730028632687474703a2f2f636163657274732e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e637274300c0603551d130101ff040230003082017e060a2b06010401d6790204020482016e0482016a01680076002979bef09e393921f056739f63a577e5be577d9c600af8f94d5d265c255dc7840000017c538a58bb0000040300473045022100e223bc483fa330e18e1895d1f6da61cf37a0f6f6234f2677f6d4ee785f42e7e002203203a09a260a546184237213ea892dc3cc720840bd05224a2111c96ea8f255a000770051a3b0f5fd01799c566db837788f0ca47acc1b27cbf79e88429a0dfed48b05e50000017c538a58e40000040300483046022100903b411eb6499360a14d1209f5da3d4ae25b816b3e555465b48b97bb3eab75b802210083f882214113a59130f0802f4060b88203704609bdee999add483c161269d0a800750041c8cab1df22464a10c6a13a0942875e4e318b1b03ebeb4bc768f090629606f60000017c538a589f00000403004630440220572e57e12c75fa94c61495e3ea5217923f1150558a7fe43a969305c49394771c02203b21d470c8dd3dbfd6e75ca2765ec30319f7bd447c16c15a1703f349331e40dc300d06092a864886f70d01010b05000382010100c8b265b86e80159e5f560c5d4b9ef849977b7489c4ba69d05109adf83fef6d46f835f88ee1a45d3c6906a2d187a6d156f70c588ef6254a6b566e7b39bfed029a989769d5cb34f599b4d8c98054775932db1f306d0fe0bcc8bd4043f2f690e93d3d5a6ae7495e0fbf9d6629aeae35f793b09bc5a22d8c79ca02add592520d3362cb57ffd9aa74310651de5224df9d48ca47fd05443338cebdb8ec75f4047e42525df04f9fdeea606a91790a56f97ecf355f42391e2f8d0a8c9263438f8dd20b0f4bcfab04f1871155c518fb656c8ea9c92dd6a36ad391a203c1dfa2edc91542f88528fa287b84957e9fa45f8c55bbd04423886555adb2eea73f98c79c0695d3f9
RawTBSCertificate 308207a9a00302010202100e4239ab85e2e6a27c52c6de9b9078d9300d06092a864886f70d01010b05003044310b300906035504061302555331153013060355040a130c446967694365727420496e63311e301c06035504031315446967694365727420476c6f62616c204341204732301e170d3231313030363030303030305a170d3232303931393233353935395a30183116301406035504030c0d2a2e7065672e61327a2e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100bfefee33c3647bea4353a956a1900b5dfacdc07ebf077fbc1447cd7b00fa98df2e9edcc2307f1f3d4e466f5fe8750592ec68813e8c2853ab26163e05d240f7421e0e5290156dc612d9a7799d5067c2687c4e6fd4dc33b7e05660c6d8f3deac4154aaf5af260edfed7f1f6c41ba2b7c5b54d277fb3eda3a2ea7300042ad339fc077ea4a62d7875821a660070d16b901dac9b4e50b4724a3dc76b78dd15f1359811c6a63287e23e30ad7d64e0198023c0a28257c9089422885374ec3c8270d8e60238ce11f2cefba189f481788235580e8c7c6762295f8ad11f4b2ebd281d857717bc824280cddbd6558178f8519bbae08c48427b8744de97da8b51dea8148c0a10203010001a38205d9308205d5301f0603551d23041830168014246e2b2dd06a925151256901aa9a47a689e74020301d0603551d0e041604149545143e3a401e9516f082ac457382586d9bf074308202a30603551d110482029a30820296820c616d617a6f6e2e636f2e756b82137565646174612e616d617a6f6e2e636f2e756b82107777772e616d617a6f6e2e636f2e756b82176f726967696e2d7777772e616d617a6f6e2e636f2e756b820d2a2e7065672e61327a2e636f6d820a616d617a6f6e2e636f6d8208616d7a6e2e636f6d82117565646174612e616d617a6f6e2e636f6d820d75732e616d617a6f6e2e636f6d820e7777772e616d617a6f6e2e636f6d820c7777772e616d7a6e2e636f6d8214636f72706f726174652e616d617a6f6e2e636f6d8211627579626f782e616d617a6f6e2e636f6d82116970686f6e652e616d617a6f6e2e636f6d820d79702e616d617a6f6e2e636f6d820f686f6d652e616d617a6f6e2e636f6d82156f726967696e2d7777772e616d617a6f6e2e636f6d82166f726967696e322d7777772e616d617a6f6e2e636f6d82216275636b6579652d72657461696c2d776562736974652e616d617a6f6e2e636f6d8212687564646c65732e616d617a6f6e2e636f6d8209616d617a6f6e2e6465820d7777772e616d617a6f6e2e646582146f726967696e2d7777772e616d617a6f6e2e6465820c616d617a6f6e2e636f2e6a708209616d617a6f6e2e6a70820d7777772e616d617a6f6e2e6a7082107777772e616d617a6f6e2e636f2e6a7082176f726967696e2d7777772e616d617a6f6e2e636f2e6a7082102a2e61612e7065672e61327a2e636f6d82102a2e61622e7065672e61327a2e636f6d82102a2e61632e7065672e61327a2e636f6d82186f726967696e2d7777772e616d617a6f6e2e636f6d2e617582117777772e616d617a6f6e2e636f6d2e617582102a2e627a2e7065672e61327a2e636f6d820d616d617a6f6e2e636f6d2e617582186f726967696e322d7777772e616d617a6f6e2e636f2e6a70300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b0601050507030230770603551d1f0470306e3035a033a031862f687474703a2f2f63726c332e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e63726c3035a033a031862f687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e63726c303e0603551d20043730353033060667810c0102013029302706082b06010505070201161b687474703a2f2f7777772e64696769636572742e636f6d2f435053307406082b0601050507010104683066302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d303e06082b060105050730028632687474703a2f2f636163657274732e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e637274300c0603551d130101ff040230003082017e060a2b06010401d6790204020482016e0482016a01680076002979bef09e393921f056739f63a577e5be577d9c600af8f94d5d265c255dc7840000017c538a58bb0000040300473045022100e223bc483fa330e18e1895d1f6da61cf37a0f6f6234f2677f6d4ee785f42e7e002203203a09a260a546184237213ea892dc3cc720840bd05224a2111c96ea8f255a000770051a3b0f5fd01799c566db837788f0ca47acc1b27cbf79e88429a0dfed48b05e50000017c538a58e40000040300483046022100903b411eb6499360a14d1209f5da3d4ae25b816b3e555465b48b97bb3eab75b802210083f882214113a59130f0802f4060b88203704609bdee999add483c161269d0a800750041c8cab1df22464a10c6a13a0942875e4e318b1b03ebeb4bc768f090629606f60000017c538a589f00000403004630440220572e57e12c75fa94c61495e3ea5217923f1150558a7fe43a969305c49394771c02203b21d470c8dd3dbfd6e75ca2765ec30319f7bd447c16c15a1703f349331e40dc
RawSubjectPublicKeyInfo 30820122300d06092a864886f70d01010105000382010f003082010a0282010100bfefee33c3647bea4353a956a1900b5dfacdc07ebf077fbc1447cd7b00fa98df2e9edcc2307f1f3d4e466f5fe8750592ec68813e8c2853ab26163e05d240f7421e0e5290156dc612d9a7799d5067c2687c4e6fd4dc33b7e05660c6d8f3deac4154aaf5af260edfed7f1f6c41ba2b7c5b54d277fb3eda3a2ea7300042ad339fc077ea4a62d7875821a660070d16b901dac9b4e50b4724a3dc76b78dd15f1359811c6a63287e23e30ad7d64e0198023c0a28257c9089422885374ec3c8270d8e60238ce11f2cefba189f481788235580e8c7c6762295f8ad11f4b2ebd281d857717bc824280cddbd6558178f8519bbae08c48427b8744de97da8b51dea8148c0a10203010001
RawSubject 30183116301406035504030c0d2a2e7065672e61327a2e636f6d
RawIssuer 3044310b300906035504061302555331153013060355040a130c446967694365727420496e63311e301c06035504031315446967694365727420476c6f62616c204341204732
Signature c8b265b86e80159e5f560c5d4b9ef849977b7489c4ba69d05109adf83fef6d46f835f88ee1a45d3c6906a2d187a6d156f70c588ef6254a6b566e7b39bfed029a989769d5cb34f599b4d8c98054775932db1f306d0fe0bcc8bd4043f2f690e93d3d5a6ae7495e0fbf9d6629aeae35f793b09bc5a22d8c79ca02add592520d3362cb57ffd9aa74310651de5224df9d48ca47fd05443338cebdb8ec75f4047e42525df04f9fdeea606a91790a56f97ecf355f42391e2f8d0a8c9263438f8dd20b0f4bcfab04f1871155c518fb656c8ea9c92dd6a36ad391a203c1dfa2edc91542f88528fa287b84957e9fa45f8c55bbd04423886555adb2eea73f98c79c0695d3f9
SignatureAlgorithm SHA256-RSA
PublicKeyAlgorithm RSA
PublicKey N=bfefee33c3647bea4353a956a1900b5dfacdc07ebf077fbc1447cd7b00fa98df2e9edcc2307f1f3d4e466f5fe8750592ec68813e8c2853ab26163e05d240f7421e0e5290156dc612d9a7799d5067c2687c4e6fd4dc33b7e05660c6d8f3deac4154aaf5af260edfed7f1f6c41ba2b7c5b54d277fb3eda3a2ea7300042ad339fc077ea4a62d7875821a660070d16b901dac9b4e50b4724a3dc76b78dd15f1359811c6a63287e23e30ad7d64e0198023c0a28257c9089422885374ec3c8270d8e60238ce11f2cefba189f481788235580e8c7c6762295f8ad11f4b2ebd281d857717bc824280cddbd6558178f8519bbae08c48427b8744de97da8b51dea8148c0a1
PublicKey E=10001
Version 3
SerialNumber 18953053220451131611646046652406462681 (e4239ab85e2e6a27c52c6de9b9078d9)
Issuer CN=DigiCert Global CA G2,O=DigiCert Inc,C=US
Subject CN=*.peg.a2z.com
NotBefore 2021-10-06 00:00:00 +0000 UTC
NotAfter 2022-09-19 23:59:59 +0000 UTC
KeyUsage 5
IsCA false
SubjectKeyId 9545143e3a401e9516f082ac457382586d9bf074
AuthorityKeyId 246e2b2dd06a925151256901aa9a47a689e74020
DNSNames [amazon.co.uk uedata.amazon.co.uk www.amazon.co.uk origin-www.amazon.co.uk *.peg.a2z.com amazon.com amzn.com uedata.amazon.com us.amazon.com www.amazon.com www.amzn.com corporate.amazon.com buybox.amazon.com iphone.amazon.com yp.amazon.com home.amazon.com origin-www.amazon.com origin2-www.amazon.com buckeye-retail-website.amazon.com huddles.amazon.com amazon.de www.amazon.de origin-www.amazon.de amazon.co.jp amazon.jp www.amazon.jp www.amazon.co.jp origin-www.amazon.co.jp *.aa.peg.a2z.com *.ab.peg.a2z.com *.ac.peg.a2z.com origin-www.amazon.com.au www.amazon.com.au *.bz.peg.a2z.com amazon.com.au origin2-www.amazon.co.jp]
EmailAddresses []
IPAddresses []
URIs []
Extensions 0 Id=2.5.29.35 (Authority Key Id) Critical=false Value=30168014246e2b2dd06a925151256901aa9a47a689e74020
Extensions 1 Id=2.5.29.14 (Subject Key Id) Critical=false Value=04149545143e3a401e9516f082ac457382586d9bf074
Extensions 2 Id=2.5.29.17 (Subject Alt Name) Critical=false Value=30820296820c616d617a6f6e2e636f2e756b82137565646174612e616d617a6f6e2e636f2e756b82107777772e616d617a6f6e2e636f2e756b82176f726967696e2d7777772e616d617a6f6e2e636f2e756b820d2a2e7065672e61327a2e636f6d820a616d617a6f6e2e636f6d8208616d7a6e2e636f6d82117565646174612e616d617a6f6e2e636f6d820d75732e616d617a6f6e2e636f6d820e7777772e616d617a6f6e2e636f6d820c7777772e616d7a6e2e636f6d8214636f72706f726174652e616d617a6f6e2e636f6d8211627579626f782e616d617a6f6e2e636f6d82116970686f6e652e616d617a6f6e2e636f6d820d79702e616d617a6f6e2e636f6d820f686f6d652e616d617a6f6e2e636f6d82156f726967696e2d7777772e616d617a6f6e2e636f6d82166f726967696e322d7777772e616d617a6f6e2e636f6d82216275636b6579652d72657461696c2d776562736974652e616d617a6f6e2e636f6d8212687564646c65732e616d617a6f6e2e636f6d8209616d617a6f6e2e6465820d7777772e616d617a6f6e2e646582146f726967696e2d7777772e616d617a6f6e2e6465820c616d617a6f6e2e636f2e6a708209616d617a6f6e2e6a70820d7777772e616d617a6f6e2e6a7082107777772e616d617a6f6e2e636f2e6a7082176f726967696e2d7777772e616d617a6f6e2e636f2e6a7082102a2e61612e7065672e61327a2e636f6d82102a2e61622e7065672e61327a2e636f6d82102a2e61632e7065672e61327a2e636f6d82186f726967696e2d7777772e616d617a6f6e2e636f6d2e617582117777772e616d617a6f6e2e636f6d2e617582102a2e627a2e7065672e61327a2e636f6d820d616d617a6f6e2e636f6d2e617582186f726967696e322d7777772e616d617a6f6e2e636f2e6a70
Extensions 3 Id=2.5.29.15 (Key Usage) Critical=true Value=030205a0
Extensions 4 Id=2.5.29.37 (Extended Key Usage) Critical=false Value=301406082b0601050507030106082b06010505070302
Extensions 5 Id=2.5.29.31 (CRL Distribution Points) Critical=false Value=306e3035a033a031862f687474703a2f2f63726c332e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e63726c3035a033a031862f687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e63726c
Extensions 6 Id=2.5.29.32 (Certificate Policies) Critical=false Value=30353033060667810c0102013029302706082b06010505070201161b687474703a2f2f7777772e64696769636572742e636f6d2f435053
Extensions 7 Id=1.3.6.1.5.5.7.1.1 (Authority Info Access) Critical=false Value=3066302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d303e06082b060105050730028632687474703a2f2f636163657274732e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e637274
Extensions 8 Id=2.5.29.19 (Basic Constraints) Critical=true Value=3000
Extensions 9 Id=1.3.6.1.4.1.11129.2.4.2 (Signed Certificate Timestamp) Critical=false Value=0482016a01680076002979bef09e393921f056739f63a577e5be577d9c600af8f94d5d265c255dc7840000017c538a58bb0000040300473045022100e223bc483fa330e18e1895d1f6da61cf37a0f6f6234f2677f6d4ee785f42e7e002203203a09a260a546184237213ea892dc3cc720840bd05224a2111c96ea8f255a000770051a3b0f5fd01799c566db837788f0ca47acc1b27cbf79e88429a0dfed48b05e50000017c538a58e40000040300483046022100903b411eb6499360a14d1209f5da3d4ae25b816b3e555465b48b97bb3eab75b802210083f882214113a59130f0802f4060b88203704609bdee999add483c161269d0a800750041c8cab1df22464a10c6a13a0942875e4e318b1b03ebeb4bc768f090629606f60000017c538a589f00000403004630440220572e57e12c75fa94c61495e3ea5217923f1150558a7fe43a969305c49394771c02203b21d470c8dd3dbfd6e75ca2765ec30319f7bd447c16c15a1703f349331e40dc

Raw 3082048b30820373a00302010202100c8ee0c90d6a89158804061ee241f9af300d06092a864886f70d01010b05003061310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d3120301e06035504031317446967694365727420476c6f62616c20526f6f74204732301e170d3133303830313132303030305a170d3238303830313132303030305a3044310b300906035504061302555331153013060355040a130c446967694365727420496e63311e301c06035504031315446967694365727420476c6f62616c20434120473230820122300d06092a864886f70d01010105000382010f003082010a0282010100d3487cbef305865d5bd52f854e4be086ad15ac61cf5baf3e6a0a47fb9a7691600b8a6bcdcfdc577e60980be454d956ed21cc02b65a815f976aee022f2327b86dd4b0e70602780b1f5ca99936febbac1b05fa57cd81104067d6308b5835d49661bed08c7a979f1af922e6142fa9c6e8011fabf8260fac8e4d2c32391d819b8d1c65b21cdb61a8892f60e7ebc24a18c46f2ae9109209ed17d1002be67def0489144e33a1b20f97879fb3a0cd2fbc2cecb88368313d1fd54a9010190b8195d6297651f93676d0b7097a384ad76f8cbf137c39edbaae90fc95f77b7809365e74931e25f0ffd4adae686bc6ff0fd535f1556e4849f8f8b8ef88f8f15e1177aadf02b30203010001a382015a3082015630120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020186303406082b0601050507010104283026302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d307b0603551d1f047430723037a035a0338631687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274476c6f62616c526f6f7447322e63726c3037a035a0338631687474703a2f2f63726c332e64696769636572742e636f6d2f4469676943657274476c6f62616c526f6f7447322e63726c303d0603551d200436303430320604551d2000302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f435053301d0603551d0e04160414246e2b2dd06a925151256901aa9a47a689e74020301f0603551d230418301680144e2254201895e6e36ee60ffafab912ed06178f39300d06092a864886f70d01010b050003820101000b398491f997ebaa81af84e95a3892fce26c59bf36c845a7310311e106c0ac32c75a5529da4f4002f5a1deb0eddec0f8f6759d76b987fe41807acf5de300c65b02e69b7862c9dcb8629a77ed8908d74bc5fd43d5622327c404596d713f235bead9f2e724276ff49580db962ce4548bcfea19d97f5599517a0e2d183d785852bc6368570bdd44b3574a60e6c870705b87286ad73b4e524519af24069248111a8baeac181257ac03cbb8f4bdca260ea7c1dde333efc055300d95594e9c033606f8c08f14999c4d2a9ec1e17d3baf72a745ba1396294e19d01a9806f4379417ada318ba3eb0010c95d6293520357df51060e4f768621eec19e124f28711ace90880
RawTBSCertificate 30820373a00302010202100c8ee0c90d6a89158804061ee241f9af300d06092a864886f70d01010b05003061310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d3120301e06035504031317446967694365727420476c6f62616c20526f6f74204732301e170d3133303830313132303030305a170d3238303830313132303030305a3044310b300906035504061302555331153013060355040a130c446967694365727420496e63311e301c06035504031315446967694365727420476c6f62616c20434120473230820122300d06092a864886f70d01010105000382010f003082010a0282010100d3487cbef305865d5bd52f854e4be086ad15ac61cf5baf3e6a0a47fb9a7691600b8a6bcdcfdc577e60980be454d956ed21cc02b65a815f976aee022f2327b86dd4b0e70602780b1f5ca99936febbac1b05fa57cd81104067d6308b5835d49661bed08c7a979f1af922e6142fa9c6e8011fabf8260fac8e4d2c32391d819b8d1c65b21cdb61a8892f60e7ebc24a18c46f2ae9109209ed17d1002be67def0489144e33a1b20f97879fb3a0cd2fbc2cecb88368313d1fd54a9010190b8195d6297651f93676d0b7097a384ad76f8cbf137c39edbaae90fc95f77b7809365e74931e25f0ffd4adae686bc6ff0fd535f1556e4849f8f8b8ef88f8f15e1177aadf02b30203010001a382015a3082015630120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020186303406082b0601050507010104283026302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d307b0603551d1f047430723037a035a0338631687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274476c6f62616c526f6f7447322e63726c3037a035a0338631687474703a2f2f63726c332e64696769636572742e636f6d2f4469676943657274476c6f62616c526f6f7447322e63726c303d0603551d200436303430320604551d2000302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f435053301d0603551d0e04160414246e2b2dd06a925151256901aa9a47a689e74020301f0603551d230418301680144e2254201895e6e36ee60ffafab912ed06178f39
RawSubjectPublicKeyInfo 30820122300d06092a864886f70d01010105000382010f003082010a0282010100d3487cbef305865d5bd52f854e4be086ad15ac61cf5baf3e6a0a47fb9a7691600b8a6bcdcfdc577e60980be454d956ed21cc02b65a815f976aee022f2327b86dd4b0e70602780b1f5ca99936febbac1b05fa57cd81104067d6308b5835d49661bed08c7a979f1af922e6142fa9c6e8011fabf8260fac8e4d2c32391d819b8d1c65b21cdb61a8892f60e7ebc24a18c46f2ae9109209ed17d1002be67def0489144e33a1b20f97879fb3a0cd2fbc2cecb88368313d1fd54a9010190b8195d6297651f93676d0b7097a384ad76f8cbf137c39edbaae90fc95f77b7809365e74931e25f0ffd4adae686bc6ff0fd535f1556e4849f8f8b8ef88f8f15e1177aadf02b30203010001
RawSubject 3044310b300906035504061302555331153013060355040a130c446967694365727420496e63311e301c06035504031315446967694365727420476c6f62616c204341204732
RawIssuer 3061310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d3120301e06035504031317446967694365727420476c6f62616c20526f6f74204732
Signature 0b398491f997ebaa81af84e95a3892fce26c59bf36c845a7310311e106c0ac32c75a5529da4f4002f5a1deb0eddec0f8f6759d76b987fe41807acf5de300c65b02e69b7862c9dcb8629a77ed8908d74bc5fd43d5622327c404596d713f235bead9f2e724276ff49580db962ce4548bcfea19d97f5599517a0e2d183d785852bc6368570bdd44b3574a60e6c870705b87286ad73b4e524519af24069248111a8baeac181257ac03cbb8f4bdca260ea7c1dde333efc055300d95594e9c033606f8c08f14999c4d2a9ec1e17d3baf72a745ba1396294e19d01a9806f4379417ada318ba3eb0010c95d6293520357df51060e4f768621eec19e124f28711ace90880
SignatureAlgorithm SHA256-RSA
PublicKeyAlgorithm RSA
PublicKey N=d3487cbef305865d5bd52f854e4be086ad15ac61cf5baf3e6a0a47fb9a7691600b8a6bcdcfdc577e60980be454d956ed21cc02b65a815f976aee022f2327b86dd4b0e70602780b1f5ca99936febbac1b05fa57cd81104067d6308b5835d49661bed08c7a979f1af922e6142fa9c6e8011fabf8260fac8e4d2c32391d819b8d1c65b21cdb61a8892f60e7ebc24a18c46f2ae9109209ed17d1002be67def0489144e33a1b20f97879fb3a0cd2fbc2cecb88368313d1fd54a9010190b8195d6297651f93676d0b7097a384ad76f8cbf137c39edbaae90fc95f77b7809365e74931e25f0ffd4adae686bc6ff0fd535f1556e4849f8f8b8ef88f8f15e1177aadf02b3
PublicKey E=10001
Version 3
SerialNumber 16692601292094917965351216382751144367 (c8ee0c90d6a89158804061ee241f9af)
Issuer CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US
Subject CN=DigiCert Global CA G2,O=DigiCert Inc,C=US
NotBefore 2013-08-01 12:00:00 +0000 UTC
NotAfter 2028-08-01 12:00:00 +0000 UTC
KeyUsage 97
IsCA true
SubjectKeyId 246e2b2dd06a925151256901aa9a47a689e74020
AuthorityKeyId 4e2254201895e6e36ee60ffafab912ed06178f39
DNSNames []
EmailAddresses []
IPAddresses []
URIs []
Extensions 0 Id=2.5.29.19 (Basic Constraints) Critical=true Value=30060101ff020100
Extensions 1 Id=2.5.29.15 (Key Usage) Critical=true Value=03020186
Extensions 2 Id=1.3.6.1.5.5.7.1.1 (Authority Info Access) Critical=false Value=3026302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d
Extensions 3 Id=2.5.29.31 (CRL Distribution Points) Critical=false Value=30723037a035a0338631687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274476c6f62616c526f6f7447322e63726c3037a035a0338631687474703a2f2f63726c332e64696769636572742e636f6d2f4469676943657274476c6f62616c526f6f7447322e63726c
Extensions 4 Id=2.5.29.32 (Certificate Policies) Critical=false Value=303430320604551d2000302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f435053
Extensions 5 Id=2.5.29.14 (Subject Key Id) Critical=false Value=0414246e2b2dd06a925151256901aa9a47a689e74020
Extensions 6 Id=2.5.29.35 (Authority Key Id) Critical=false Value=301680144e2254201895e6e36ee60ffafab912ed06178f39

Raw 308204df308203c7a003020102021063180d38fb809778a9d035a31618f840300d06092a864886f70d01010b05003081ca310b300906035504061302555331173015060355040a130e566572695369676e2c20496e632e311f301d060355040b1316566572695369676e205472757374204e6574776f726b313a3038060355040b1331286329203230303620566572695369676e2c20496e632e202d20466f7220617574686f72697a656420757365206f6e6c79314530430603550403133c566572695369676e20436c6173732033205075626c6963205072696d6172792043657274696669636174696f6e20417574686f72697479202d204735301e170d3137313130363030303030305a170d3232313130353233353935395a3061310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d3120301e06035504031317446967694365727420476c6f62616c20526f6f7420473230820122300d06092a864886f70d01010105000382010f003082010a0282010100bb37cd34dc7b6bc9b26890ad4a75ff46ba210a088df51954c9fb88dbf3aef23a89913c7ae6ab061a6bcfac2de85e092444ba629a7ed6a3a87ee054752005ac50b79c631a6c30dcda1f19b1d71edefdd7e0cb948337aeec1f434edd7b2cd2bd2ea52fe4a9b8ad3ad499a4b625e99b6b00609260ff4f214918f76790ab61069c8ff2bae9b4e992326bb5f357e85d1bcd8c1dab95049549f3352d96e3496ddd77e3fb494bb4ac5507a98f95b3b423bb4c6d45f0f6a9b29530b4fd4c558c274a57147c829dcd7392d3164a060c8c50d18f1e09be17a1e621cafd83e510bc83a50ac46728f67314143d4676c387148921344daf0f450ca649a1babb9cc5b1338329850203010001a382012730820123301d0603551d0e041604144e2254201895e6e36ee60ffafab912ed06178f39300f0603551d130101ff040530030101ff305f0603551d200458305630540604551d2000304c302306082b06010505070201161768747470733a2f2f642e73796d63622e636f6d2f637073302506082b0601050507020230190c1768747470733a2f2f642e73796d63622e636f6d2f727061302f0603551d1f042830263024a022a020861e687474703a2f2f732e73796d63622e636f6d2f706361332d67352e63726c300e0603551d0f0101ff040403020186302e06082b0601050507010104223020301e06082b060105050730018612687474703a2f2f732e73796d63642e636f6d301f0603551d230418301680147fd365a7c2ddecbbf03009f34339fa02af333133300d06092a864886f70d01010b0500038201010050ddd3562925018a9ea7e57d4db9af1b8ca2d22735e59deb1c6af3c408ca45065208287da673a98bd97affc24488043aeca803b7b01726a0937e9fc577d0ee497a5aed1001584b24435dfbbbf199479fa92f579fe33d414408433f85d374c7c59d2e91a324ca9fb34106e6a1e3f946b1a6e7160f8e39c1e6b8ce52bb85447e300f1fab461dd4710a8f873c4dc81a4081cc6b8287af8e3c710ebd7b708f10246144d83e440293d88ed295a5732ef681ffccb29b6a0c084b28aa2453f1d6d7837e5a2846269b39f73bf9a707b6c651dfc452b9087fb1556a681865dd5f4b341e835707a9fd236ba787a6fab66d397e7161476aaffce0a9477b9461d02b26a59ce7
RawTBSCertificate 308203c7a003020102021063180d38fb809778a9d035a31618f840300d06092a864886f70d01010b05003081ca310b300906035504061302555331173015060355040a130e566572695369676e2c20496e632e311f301d060355040b1316566572695369676e205472757374204e6574776f726b313a3038060355040b1331286329203230303620566572695369676e2c20496e632e202d20466f7220617574686f72697a656420757365206f6e6c79314530430603550403133c566572695369676e20436c6173732033205075626c6963205072696d6172792043657274696669636174696f6e20417574686f72697479202d204735301e170d3137313130363030303030305a170d3232313130353233353935395a3061310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d3120301e06035504031317446967694365727420476c6f62616c20526f6f7420473230820122300d06092a864886f70d01010105000382010f003082010a0282010100bb37cd34dc7b6bc9b26890ad4a75ff46ba210a088df51954c9fb88dbf3aef23a89913c7ae6ab061a6bcfac2de85e092444ba629a7ed6a3a87ee054752005ac50b79c631a6c30dcda1f19b1d71edefdd7e0cb948337aeec1f434edd7b2cd2bd2ea52fe4a9b8ad3ad499a4b625e99b6b00609260ff4f214918f76790ab61069c8ff2bae9b4e992326bb5f357e85d1bcd8c1dab95049549f3352d96e3496ddd77e3fb494bb4ac5507a98f95b3b423bb4c6d45f0f6a9b29530b4fd4c558c274a57147c829dcd7392d3164a060c8c50d18f1e09be17a1e621cafd83e510bc83a50ac46728f67314143d4676c387148921344daf0f450ca649a1babb9cc5b1338329850203010001a382012730820123301d0603551d0e041604144e2254201895e6e36ee60ffafab912ed06178f39300f0603551d130101ff040530030101ff305f0603551d200458305630540604551d2000304c302306082b06010505070201161768747470733a2f2f642e73796d63622e636f6d2f637073302506082b0601050507020230190c1768747470733a2f2f642e73796d63622e636f6d2f727061302f0603551d1f042830263024a022a020861e687474703a2f2f732e73796d63622e636f6d2f706361332d67352e63726c300e0603551d0f0101ff040403020186302e06082b0601050507010104223020301e06082b060105050730018612687474703a2f2f732e73796d63642e636f6d301f0603551d230418301680147fd365a7c2ddecbbf03009f34339fa02af333133
RawSubjectPublicKeyInfo 30820122300d06092a864886f70d01010105000382010f003082010a0282010100bb37cd34dc7b6bc9b26890ad4a75ff46ba210a088df51954c9fb88dbf3aef23a89913c7ae6ab061a6bcfac2de85e092444ba629a7ed6a3a87ee054752005ac50b79c631a6c30dcda1f19b1d71edefdd7e0cb948337aeec1f434edd7b2cd2bd2ea52fe4a9b8ad3ad499a4b625e99b6b00609260ff4f214918f76790ab61069c8ff2bae9b4e992326bb5f357e85d1bcd8c1dab95049549f3352d96e3496ddd77e3fb494bb4ac5507a98f95b3b423bb4c6d45f0f6a9b29530b4fd4c558c274a57147c829dcd7392d3164a060c8c50d18f1e09be17a1e621cafd83e510bc83a50ac46728f67314143d4676c387148921344daf0f450ca649a1babb9cc5b1338329850203010001
RawSubject 3061310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d3120301e06035504031317446967694365727420476c6f62616c20526f6f74204732
RawIssuer 3081ca310b300906035504061302555331173015060355040a130e566572695369676e2c20496e632e311f301d060355040b1316566572695369676e205472757374204e6574776f726b313a3038060355040b1331286329203230303620566572695369676e2c20496e632e202d20466f7220617574686f72697a656420757365206f6e6c79314530430603550403133c566572695369676e20436c6173732033205075626c6963205072696d6172792043657274696669636174696f6e20417574686f72697479202d204735
Signature 50ddd3562925018a9ea7e57d4db9af1b8ca2d22735e59deb1c6af3c408ca45065208287da673a98bd97affc24488043aeca803b7b01726a0937e9fc577d0ee497a5aed1001584b24435dfbbbf199479fa92f579fe33d414408433f85d374c7c59d2e91a324ca9fb34106e6a1e3f946b1a6e7160f8e39c1e6b8ce52bb85447e300f1fab461dd4710a8f873c4dc81a4081cc6b8287af8e3c710ebd7b708f10246144d83e440293d88ed295a5732ef681ffccb29b6a0c084b28aa2453f1d6d7837e5a2846269b39f73bf9a707b6c651dfc452b9087fb1556a681865dd5f4b341e835707a9fd236ba787a6fab66d397e7161476aaffce0a9477b9461d02b26a59ce7
SignatureAlgorithm SHA256-RSA
PublicKeyAlgorithm RSA
PublicKey N=bb37cd34dc7b6bc9b26890ad4a75ff46ba210a088df51954c9fb88dbf3aef23a89913c7ae6ab061a6bcfac2de85e092444ba629a7ed6a3a87ee054752005ac50b79c631a6c30dcda1f19b1d71edefdd7e0cb948337aeec1f434edd7b2cd2bd2ea52fe4a9b8ad3ad499a4b625e99b6b00609260ff4f214918f76790ab61069c8ff2bae9b4e992326bb5f357e85d1bcd8c1dab95049549f3352d96e3496ddd77e3fb494bb4ac5507a98f95b3b423bb4c6d45f0f6a9b29530b4fd4c558c274a57147c829dcd7392d3164a060c8c50d18f1e09be17a1e621cafd83e510bc83a50ac46728f67314143d4676c387148921344daf0f450ca649a1babb9cc5b133832985
PublicKey E=10001
Version 3
SerialNumber 131718454893249650824332873540371544128 (63180d38fb809778a9d035a31618f840)
Issuer CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU=VeriSign Trust Network+OU=(c) 2006 VeriSign\, Inc. - For authorized use only,O=VeriSign\, Inc.,C=US
Subject CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US
NotBefore 2017-11-06 00:00:00 +0000 UTC
NotAfter 2022-11-05 23:59:59 +0000 UTC
KeyUsage 97
IsCA true
SubjectKeyId 4e2254201895e6e36ee60ffafab912ed06178f39
AuthorityKeyId 7fd365a7c2ddecbbf03009f34339fa02af333133
DNSNames []
EmailAddresses []
IPAddresses []
URIs []
Extensions 0 Id=2.5.29.14 (Subject Key Id) Critical=false Value=04144e2254201895e6e36ee60ffafab912ed06178f39
Extensions 1 Id=2.5.29.19 (Basic Constraints) Critical=true Value=30030101ff
Extensions 2 Id=2.5.29.32 (Certificate Policies) Critical=false Value=305630540604551d2000304c302306082b06010505070201161768747470733a2f2f642e73796d63622e636f6d2f637073302506082b0601050507020230190c1768747470733a2f2f642e73796d63622e636f6d2f727061
Extensions 3 Id=2.5.29.31 (CRL Distribution Points) Critical=false Value=30263024a022a020861e687474703a2f2f732e73796d63622e636f6d2f706361332d67352e63726c
Extensions 4 Id=2.5.29.15 (Key Usage) Critical=true Value=03020186
Extensions 5 Id=1.3.6.1.5.5.7.1.1 (Authority Info Access) Critical=false Value=3020301e06082b060105050730018612687474703a2f2f732e73796d63642e636f6d
Extensions 6 Id=2.5.29.35 (Authority Key Id) Critical=false Value=301680147fd365a7c2ddecbbf03009f34339fa02af333133

図7: pemdump による amazon.pem の表示

今回は3つの証明書を内部に含むので、空行で証明書の区切りを示した。その中から特定の1つだけが欲しい場合には

pemdump amazon.pem n
のように n (= 1,2,...) に証明書番号を書く仕様にした。

さて図4の frank4dd-cacert.pem の場合には
IssuerSubject は同じ、IsCA trueKeyUsage 0 であったが、amazon.pem の場合には n=1

となる。これは amazon.pem に含まれる最初の証明書の情報で、残りの証明書は証明者に関する情報と公開鍵を含む。いわゆる公開鍵の鎖(certificate chain)である。

https://www.trustss.co.jp/smnSignature350.html
によれば

KeyUsage は、0 は電子署名、5 は電子証明書の検証
となっている。

証明書の検証(1)

ここでは証明書の中に含まれている公開鍵が正しいと仮定して、署名を検証する。(実はこの仮定が成立するか否かが「証明書」の中心問題なのである)

pemdump.go に戻ると、署名は
署名は RawTBSCertificate の hash 値 H に対して行われたはずである。従って署名 S を公開鍵を使って元に戻す、すなわち公開鍵の E,N を使って

S**E mod N
を計算すれば、H が得られるはずである。と簡単に考えていたが... そんなに単純ではない。

例えば frank4dd-cacert.pem について言えば、H,N,E,S は以下に示す値になっている。(非負整数の16進数表記)

x509.SignatureAlgorithm
H=d628dc3fc5b3e6747c1091d78a6ddff1fe48a6db
C=30820325a003020102020900c6c70409bc225ba0300d06092a864886f70d010105050030819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d301e170d3037313230373130323134365a170d3137313230343130323134365a30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b0203010001a382010430820100301d0603551d0e0416041462f37bed06d4b1d59c7f48e5efc5c91561fdd9113081d00603551d230481c83081c5801462f37bed06d4b1d59c7f48e5efc5c91561fdd911a181a1a4819e30819b310b3009060355040613024a50310e300c06035504081305546f6b796f3110300e060355040713074368756f2d6b753111300f060355040a13084672616e6b34444431183016060355040b130f5765624365727420537570706f7274311830160603550403130f4672616e6b344444205765622043413123302106092a864886f70d0109011614737570706f7274406672616e6b3464642e636f6d820900c6c70409bc225ba0300c0603551d13040530030101ff
N=bbafbc8f25d5e60cbdbff8bda2a20c50acb30bfb5d04c0063d9494421c63ea489f227fbb5eaa75e016be8c004882c1370bbe4e21d54c4bac35e6c68a1e80d835cf1fce3836dc73ef927c508699f9708ffc232e9611c0f82ec7bfd0220ad4ab3b23d87b5d44577e58f543e003ad63d827c6335716955ed739a0026fd414b74c7b
E=10001
S=ba2c2e91ddb85398df4c0a4b6590df64734608746563652d7587910626cd31cda24c182f2d3019f22acc3d68bcb3230ee3cc0b73019903e0f3385df81636b2046181d1019985938b0ef57992cb988fde7506eed73eab39725bf047a0b9b24d9184dcbb1b0a2e28c87c90e72b69e8a8fb74de9b8912c071a2c375e173c484810e
D=0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414d628dc3fc5b3e6747c1091d78a6ddff1fe48a6db

図8: pemverify による frank4dd-cacert.pem の output

最後の D

S**E mod N
の値である。見て分かる通り、H に一致していない。しかし得られた文字列の中に H
d628dc3fc5b3e6747c1091d78a6ddff1fe48a6db
が含まれている。従って確かに decrypto できたのである。よく解らないのは
0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414
の部分である。これは何だ? ⇒ Hash Prefix を見よ

この結果を出したプログラムは
pemverify.go にある。使い方は

pemverify amazon.pem
のようにすればよい。amazon.pem に対する結果を次に示す:
SHA256WithRSA
H=787c8b32c43d57cf862530a5a0af775b55cc98bf5e04edaf65753a68b3f3ea05
C=308207a9a00302010202100e4239ab85e2e6a27c52c6de9b9078d9300d06092a864886f70d01010b05003044310b300906035504061302555331153013060355040a130c446967694365727420496e63311e301c06035504031315446967694365727420476c6f62616c204341204732301e170d3231313030363030303030305a170d3232303931393233353935395a30183116301406035504030c0d2a2e7065672e61327a2e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100bfefee33c3647bea4353a956a1900b5dfacdc07ebf077fbc1447cd7b00fa98df2e9edcc2307f1f3d4e466f5fe8750592ec68813e8c2853ab26163e05d240f7421e0e5290156dc612d9a7799d5067c2687c4e6fd4dc33b7e05660c6d8f3deac4154aaf5af260edfed7f1f6c41ba2b7c5b54d277fb3eda3a2ea7300042ad339fc077ea4a62d7875821a660070d16b901dac9b4e50b4724a3dc76b78dd15f1359811c6a63287e23e30ad7d64e0198023c0a28257c9089422885374ec3c8270d8e60238ce11f2cefba189f481788235580e8c7c6762295f8ad11f4b2ebd281d857717bc824280cddbd6558178f8519bbae08c48427b8744de97da8b51dea8148c0a10203010001a38205d9308205d5301f0603551d23041830168014246e2b2dd06a925151256901aa9a47a689e74020301d0603551d0e041604149545143e3a401e9516f082ac457382586d9bf074308202a30603551d110482029a30820296820c616d617a6f6e2e636f2e756b82137565646174612e616d617a6f6e2e636f2e756b82107777772e616d617a6f6e2e636f2e756b82176f726967696e2d7777772e616d617a6f6e2e636f2e756b820d2a2e7065672e61327a2e636f6d820a616d617a6f6e2e636f6d8208616d7a6e2e636f6d82117565646174612e616d617a6f6e2e636f6d820d75732e616d617a6f6e2e636f6d820e7777772e616d617a6f6e2e636f6d820c7777772e616d7a6e2e636f6d8214636f72706f726174652e616d617a6f6e2e636f6d8211627579626f782e616d617a6f6e2e636f6d82116970686f6e652e616d617a6f6e2e636f6d820d79702e616d617a6f6e2e636f6d820f686f6d652e616d617a6f6e2e636f6d82156f726967696e2d7777772e616d617a6f6e2e636f6d82166f726967696e322d7777772e616d617a6f6e2e636f6d82216275636b6579652d72657461696c2d776562736974652e616d617a6f6e2e636f6d8212687564646c65732e616d617a6f6e2e636f6d8209616d617a6f6e2e6465820d7777772e616d617a6f6e2e646582146f726967696e2d7777772e616d617a6f6e2e6465820c616d617a6f6e2e636f2e6a708209616d617a6f6e2e6a70820d7777772e616d617a6f6e2e6a7082107777772e616d617a6f6e2e636f2e6a7082176f726967696e2d7777772e616d617a6f6e2e636f2e6a7082102a2e61612e7065672e61327a2e636f6d82102a2e61622e7065672e61327a2e636f6d82102a2e61632e7065672e61327a2e636f6d82186f726967696e2d7777772e616d617a6f6e2e636f6d2e617582117777772e616d617a6f6e2e636f6d2e617582102a2e627a2e7065672e61327a2e636f6d820d616d617a6f6e2e636f6d2e617582186f726967696e322d7777772e616d617a6f6e2e636f2e6a70300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b0601050507030230770603551d1f0470306e3035a033a031862f687474703a2f2f63726c332e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e63726c3035a033a031862f687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e63726c303e0603551d20043730353033060667810c0102013029302706082b06010505070201161b687474703a2f2f7777772e64696769636572742e636f6d2f435053307406082b0601050507010104683066302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d303e06082b060105050730028632687474703a2f2f636163657274732e64696769636572742e636f6d2f4469676943657274476c6f62616c434147322e637274300c0603551d130101ff040230003082017e060a2b06010401d6790204020482016e0482016a01680076002979bef09e393921f056739f63a577e5be577d9c600af8f94d5d265c255dc7840000017c538a58bb0000040300473045022100e223bc483fa330e18e1895d1f6da61cf37a0f6f6234f2677f6d4ee785f42e7e002203203a09a260a546184237213ea892dc3cc720840bd05224a2111c96ea8f255a000770051a3b0f5fd01799c566db837788f0ca47acc1b27cbf79e88429a0dfed48b05e50000017c538a58e40000040300483046022100903b411eb6499360a14d1209f5da3d4ae25b816b3e555465b48b97bb3eab75b802210083f882214113a59130f0802f4060b88203704609bdee999add483c161269d0a800750041c8cab1df22464a10c6a13a0942875e4e318b1b03ebeb4bc768f090629606f60000017c538a589f00000403004630440220572e57e12c75fa94c61495e3ea5217923f1150558a7fe43a969305c49394771c02203b21d470c8dd3dbfd6e75ca2765ec30319f7bd447c16c15a1703f349331e40dc
N=d3487cbef305865d5bd52f854e4be086ad15ac61cf5baf3e6a0a47fb9a7691600b8a6bcdcfdc577e60980be454d956ed21cc02b65a815f976aee022f2327b86dd4b0e70602780b1f5ca99936febbac1b05fa57cd81104067d6308b5835d49661bed08c7a979f1af922e6142fa9c6e8011fabf8260fac8e4d2c32391d819b8d1c65b21cdb61a8892f60e7ebc24a18c46f2ae9109209ed17d1002be67def0489144e33a1b20f97879fb3a0cd2fbc2cecb88368313d1fd54a9010190b8195d6297651f93676d0b7097a384ad76f8cbf137c39edbaae90fc95f77b7809365e74931e25f0ffd4adae686bc6ff0fd535f1556e4849f8f8b8ef88f8f15e1177aadf02b3
E=10001
S=c8b265b86e80159e5f560c5d4b9ef849977b7489c4ba69d05109adf83fef6d46f835f88ee1a45d3c6906a2d187a6d156f70c588ef6254a6b566e7b39bfed029a989769d5cb34f599b4d8c98054775932db1f306d0fe0bcc8bd4043f2f690e93d3d5a6ae7495e0fbf9d6629aeae35f793b09bc5a22d8c79ca02add592520d3362cb57ffd9aa74310651de5224df9d48ca47fd05443338cebdb8ec75f4047e42525df04f9fdeea606a91790a56f97ecf355f42391e2f8d0a8c9263438f8dd20b0f4bcfab04f1871155c518fb656c8ea9c92dd6a36ad391a203c1dfa2edc91542f88528fa287b84957e9fa45f8c55bbd04423886555adb2eea73f98c79c0695d3f9
D=0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420787c8b32c43d57cf862530a5a0af775b55cc98bf5e04edaf65753a68b3f3ea05

SHA256WithRSA
H=f61e576877da9650294cccb5f96c75fcb71bda1bbc4646367c4ebeda89d7318f
C=30820373a00302010202100c8ee0c90d6a89158804061ee241f9af300d06092a864886f70d01010b05003061310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d3120301e06035504031317446967694365727420476c6f62616c20526f6f74204732301e170d3133303830313132303030305a170d3238303830313132303030305a3044310b300906035504061302555331153013060355040a130c446967694365727420496e63311e301c06035504031315446967694365727420476c6f62616c20434120473230820122300d06092a864886f70d01010105000382010f003082010a0282010100d3487cbef305865d5bd52f854e4be086ad15ac61cf5baf3e6a0a47fb9a7691600b8a6bcdcfdc577e60980be454d956ed21cc02b65a815f976aee022f2327b86dd4b0e70602780b1f5ca99936febbac1b05fa57cd81104067d6308b5835d49661bed08c7a979f1af922e6142fa9c6e8011fabf8260fac8e4d2c32391d819b8d1c65b21cdb61a8892f60e7ebc24a18c46f2ae9109209ed17d1002be67def0489144e33a1b20f97879fb3a0cd2fbc2cecb88368313d1fd54a9010190b8195d6297651f93676d0b7097a384ad76f8cbf137c39edbaae90fc95f77b7809365e74931e25f0ffd4adae686bc6ff0fd535f1556e4849f8f8b8ef88f8f15e1177aadf02b30203010001a382015a3082015630120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020186303406082b0601050507010104283026302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d307b0603551d1f047430723037a035a0338631687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274476c6f62616c526f6f7447322e63726c3037a035a0338631687474703a2f2f63726c332e64696769636572742e636f6d2f4469676943657274476c6f62616c526f6f7447322e63726c303d0603551d200436303430320604551d2000302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f435053301d0603551d0e04160414246e2b2dd06a925151256901aa9a47a689e74020301f0603551d230418301680144e2254201895e6e36ee60ffafab912ed06178f39
N=bb37cd34dc7b6bc9b26890ad4a75ff46ba210a088df51954c9fb88dbf3aef23a89913c7ae6ab061a6bcfac2de85e092444ba629a7ed6a3a87ee054752005ac50b79c631a6c30dcda1f19b1d71edefdd7e0cb948337aeec1f434edd7b2cd2bd2ea52fe4a9b8ad3ad499a4b625e99b6b00609260ff4f214918f76790ab61069c8ff2bae9b4e992326bb5f357e85d1bcd8c1dab95049549f3352d96e3496ddd77e3fb494bb4ac5507a98f95b3b423bb4c6d45f0f6a9b29530b4fd4c558c274a57147c829dcd7392d3164a060c8c50d18f1e09be17a1e621cafd83e510bc83a50ac46728f67314143d4676c387148921344daf0f450ca649a1babb9cc5b133832985
E=10001
S=0b398491f997ebaa81af84e95a3892fce26c59bf36c845a7310311e106c0ac32c75a5529da4f4002f5a1deb0eddec0f8f6759d76b987fe41807acf5de300c65b02e69b7862c9dcb8629a77ed8908d74bc5fd43d5622327c404596d713f235bead9f2e724276ff49580db962ce4548bcfea19d97f5599517a0e2d183d785852bc6368570bdd44b3574a60e6c870705b87286ad73b4e524519af24069248111a8baeac181257ac03cbb8f4bdca260ea7c1dde333efc055300d95594e9c033606f8c08f14999c4d2a9ec1e17d3baf72a745ba1396294e19d01a9806f4379417ada318ba3eb0010c95d6293520357df51060e4f768621eec19e124f28711ace90880
D=0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420f61e576877da9650294cccb5f96c75fcb71bda1bbc4646367c4ebeda89d7318f

Need publick key for
 CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU=VeriSign Trust Network+OU=(c) 2006 VeriSign\, Inc. - For authorized use only,O=VeriSign\, Inc.,C=US
 KeyId=7fd365a7c2ddecbbf03009f34339fa02af333133

amazon.pem に含まれる3つの証明書は、いわゆる証明書の鎖(certificate chain)である。最後の証明書の公開鍵は amazon.pem の中には含まれない。KeyId をネット検索すると VeriSign のサーバーに飛ぶと思ったのであるが...

Hash Prefix

SHA-1 の場合に D に現れる
3021300906052b0e03021a05000414
hashprefix として $GOROOT/src/crypto/rsa/pkcs1v15.go に map 変数 hashPrefixes の中に定義されている。Hash アルゴリズムごとに固有の値を持つ。

hashPrefixe の値は rfc3447 にも載っている。この文書によると signature S は次のアルゴリズムで生成される。hexstr(bs) を byte 列 bs の16進文字列とすると

  1. N のサイズに合わせて、全てが 0xff の byte 列 bs を作る
  2. "0001"hexstr(bs) の先頭に埋め込む
  3. "00" + hashprefix + Hhexstr(bs) の末尾部に埋め込む。H は Hash 値の16進文字列
  4. こうして生成された文字列を private key で暗号化する

証明書の検証(2)

証明書は正当性を備えた公開鍵によってしか検証できない。それでは証明書に添えられた公開鍵の正当性をどのように確認するかが、ここでのテーマである。

CA ビジネスの嘘と真

証明書の使われ方

この3つはかなり性格が異なる。

裁判になれば、郵便封筒に押された time stamp の方が有利ではなかろうか? 何しろ裁判官の知識が乏しい。
電子証明書のアキレス腱: 秘密鍵が漏洩していないことを証明できない。

[1] 総務省『タイムスタンプについて』
https://www.soumu.go.jp/main_sosiki/joho_tsusin/top/ninshou-law/timestamp.html

秘密鍵の漏洩問題

ジレンマ
秘密鍵が単なる情報であるから扱いやすい。
しかし秘密鍵が単なる情報であるから漏洩を防ぐのが難しい。
秘密鍵を IC カードに入れる方法も考えられるが、運用が不便になる。
漏洩問題を扱った文献がある。

[1] 宇根正志『デジタル署名生成用秘密鍵の漏洩を巡る問題とその対策』
https://www.imes.boj.or.jp/research/papers/japanese/kk22-b1-2.pdf

[2] 小森旭、他『署名鍵漏洩問題における電子証拠生成技術について』
http://kmlab.iis.u-tokyo.ac.jp/old/publications/2002d/Komori_SCIS2003.pdf

[3] 『電子証明基盤の構築に向けて ~タイムスタンプの長期的証明力の考察と信頼できる基盤の提言~』
https://www.dekyo.or.jp/tbf/data/seika/kiban_001.pdf

証明書の信頼とは?

何を信頼するかは各自の判断である。他から強制されるいわれはない。

事例

CA が客の private key を大量に保持しているとは驚くね... 客の実印を預かっているようなものだ。印鑑と違って、客には判らないのが恐ろしい。(記事[1])
公開鍵の作成を CA にお願いするから、private key のコレクションが発生するのだろう。この問題を解決しない限り、電子商取引に使われる時代は来ないだろう。

[1]「Trustico扱い証明書の失効について」DigiCertの声明
https://rms.ne.jp/digital-certificate-news/trustico-certificate-revocation

CA(certificate authority)

Mac の場合 TrustStore

file:///System/Library/Security/Certificates.bundle/Contents/Resources/TrustStore.html
Ref: https://support.apple.com/ja-jp/HT213080

疑問: 公開鍵が載っていない。公開鍵がわからないと判断できないのでは?

Firefox

Firefox が使う root CA の公開鍵は、フォーマットが特殊で扱いにくい。

curl

curl は Firefox の 133 の root CA の公開鍵を PEM 形式に直して公開している。
次の HP から cacert.pem をダウンロードすればよい。
https://curl.se/docs/caextract.html

ここには公開鍵が含まれている。pemdump でこれを見るに、AuthorityKeyId が空欄になっているものがあるのに気付く。自己署名であるから SubjectKeyId と同じなはずであるから要らないと考えたのだろうが、それでも書くべきではないかと思う。

証明書の鎖は root CA の自己署名で終わってくれるのが良い。そうすればブラウザは信頼できる root CA の KeyId の AuthorityKeyId のリストを持っていれば簡単に検証できるはずである。現状はそのようになっていない。

メモ:

SignatureAlgorithm ECDSA-SHA384
PublicKeyAlgorithm ECDSA
が使われている。しかし pemdump の楕円曲線の扱いはもっと吟味する必要がある

その他

Firefoxと認証局証明書(信頼されたルート証明機関)
https://ozuma.hatenablog.jp/entry/20180725/1532530568
これはなかなか良い

Certificate Chain

Subject と Issuer
Subject == Issuer は自己証明

root CA