SVX日記
2024-01-16(Tue) マイナンバーカードで遊んでみる
正直に「パスワードを覚えていない」というと「そうなると手続きが面倒なのよねぇ」とのこと。フムン。いや、たぶんアレとアレなんだが、長い方が特に自信がない。なんとかならんかと思ってググると、短い方がわかるなら、コンビニで長い方を再設定することができるらしい。短い方は割と自信がある。試してみるか。で、無事に再設定することができ、ふるさと納税の手続きも完了した。よっしゃよっしゃ。
と、そこでフトだいぶ前に買ったカードリーダが手元にあることに気づいた。もしかすると、これで読んだりできるのかしらん。早速、やってみた。
$ pkcs15-tool --dump
Using reader with a card: NTT Communications Corp. SCR3310-NTTCom USB SmartCard Reader [Vendor Interface] 00 00
PKCS#15 Card [JPKI]:
Version : 0
Serial number : 00000000
Manufacturer ID: JPKI
Flags :
PIN [User Authentication PIN]
Object Flags : [0x12], modifiable
ID : 01
Flags : [0x12], local, initialized
Length : min_len:4, max_len:4, stored_len:0
Pad char : 0x00
Reference : 1 (0x01)
Type : ascii-numeric
Tries left : 3
PIN [Digital Signature PIN]
Object Flags : [0x12], modifiable
ID : 02
Flags : [0x12], local, initialized
Length : min_len:6, max_len:16, stored_len:0
Pad char : 0x00
Reference : 2 (0x02)
Type : ascii-numeric
Tries left : 5
Private RSA Key [User Authentication Key]
Object Flags : [0x1], private
Usage : [0x4], sign
Access Flags : [0x1D], sensitive, alwaysSensitive, neverExtract, local
ModLength : 2048
Key ref : 1 (0x1)
Native : yes
Auth ID : 01
ID : 01
MD:guid : c5a0a252-9d2d-eb60-fec0-41b4fbd722a2
Private RSA Key [Digital Signature Key]
Object Flags : [0x1], private
Usage : [0x204], sign, nonRepudiation
Access Flags : [0x1D], sensitive, alwaysSensitive, neverExtract, local
ModLength : 2048
Key ref : 2 (0x2)
Native : yes
Auth ID : 02
ID : 02
MD:guid : e1bc1dae-59f1-16ab-b43f-9dafbb2acc9b
Public RSA Key [User Authentication Public Key]
Object Flags : [0x0]
Usage : [0x0]
Access Flags : [0x2], extract
Key ref : 1 (0x1)
Native : yes
Path : 000a
ID : 01
Public RSA Key [Digital Signature Public Key]
Object Flags : [0x0]
Usage : [0x0]
Access Flags : [0x2], extract
Key ref : 2 (0x2)
Native : yes
Path : 0001
ID : 02
X.509 Certificate [User Authentication Certificate]
Object Flags : [0x0]
Authority : no
Path : 000a
ID : 01
Encoded serial : xx xx xxxxxxxx
X.509 Certificate [Digital Signature Certificate]
Object Flags : [0x1], private
Authority : no
Path : 0001
ID : 02
X.509 Certificate [User Authentication Certificate CA]
Object Flags : [0x0]
Authority : yes
Path : 000b
ID : 03
Encoded serial : 02 04 0133C349
X.509 Certificate [Digital Signature Certificate CA]
Object Flags : [0x0]
Authority : yes
Path : 0002
ID : 04
Encoded serial : 02 04 0132C4AB
えらくゾロソロと出てくるが、わからんようなわかるようなで面白い。特に冒頭の「PIN」「Tries left」なんて、どう見てもパスワードの失敗許容回数だ。当たり前だがカード内で管理されてるんだな。なかなか高機能なカードであるといえよう。
そのほか「Private RSA Key」「Public RSA Key」「X.509 Certificate」なんてのも、普段からSSLをガチャガチャしているオイラには見慣れた概念だ。証明書の内容を読み出してみる。
$ pkcs15-tool --read-certificate 1
-----BEGIN CERTIFICATE-----
XXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxx
xxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXX
:
XXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxx
xxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXX
-----END CERTIFICATE-----
$ pkcs15-tool --read-certificate 2 --auth-id 2 --verify-pin
Please enter PIN [Digital Signature PIN]:
-----BEGIN CERTIFICATE-----
XXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxx
xxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXX
:
XXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxx
xxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXX
-----END CERTIFICATE-----
$ pkcs15-tool --read-public-key 1
Public key enumeration failed: Required ASN.1 object not found
$ pkcs15-tool --read-public-key 2 --auth-id 1 --verify-pin
Please enter PIN [User Authentication PIN]:
Public key enumeration failed: Security status not satisfied
さらに秘密鍵にもなると読み出すコマンドすらない。そもそも「neverextract」だから読み出せなくて正しそう。カードに暗号文を渡し、カード内で(秘密鍵を使って)復号して平文を返してもらう、という形なんだろう。実に高機能なカードである。いくらすんだろね、これ。
カード情報 JPKI
(PIN1) PIN ユーザ認証PIN 4桁 残3回
(PIN2) PIN デジタル署名PIN 6-16桁 残5回
(秘密鍵1) 秘密RSA鍵 ユーザ認証鍵 署名用 機密 2048桁
→読み出し不可
→カード内で復号させる、PIN1で保護されている
(秘密鍵2) 秘密RSA鍵 デジタル署名鍵 署名用 非否認 機密 2048桁
→読み出し不可
→カード内で復号させる、PIN2で保護されている
(公開鍵1) 公開RSA鍵 ユーザ認証鍵
→読み出し失敗
(公開鍵2) 公開RSA鍵 デジタル署名鍵
→PIN2で保護されている、読み出し失敗
(証明書1) X.509 証明書 ユーザ認証証明書
(証明書2) X.509 証明書 デジタル署名証明書
→PIN2で保護されている
(証明書3) X.509 証明書 ユーザ認証認証局証明書
(証明書4) X.509 証明書 デジタル署名認証局証明書
require 'openssl'
cert = OpenSSL::X509::Certificate.new($stdin.read)
puts(cert.to_text)
$ ./pem_dec.rb < UserAuthenticationCertificateCA.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 20169545 (0x133c349)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=JP, O=JPKI, OU=JPKI for user authentication, OU=Japan Agency for Local Authority Information Systems
Validity
Not Before: Sep 14 23:41:59 2019 GMT
Not After : Sep 14 14:59:59 2029 GMT
Subject: C=JP, O=JPKI, OU=JPKI for user authentication, OU=Japan Agency for Local Authority Information Systems
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Subject Alternative Name:
DirName:/C=JP/O=\xE5\x85\xAC\xE7\x9A\x84\xE5\x80\x8B\xE4\xBA\xBA\xE8\xAA\x8D\xE8\xA8\xBC\xE3\x82\xB5\xE3\x83\xBC\xE3\x83\x93\xE3\x82\xB9
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 CRL Distribution Points:
Full Name:
DirName:C = JP, O = JPKI, OU = JPKI for user authentication, OU = Japan Agency for Local Authority Information Systems
X509v3 Subject Key Identifier:
8C:D5:58:6A:89:14:85:E5:59:37:9B:7E:29:D4:10:CF:D2:8B:35:93
公開するとマズいのは、(私自身の)個人情報を含んでいる「(証明書1) X.509証明書 ユーザ認証証明書」「(証明書2) X.509 証明書 デジタル署名証明書」の方だが、前者は(おそらく)マイナンバーの番号だけで、直接的な情報は後者に含まれているはずだ。
X509v3 CRL Distribution Points:
Full Name:
DirName:C = JP, O = JPKI, OU = JPKI for digital signature, OU = CRL Distribution Points, OU = Aichi-ken, CN = Nagoya-shi-Xxxx-ku CRLDP
クサイのは以下。デコードができていないっぽい。そういえば、「othername:<unsupported>」って、先日の自分に会社から支給されている証明書でも出てたな。その時は深く考えなかったけれど。
X509v3 Subject Alternative Name:
othername:<unsupported>, othername:<unsupported>, othername:<unsupported>, othername:<unsupported>, othername:<unsupported>, othername:<unsupported>
そんならRubyのOpenSSL::ASN1クラスを使ってデコードすりゃええか……と、思ったらその中身がムチャクチャに複雑で、ちっとも意図した結果が得られない。結局、どうにかこうにか再帰を使って出力に成功したが、実際にその中身はムチャクチャに複雑だった。これは再帰なしで書いたら日が暮れるな。文字列なのに、それがデコードできる場合と、単なる文字列の場合があるって、どういう構造なんだよ。
def asn_decode(value, n)
puts('%sdecode[%s]' % [(indent = ' ') * n, value.class])
if(value.is_a?(Array))
value.each {|v|
asn_decode(v, n + 1)
}
else
begin
asn = OpenSSL::ASN1.decode(value)
asn_decode(asn.value, n + 1)
rescue
puts('%smay be string[%s]' % [indent * n, value])
end
end
end
cert.extensions.each {|ext|
puts('*%s' % ext.to_h['oid'])
asn_decode(ext, 1)
}
$ ./pem_dec.rb < UserAuthenticationCertificateCA.pem
*subjectAltName
decode[OpenSSL::X509::Extension]
decode[Array]
decode[OpenSSL::ASN1::ObjectId]
decode[String]
may be string[subjectAltName]
decode[OpenSSL::ASN1::OctetString]
decode[String]
decode[Array]
decode[OpenSSL::ASN1::ASN1Data]
decode[Array]
decode[OpenSSL::ASN1::Sequence]
decode[Array]
decode[OpenSSL::ASN1::Set]
decode[Array]
decode[OpenSSL::ASN1::Sequence]
decode[Array]
decode[OpenSSL::ASN1::ObjectId]
decode[String]
may be string[C]
decode[OpenSSL::ASN1::PrintableString]
decode[String]
may be string[JP]
decode[OpenSSL::ASN1::Set]
decode[Array]
decode[OpenSSL::ASN1::Sequence]
decode[Array]
decode[OpenSSL::ASN1::ObjectId]
decode[String]
may be string[O]
decode[OpenSSL::ASN1::UTF8String]
decode[String]
may be string[公的個人認証サービス]
decode[OpenSSL::ASN1::Set]
decode[Array]
decode[OpenSSL::ASN1::Sequence]
decode[Array]
decode[OpenSSL::ASN1::ObjectId]
decode[String]
may be string[OU]
decode[OpenSSL::ASN1::UTF8String]
decode[String]
may be string[公的個人認証サービス署名用]
decode[OpenSSL::ASN1::Set]
decode[Array]
decode[OpenSSL::ASN1::Sequence]
decode[Array]
decode[OpenSSL::ASN1::ObjectId]
decode[String]
may be string[OU]
decode[OpenSSL::ASN1::UTF8String]
decode[String]
may be string[地方公共団体情報システム機構]
$ ./pem_dec.rb < DigitalSignatureCertificateCA.pem | grep may
may be string[subjectAltName]
may be string[C]
may be string[JP]
may be string[O]
may be string[公的個人認証サービス]
may be string[OU]
may be string[公的個人認証サービス署名用]
may be string[OU]
may be string[地方公共団体情報システム機構]
$ ./pem_dec.rb < DigitalSignatureCertificate.pem | grep may
may be string[subjectAltName]
may be string[1.2.392.200149.8.5.5.1]
may be string[山田 太郎]
may be string[1.2.392.200149.8.5.5.4]
may be string[319700101]
may be string[1.2.392.200149.8.5.5.3]
may be string[1]
may be string[1.2.392.200149.8.5.5.5]
may be string[愛知県名古屋市中区栄3丁目]
may be string[1.2.392.200149.8.5.5.2]
may be string[00000]
may be string[1.2.392.200149.8.5.5.6]
may be string[00000000000000000000]
当然だが上記は改ざんしている。んが、モロに自分の個人情報が入っていた。「デジタル署名」をするという行為は、上記の情報を提供するということであり、それが意図に反して行われないようにするためのものが、長い方のPINコードなのであった。逆に言えば、長い方のPINコードの要求に応じた場合は「自分の個人情報が提供される」ということだ。
しかし、だ。「名前、生年月日、性別、住所」なんて、役所で気にもせずに一番に書面に書き出す内容である。たかが、それだけの情報なのである。マイナンバー制度に関してはマスゴミの意味不明のFUDキャンペーンで、すっかりネガティブイメージが付いてしまっているが、フタを開けてみればそれだけのこと。ボールペンで書くか、PINコードを打つかの違いしかないといえよう。仮に落として紛失したところで、運転免許証と同程度の危険性しかない。