SSL/TLSは、モバイルアプリケーションとサーバー間のデータを暗号化し、トラフィックの機密性と完全性を保証する暗号プロトコルです。Apple(2026)によると、App Transport SecurityはすべてのiOSデバイスでデフォルトでTLS 1.2未満の接続をブロックします。TLS 1.3はTLS 1.2と比較してハンドシェイク時間を2倍短縮し、モバイルアプリケーションのUXを向上させます。
要点
SSL(Secure Sockets Layer)とTLS(Transport Layer Security)は、ネットワーク上での安全なデータ転送を保証する暗号プロトコルです。1990年代にNetscapeによって開発されたSSLは、POODLEやBEASTの脆弱性によりバージョン3.0以降、旧式と見なされています。その後継であるTLSは、バージョン1.0、1.1、1.2、1.3を経ており、現在はTLS 1.2とTLS 1.3のみが有効と見なされています。すべての最新モバイルプラットフォームはネットワーク接続にTLSを要求し、App StoreとGoogle Playはレビュー時にこれを確認します。
TLSなしでは、アプリケーションとサーバー間のトラフィックは平文で送信されます。同じWi-Fiネットワーク上の誰でも、Wiresharkやtcpdumpを使用してログイン、パスワード、トークン、ユーザーの個人データを傍受できます。TLSは送信されるすべてのデータを暗号化し(トランスポート層暗号化)、X.509証明書のチェーンを通じてサーバーの正当性を検証します。IETF(2018)によると、TLS 1.3は最新のAEAD暗号(AES-GCM、ChaCha20-Poly1305)のみを使用し、RC4や3DESなどの旧式アルゴリズムを除外しています。
HTTPS(HTTP Secure)はTLS上のHTTPです。モバイルアプリケーションがhttps://でリクエストを行うと、最初にサーバーとのTLS接続を確立し、その後暗号化チャネルを介してHTTPヘッダーとリクエスト本文を送信します。HTTPSなしでは、まともなAPIは動作すべきではありません — これは基本的なセキュリティ衛生です。OWASP(2026)によると、安全でない接続はモバイルアプリケーションの脆弱性トップ3に入っています。
TLSハンドシェイクは、クライアントとサーバー間の安全な接続を確立するプロセスです。両者はプロトコルバージョンをネゴシエーションし、暗号スイートを選択し、非対称暗号方式で鍵を交換し、証明書を検証します。TLS 1.2では、ハンドシェイクに2ラウンドトリップタイム(2 RTT)が必要です:クライアント→サーバー(ClientHello)、サーバー→クライアント(ServerHelloとCertificate)、そして最終的なFinishedメッセージ。TLS 1.3はこのプロセスを1 RTTに短縮します。
第1段階:ClientHello — クライアントがサポートするTLSバージョン、暗号スイートのリスト、ランダム数を送信します。サーバーはServerHelloで応答し、バージョンと暗号スイートを選択し、X.509証明書(Certificate)とServerHelloDoneメッセージを送信します。クライアントは信頼できる認証局(CA)のチェーンを通じて証明書を検証し、pre-master secretを生成し、証明書の公開鍵で暗号化してClientKeyExchangeでサーバーに送信します。その後、両者はセッション鍵を生成し、ChangeCipherSpecとFinishedメッセージを交換します。この時点以降、すべてのデータは対称暗号化されます。
import Security
let url = URL(string: "https://api.example.com")!
let session = URLSession(configuration: .default,
delegate: self,
delegateQueue: nil)
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition,
URLCredential?) -> Void
) {
let trust = challenge.protectionSpace.serverTrust
guard let trust else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
completionHandler(.useCredential, URLCredential(trust: trust))
}
URLSessionDelegateを介したiOSでのURLAuthenticationChallengeの処理例。このメソッドは各TLSハンドシェイク中に呼び出され、アプリケーションがサーバー証明書をカスタム検証できるようにします。本番環境では、SecTrustEvaluateWithErrorによる証明書検証を追加し、事前に保存したフィンガープリントと比較してからuseCredentialを呼び出してください。
TLS 1.3(RFC 8446、2018)は10年ぶりの主要なプロトコルアップデートです。主な改善点:ハンドシェイクを1 RTTに短縮(再接続時は0 RTT)、旧式の暗号スイートを削除(RSA鍵交換、CBCモード)、Perfect Forward Secrecy(PFS)を必須化、signed transcriptによるダウングレード攻撃からの保護。Qualys SSL Labs(2026)によると、TLS 1.3はPFSのおかげで長期サーバー鍵が侵害された場合でも保護を提供します。
| 特性 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| ハンドシェイク | 2 RTT(完全) | 1 RTT(PSKで0 RTT) |
| 暗号スイート | 30以上の組み合わせ(RSA、DH、ECDH) | 5つのAEADスイート(AES-GCM、ChaCha20) |
| Forward Secrecy | オプション(DHE、ECDHE) | 必須(すべてのスイート) |
| iOSサポート | iOS 5+ | iOS 12+ |
| Androidサポート | Android 4.0+ | Android 10+ |
| 旧式アルゴリズム | RSA、CBC、RC4、3DES | 完全に削除 |
0-RTT(ゼロラウンドトリップタイム)はTLS 1.3の機能で、PSK(事前共有鍵)による再接続時にClientHelloとともにデータを即座に送信できます。これにより、特に同じサーバーへの頻繁なリクエストがある場合、モバイルアプリケーションの後続画面の読み込みが高速化します。ただし、0-RTTデータはリプレイ攻撃から保護されていません — 傍受されて再送される可能性があります。0-RTTは副作用のないべき等リクエスト(GET、PUT)にのみ使用してください。
App Transport Security(ATS)はAppleのメカニズムで、TLS 1.2以上でのHTTPS接続を要求し、iOS 9からデフォルトで有効です。ATSはすべてのHTTP接続およびTLS 1.2未満のHTTPSをブロックします。開発者は特定のドメインに対してNSAppTransportSecurityを介してInfo.plistに例外を設定できますが、Appleは例外を最小限に抑え、どこでもHTTPSを使用することを推奨しています。ATS要件の違反は、App Storeレビューでのアプリ拒否の理由となります。
<!-- Info.plist — App Transport Security -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSExceptionDomains</key>
<dict>
<key>cdn.example.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<false/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
</dict>
</dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
Info.plistでのATS設定。NSAllowsArbitraryLoadsはfalseに設定されています — すべての接続はHTTPSを使用する必要があります。ドメインcdn.example.comには最小TLSバージョン1.2が指定され、NSAllowsLocalNetworking=trueはローカルネットワークのHTTPを許可します(開発サーバーに便利)。AppleはNSExceptionDomainsなしでNSAllowsArbitraryLoadsを有効にしないことを強く推奨しています — これは一般ルールではなく例外であるべきです。
Network Security Configは、Java/Kotlinコードを変更せずにHTTPSとTLSを設定するAndroidのメカニズムです。設定はnetwork_security_config.xmlファイルで指定され、android:networkSecurityConfig属性を介してAndroidManifestで接続されます。信頼できる証明書(ユーザーCAとシステムCA)、Certificate Pinning、平文HTTPの無効化、デバッグオーバーライド、トラフィックリダイレクトの設定をサポートしています。
<!-- res/xml/network_security_config.xml -->
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">api.example.com</domain>
<pin-set expiration="2027-01-01">
<pin digest="SHA-256">
47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
</pin>
</pin-set>
</domain-config>
</network-security-config>
Android用Network Security Config。base-configは平文トラフィックをブロックし、システムCA証明書のみを信頼します(ユーザー証明書はなし — ユーザーによるMitM証明書インストールからの保護)。api.example.comのdomain-configにはSHA-256証明書フィンガープリントのpin-setが含まれています。指定された有効期限前にサーバー証明書が変更されると、接続は拒否されます — これはCertificate Pinningの厳格な形式です。
Certificate Pinningは、アプリケーションコードにサーバーの証明書または公開鍵を固定する手法です。各TLSハンドシェイク中に、クライアントはサーバー証明書を事前に保存されたフィンガープリント(SHA-256ハッシュ)と比較します。攻撃者が信頼できるCA証明書を入手したり認証局を侵害したりしても、MitM攻撃は実行できません — アプリケーションはCAチェーンではなく特定のフィンガープリントをチェックするからです。これは金融アプリケーションや機密データを扱うアプリにとって特に重要です。
Certificate Pinningには注意が必要です:サーバー証明書が変更されると、アプリの古いバージョンはすべて接続できなくなります。複数のバックアップフィンガープリント(プライマリ+バックアップ)を保存し、pin-setの有効期限を指定し、標準のCA検証によるフォールバックメカニズムを実装することをお勧めします。代替手段としてTrust On First Use(TOFU)があります。これはアプリが最初の接続時に証明書を記憶し、変更時にユーザーに警告するものです。OWASP(2026)によると、Certificate Pinningの欠如はモバイルアプリケーションの脆弱性トップ3(M3:安全でない通信)に入っています。
Alamofire 5+では、Certificate PinningはServerTrustManagerとPinnedCertificatesTrustEvaluator(完全な証明書チェック)またはPublicKeysTrustEvaluator(公開鍵のみ)を介して設定されます。公開鍵の方が望ましいです — 同じCAで証明書を更新しても変更されないからです。[host: evaluator]辞書でServerTrustManagerを作成し、Sessionに渡して、保護されたAPIへのすべてのリクエストに使用します。
よくある質問
SSLは旧式のプロトコル(バージョン2.0および3.0)で、POODLEやBEASTの脆弱性により安全ではないと見なされています。TLSはその後継で、TLS 1.0(RFC 2246、1999)から始まります。現代の“SSL証明書”はすべて、TLSプロトコルで使用されるX.509証明書です。SSL 3.0はすべての最新OSとブラウザで禁止されています。
App Transport SecurityはAppleのアプリケーションセキュリティ要件です。HTTPはデータを平文で送信するため、公衆Wi-Fiネットワークでトークンやユーザーの個人データを傍受される可能性があります。ATSはデフォルトでHTTPおよびTLS 1.2未満のHTTPSをブロックし、開発者の操作なしでもユーザーを保護します。
SSL Labs(ssllabs.com/ssltest)またはコマンドラインを使用します:openssl s_client -tls1_3 -connect example.com:443。ほとんどのクラウドプラットフォーム(AWS CloudFront、Cloudflare、Nginx 1.19+、Caddy)ではTLS 1.3がデフォルトで有効です。Android 10+では、システムのConscryptプロバイダーにサポートが組み込まれています。
自己署名証明書は、認証局ではなく自分自身で署名された証明書です。本番環境では使用できません — モバイルOSはそのような証明書を信頼しません。ローカル開発に使用されます:MDMを介して信頼できる証明書に追加するか、検証を無効にしたデバッグビルドを使用してください。
ServerTrustManagerをPinnedCertificatesTrustEvaluatorまたはPublicKeysTrustEvaluatorとともに作成します。前者は完全な証明書をチェックし、後者は公開鍵のみをチェックします(推奨)。マネージャーをSession(configuration: serverTrustManager:)に渡し、すべてのAPIリクエストにそのセッションを使用します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。