APNsのルート証明書更新の影響について調査する方法を調べてみた
先月Apple Developer Newsの中でAPNs(Apple Push Notification service)のサーバー証明書更新のお知らせが来ていました。
どうやらPush通知依頼のリクエストを受けるAPNsのエンドポイントのルート証明書を2021/3/29にGeoTrust Global CA
からAAACertificateServices
に変更するようです。ルート証明書が切り替わったときにPush通知依頼が失敗しないように、2021/3/29までにPush通知サーバーのTrust Storeに両方の証明書が入ってるか確認しておいてね、とのことです。
なお記事の最後にある通り、Appleが我々デベロッパー向けに発行しているAPNsの証明書についての影響はないので混乱しないように注意が必要です。
Note that Apple Push Notification service SSL provider certificates issued to you by Apple do not need be to updated at this time.
FirebaseやサードパーティのPush通知サービスを使ってる場合、今回の対応は利用しているサービスに任せればよいですが、自前でAPNsへのリクエストを組んでいる場合は念の為確認しておく必要がありそうです。
そこでAPNsへのリクエストを行うアプリケーションが動作する環境でAAACertificateServicesの証明書がTrust Storeに入っていることを確認する方法を調べたので以下にまとめました。
なおAPNsへPush通知のリクエストを投げる方法は以前まとめたので参考にしてみてください。
ルート証明書とは何か
ルート証明書はhttps通信を行うときに用いられる証明書で、OSやブラウザにデフォルトで保存されているものです。ここでは詳細については触れないため、ルート証明書についてよくわからないという方はさくらインターネットさんのコラムを見るとよいでしょう。
2021/3/7時点のAPNsへ通信で使われるルート証明書
opensslコマンドを使ってsandboxと商用のAPNsへのhttps通信で使われるルート証明書を見てみましょう。
$ openssl s_client -connect api.development.push.apple.com:443 > /dev/null depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA verify return:1 depth=1 CN = Apple IST CA 2 - G1, OU = Certification Authority, O = Apple Inc., C = US verify return:1 depth=0 CN = api.development.push.apple.com, OU = management:idms.group.533599, O = Apple Inc., ST = California, C = US verify return:1 $ openssl s_client -connect api.push.apple.com:443 > /dev/null depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA verify return:1 depth=1 CN = Apple IST CA 2 - G1, OU = Certification Authority, O = Apple Inc., C = US verify return:1 depth=0 CN = api.push.apple.com, OU = management:idms.group.533599, O = Apple Inc., ST = California, C = US verify return:1
今はどちらもGeoTrust Global CAになっていることがわかります。
AAACertificateServicesの証明書の中身の確認
AAACertificateServicesのルート証明書のcrtファイルは上記のAppleのニュースの本文の中にあるリンクからダウンロードできます。
こちらもopensslコマンドで中身を見てみましょう。
$ openssl x509 -noout -text -in ~/Desktop/AAACertificateServices.crt Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha1WithRSAEncryption Issuer: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services Validity Not Before: Jan 1 00:00:00 2004 GMT Not After : Dec 31 23:59:59 2028 GMT Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:be:40:9d:f4:6e:e1:ea:76:87:1c:4d:45:44:8e: be:46:c8:83:06:9d:c1:2a:fe:18:1f:8e:e4:02:fa: f3:ab:5d:50:8a:16:31:0b:9a:06:d0:c5:70:22:cd: 49:2d:54:63:cc:b6:6e:68:46:0b:53:ea:cb:4c:24: c0:bc:72:4e:ea:f1:15:ae:f4:54:9a:12:0a:c3:7a: b2:33:60:e2:da:89:55:f3:22:58:f3:de:dc:cf:ef: 83:86:a2:8c:94:4f:9f:68:f2:98:90:46:84:27:c7: 76:bf:e3:cc:35:2c:8b:5e:07:64:65:82:c0:48:b0: a8:91:f9:61:9f:76:20:50:a8:91:c7:66:b5:eb:78: 62:03:56:f0:8a:1a:13:ea:31:a3:1e:a0:99:fd:38: f6:f6:27:32:58:6f:07:f5:6b:b8:fb:14:2b:af:b7: aa:cc:d6:63:5f:73:8c:da:05:99:a8:38:a8:cb:17: 78:36:51:ac:e9:9e:f4:78:3a:8d:cf:0f:d9:42:e2: 98:0c:ab:2f:9f:0e:01:de:ef:9f:99:49:f1:2d:df: ac:74:4d:1b:98:b5:47:c5:e5:29:d1:f9:90:18:c7: 62:9c:be:83:c7:26:7b:3e:8a:25:c7:c0:dd:9d:e6: 35:68:10:20:9d:8f:d8:de:d2:c3:84:9c:0d:5e:e8: 2f:c9 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: A0:11:0A:23:3E:96:F1:07:EC:E2:AF:29:EF:82:A5:7F:D0:30:A4:B4 X509v3 Key Usage: critical Certificate Sign, CRL Sign X509v3 Basic Constraints: critical CA:TRUE X509v3 CRL Distribution Points: Full Name: URI:http://crl.comodoca.com/AAACertificateServices.crl Full Name: URI:http://crl.comodo.net/AAACertificateServices.crl Signature Algorithm: sha1WithRSAEncryption 08:56:fc:02:f0:9b:e8:ff:a4:fa:d6:7b:c6:44:80:ce:4f:c4: c5:f6:00:58:cc:a6:b6:bc:14:49:68:04:76:e8:e6:ee:5d:ec: 02:0f:60:d6:8d:50:18:4f:26:4e:01:e3:e6:b0:a5:ee:bf:bc: 74:54:41:bf:fd:fc:12:b8:c7:4f:5a:f4:89:60:05:7f:60:b7: 05:4a:f3:f6:f1:c2:bf:c4:b9:74:86:b6:2d:7d:6b:cc:d2:f3: 46:dd:2f:c6:e0:6a:c3:c3:34:03:2c:7d:96:dd:5a:c2:0e:a7: 0a:99:c1:05:8b:ab:0c:2f:f3:5c:3a:cf:6c:37:55:09:87:de: 53:40:6c:58:ef:fc:b6:ab:65:6e:04:f6:1b:dc:3c:e0:5a:15: c6:9e:d9:f1:59:48:30:21:65:03:6c:ec:e9:21:73:ec:9b:03: a1:e0:37:ad:a0:15:18:8f:fa:ba:02:ce:a7:2c:a9:10:13:2c: d4:e5:08:26:ab:22:97:60:f8:90:5e:74:d4:a2:9a:53:bd:f2: a9:68:e0:a2:6e:c2:d7:6c:b1:a3:0f:9e:bf:eb:68:e7:56:f2: ae:f2:e3:2b:38:3a:09:81:b5:6b:85:d7:be:2d:ed:3f:1a:b7: b2:63:e2:f5:62:2c:82:d4:6a:00:41:50:f1:39:83:9f:95:e9: 36:96:98:6e
2004年に発行されたもののようです。確認用にfingerprintを確認しておきましょう。
$ openssl x509 -sha256 -fingerprint -noout -in ~/Desktop/AAACertificateServices.crt SHA256 Fingerprint=D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
次にAPNsへのPush通知のリクエストを投げる発射台に上記の証明書が含まれることを確認していきます。今回はJava、PHP、Nodeについて調べてみました。
Javaの場合
Javaアプリケーションの場合はJDK / JREのKeystore情報を確認すればよいです。keytool
コマンドつかってkeystoreの中身を確認します。
$ java -version openjdk version "11.0.10" 2021-01-19 OpenJDK Runtime Environment (build 11.0.10+9) OpenJDK 64-Bit Server VM (build 11.0.10+9, mixed mode) $ keytool -list -storepass changeit -keystore $JAVA_HOME/lib/security/cacerts | \ grep "55:92:60:84:EC:96:3A:64:B9:6E:2A:BE:01:CE:0B:A8:6A:64:FB:FE:BC:C7:AA:B5:AF:C1:55:B3:7F:D7:60:66" Warning: use -cacerts option to access cacerts keystore Certificate fingerprint (SHA-256): 55:92:60:84:EC:96:3A:64:B9:6E:2A:BE:01:CE:0B:A8:6A:64:FB:FE:BC:C7:AA:B5:AF:C1:55:B3:7F:D7:60:66
AAACertificateServicesのfingerprintがヒットしました。lessで詳しく見てみると、comodoaaaca
というAliase nameで登録されていました。
... Alias name: comodoaaaca [jdk] Creation date: Jan 1, 2004 Entry type: trustedCertEntry Owner: CN=AAA Certificate Services, O=Comodo CA Limited, L=Salford, ST=Greater Manchester, C=GB Issuer: CN=AAA Certificate Services, O=Comodo CA Limited, L=Salford, ST=Greater Manchester, C=GB Serial number: 1 Valid from: Thu Jan 01 09:00:00 JST 2004 until: Mon Jan 01 08:59:59 JST 2029 Certificate fingerprints: SHA1: D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 SHA256: D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 ...
OpenJDK11の場合は特に何もしなくてもよさそうですね。
PHPの場合
PHPアプリケーションの場合は以下の関数を実行することでPHPが参照しているルート証明書リストの情報が確認できます。
確認方法だけなのでここではmacOS上で実行してしまいます。
ちなみにTerminalでPHPを実行したら警告がでました。将来のmacOSにはPHPはバンドルされないんですね...。
$ php -v WARNING: PHP is not recommended PHP is included in macOS for compatibility with legacy software. Future versions of macOS will not include PHP. PHP 7.3.24-(to be removed in future macOS) (cli) (built: Dec 21 2020 21:33:25) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.24, Copyright (c) 1998-2018 Zend Technologies $ php -a Interactive shell php > var_dump(openssl_get_cert_locations()); array(8) { ["default_cert_file"]=> string(25) "/private/etc/ssl/cert.pem" ["default_cert_file_env"]=> string(13) "SSL_CERT_FILE" ["default_cert_dir"]=> string(22) "/private/etc/ssl/certs" ["default_cert_dir_env"]=> string(12) "SSL_CERT_DIR" ["default_private_dir"]=> string(24) "/private/etc/ssl/private" ["default_default_cert_area"]=> string(16) "/private/etc/ssl" ["ini_cafile"]=> string(0) "" ["ini_capath"]=> string(0) "" } php > quit
/private/etc/ssl/cert.pem
にある証明書リストを参照するようです。中身を見てみます。
$ awk -v cmd='openssl x509 -noout -sha256 -fingerprint' ' /BEGIN/{close(cmd)};{print | cmd}' < /private/etc/ssl/cert.pem | grep "D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4" unable to load certificate 4442443436:error:09FFF06C:PEM routines:CRYPTO_internal:no start line:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-56.60.2/libressl-2.8/crypto/pem/pem_lib.c:684:Expecting: TRUSTED CERTIFICATE SHA256 Fingerprint=D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
AAACertificateServicesのfingerprintがヒットしました。lessで中身を見ても確認できました。
$ awk -v cmd='openssl x509 -noout -text ' ' /BEGIN/{close(cmd)};{print | cmd}' < /private/etc/ssl/cert.pem | less ... Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha1WithRSAEncryption Issuer: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services Validity Not Before: Jan 1 00:00:00 2004 GMT Not After : Dec 31 23:59:59 2028 GMT Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services] ...
Node.jsの場合
Node.jsの場合はtslモジュールが参照しているroot証明書を確認すればよいです。
ドキュメントを読むと、If the ca option is not given, then Node.js will default to using Mozilla's publicly trusted list of CAs.
とあるのでMozilaの証明書リストを使うようになっているようです。
https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt
以下のコードを実際に実行して参照しているルート証明書のリストが確認できます。
const tls = require('tls'); const net = require('net'); var list = tls.rootCertificates; for(key in list){ const secureContext = tls.createSecureContext({ cert: list[key] }); const secureSocket = new tls.TLSSocket(new net.Socket(), { secureContext }); const cert = secureSocket.getCertificate(); console.log(cert); }
$ node -v v12.20.1 $ node rootCAList.js | grep "D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4" fingerprint256: 'D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4',
AAACertificateServicesのfingerprintがヒットしました。lessで詳細を見ても合致してますね。
$ node rootCAList.js | less ... { subject: [Object: null prototype] { C: 'GB', ST: 'Greater Manchester', L: 'Salford', O: 'Comodo CA Limited', CN: 'AAA Certificate Services' }, issuer: [Object: null prototype] { C: 'GB', ST: 'Greater Manchester', L: 'Salford', O: 'Comodo CA Limited', CN: 'AAA Certificate Services' }, ...
3/29までに何をすればよい?
Appleの通知の本文にある通り、APNsへリクエストを投げるアプリケーションがAAACertificateServicesのルート証明書を信頼するようになっていればよいです。ルート証明書を信頼するかどうかは上記の証明書リストにAAACertificateServicesのルート証明書が登録されていればよいです。
より厳密にやるのであれば、Push通知のリクエストをAAACertificateServices経由で行えばよいのですがこれは3/29を待たなければできません。sandboxだけでも先に変わってくれるとよいのですが、おそらく一括で変更が入るのでしょう。
どうしても心配な方は、AAACertificateServicesの証明書を経由するhttpsリクエストが正しく実行できることを確認してみるといいかなと思いました。
例えばsupport.sectigo.com
へのリクエストはAAACertificateServicesのルート証明書を経由するようです。
$ openssl s_client -connect support.sectigo.com:443 > /dev/null depth=3 C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services verify return:1 depth=2 C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority verify return:1 depth=1 C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Extended Validation Secure Server CA verify return:1 depth=0 serialNumber = 04058690, jurisdictionCountryName = GB, businessCategory = Private Organization, C = GB, postalCode = M5 3EQ, ST = Manchester, L = Salford, street = Trafford Road, street = Office Village Exchange Quay, street = 3rd Floor Building 26, O = Sectigo Limited, OU = IT, CN = support.sectigo.com verify return:1
まとめ
APNsのルート証明書変更に起因して、Java・PHP・Node.jsのアプリケーションが参照しているルート証明書情報を確認する手順をまとめました。検証を通してhttps通信の仕組みについて改めて理解を深めることができました。証明書の更新に関しては影響がある方は3/29以降問題が発生しないように事前に確認しておくとよいでしょう。
2021/4/2追記
切り替えあとに証明書チェインの情報を確認してみたら無事AAA Certificate Servicesに変わってました。
$ openssl s_client -connect api.development.push.apple.com:443 > /dev/null depth=2 C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services verify return:1 depth=1 CN = Apple Public Server RSA CA 12 - G1, O = Apple Inc., ST = California, C = US verify return:1 depth=0 CN = api.development.push.apple.com, OU = management:idms.group.533599, O = Apple Inc., ST = California, C = US verify return:1 $ openssl s_client -connect api.push.apple.com:443 > /dev/null depth=2 C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services verify return:1 depth=1 CN = Apple Public Server RSA CA 12 - G1, O = Apple Inc., ST = California, C = US verify return:1 depth=0 CN = api.push.apple.com, OU = management:idms.group.887777, O = Apple Inc., ST = California, C = US verify return:1