3 ポイント 投稿者 GN⁺ 2023-12-06 | 1件のコメント | WhatsAppで共有
  • iMessageは APNs を単なる通知チャネルではなく双方向転送基盤として使い、IDS を通じて公開鍵の登録・照会とメッセージ配信の準備をまとめて処理する
  • デバイスはAPNs接続後に push token を受け取り、iMessageのtopicである com.apple.madrid をフィルタリングして受信するメッセージ範囲を決める
  • IDS登録にはApple ID認証トークン、長期証明書、公開暗号化鍵・署名鍵のアップロード、validation data の提出が必要で、非Appleデバイスでの利用が難しいように設計されている
  • メッセージ暗号化は旧式の pair と新式の pair-ec に分かれ、pair-ec はSignalに似た pre-key ベースの forward secrecy を提供する
  • 送信者は受信者ごとの暗号化ペイロードを個別に送ることも、まとめて送ることもできるが、最新デバイスで復号するにはAES鍵に HMACタグ が含まれている必要がある

APNsが担うiMessageの転送基盤

  • iMessageの基礎レイヤーの1つは Apple Push Notification Service(APNs)
  • APNsは、App Storeアプリが閉じているときでもリアルタイム通知や更新を受け取るために使われるサービスと同じレイヤー
  • iMessageではAPNsは通知受信だけでなく、メッセージ転送 にも使われる双方向サービスとして動作する
  • デバイスがAPNsに接続すると push token を受け取る
    • このトークンは特定のデバイスに通知をルーティングするために使われる
    • application:didRegisterForRemoteNotificationsWithDeviceToken: APIで受け取るトークンとは技術的に異なる
    • このAPIのトークンはアプリごとのスコープで、アプリケーションのbundle IDで要求されるが、目的は似ている
  • デバイスにpush notificationを送るときは、メッセージの topic も指定する必要がある
    • topicは通常Bundle IDのように見える
    • iMessageのtopicは com.apple.madrid
  • デバイスがAPNsに接続すると、どのメッセージを受け取るかをサーバーに伝える filter message を送信する
    • APNsサーバーはAPNs Courierとも呼ばれる
    • filter messageには状態ごとのtopic一覧を含められる
    • topicの状態は enabled, opertunistic, paused, disabled のいずれかになる

APNs上で動作するIDSクエリ

  • APNsはiMessageの実際のメッセージ配信にだけ使われるわけではない
  • APNs上の pseudo-HTTPレイヤー を通じて、IDSがクエリを送り応答を受け取れる
  • APNsに接続するには Albert activation server が発行したクライアント証明書が必要

IDSとApple ID認証フロー

  • IDSはiMessageの 鍵サーバー として機能し、FaceTimeのような他のサービスでも使われる
  • IDSはIDentity Servicesの略だと見られるが、公式な確認はないとされている
  • iMessageはエンドツーエンド暗号化を使うため、各参加者の 公開鍵 を安全に交換する必要がある
  • IDS登録の最初のステップは認証トークンを受け取ること
    • APIにApple IDのユーザー名とパスワードを渡す必要がある
  • 2FAは後からIDS APIに合わせる形で組み込まれた
    • レガシー方式では2FAコードをパスワードに直接連結する
    • GrandSlam 方式では「Anisette data」で同一デバイスであることを証明し、2FAコードの再入力を不要にする
    • その後、Password Equivalent Token(PET)を受け取り、パスワードや2FAコードのように使える
  • 認証トークンを受け取った後は、すぐにより長く有効な 証明書 に交換しなければならない
    • この証明書によってIDS登録は可能になるが、それだけで鍵照会を行うには十分ではない

IDS登録とvalidation data

  • IDS設定で最も重要なステップは registration
  • registrationでは公開暗号化鍵と署名鍵を鍵サーバーにアップロードする
  • デバイスが対応する機能に関する各種 client data もあわせてアップロードされる
  • IDS registrationリクエストには「validation data」というバイナリblobが必要
    • これは非AppleデバイスがiMessageを利用できないようにするAppleの検証メカニズム
  • validation dataの生成には、デバイスの serial number、model、disk UUID などの情報が使われる
    • すべてのvalidation dataを同一に扱うことはできない
    • Hackintoshと同様に、アカウントの古さや「score」によって、不正なserialの使用可否や「customer code」エラーの有無が左右される
  • validation dataを生成するバイナリは強く難読化されている
    • pypush はcustom mach-o loaderとUnicorn Engineで難読化バイナリをエミュレートし、この問題を回避する
    • pypush はserial numberのようなデバイス属性を data.plist ファイルに入れて、エミュレートされたバイナリに渡す

鍵照会とsession token

  • IDS登録後には identity keypair を受け取る
  • このkeypairを使って公開鍵照会を行える
  • 照会したいアカウントを渡すと「identities」の一覧を受け取る
    • 各identityは、そのアカウントに登録された1台のデバイスに対応する
    • public key、push token、session token などの重要な情報が含まれる
  • session token はデバイスにメッセージを送るために必要
    • 最近照会を実行したことを証明する役割を持つ
    • session tokenには有効期限がある
    • 照会リクエストを実行したアカウントだけが使えるため共有できない

受信メッセージと暗号化形式

  • メッセージを受け取るには、APNs接続を com.apple.madrid でフィルタリングし、active state packet を送ればよい
  • 受信メッセージの暗号化形式は、IDS登録時に通知したcapabilitiesと送信側デバイスのiOSバージョンによって変わる
    • 旧式のpre-iOS 13形式は pair
    • 新形式は pair-ec
  • pair 形式はより多く文書化されており、実装もしやすい
  • pair は新しい pair-ec と異なり、「pre-keys」を用いた forward secrecy を提供しない
  • メッセージは複数の論文と pypush の実装に従って復号できる
  • メッセージ署名の検証は任意だが、安全なクライアントを作るうえで重要

送信方式と実装時の注意点

  • メッセージ送信は受信の逆過程に近い
  • 受信者ごとにメッセージを個別送信できる
  • 複数の受信者と、それぞれの受信者向け暗号化ペイロードを1つの大きなbundleにまとめて送ることも可能
    • この場合、APNsがそれを分離する
  • メッセージは会話のすべての参加者に配信される
    • 自分のアカウントに紐づく他のデバイスにも配信される
  • 送信時によく見落とされる点は、AES key が完全なランダムではないこと
    • AES keyにはHMACがタグとして付加されている
    • 完全にランダムなAES keyを使うと、最新デバイスでメッセージの復号に失敗する

関連実装と参考資料

1件のコメント

 
GN⁺ 2023-12-06
Hacker Newsのコメント
  • Appleは attestation(DeviceCheck) でiMessageをロックし始める可能性が高そう
    ただし、古い端末にはソフトウェアアップデートが必要になるという問題がある

    • すでに部分的にはそうしている
      「validation data」を作る際に、端末のシリアル番号、モデル、ディスクUUIDのような情報が使われており、Hackintoshのような環境では、アカウント年齢や「スコア」に応じて不正なシリアル番号を使えるか、それとも「customer code」エラーになるかが分かれる
      「customer code」エラーは実質的にAppleのattestation失敗プロンプトで、一度引っかかるとApple Supportに連絡してApple IDのロックを解除しなければならない
      正規ユーザーは正規端末でログインを承認する形で簡単に通過できるが、Hackintoshユーザーは回避テクニックでこの過程をごまかしている
      https://old.reddit.com/r/hackintosh/comments/gij9rt/getting_...
    • Appleはすでにここ5年ほどの iOS端末 にセキュリティアップデートを提供しているので、実際に使われているほぼすべてのiOS端末にアップデートが行き渡るまで、そこまで長くはかからなさそう
    • 古い端末、つまり TPMのない端末 には、ソフトウェアではなくハードウェア更新が必要になりそう
    • BBMもそういう仕組みで動いていた気がするが、確信はない
      OS全体のセキュリティの一部というより、少なくともAppleの Lockdown Mode に入るような機能に思える
    • そうかもしれないが、Appleはたった今 RCS対応 も発表した: https://9to5mac.com/2023/11/16/apple-rcs-coming-to-iphone/
      もしかすると今をオープンな方向へ舵を切る良い機会と見ているのかもしれない
  • 契約の解明は見事だが、iMessageインフラスタック も気になる
    とてつもない規模なのにこれほど安定して動いている一方で、Appleの他のWebサービス、たとえばフォーラムや開発者ポータルはバグも多く未完成に感じられるので、なおさら不思議だ

    • 本当に驚異的なのは、Apple Push Notification service がiMessageだけを運んでいるわけではないこと
      すべてのサードパーティ製メッセンジャーアプリのプッシュ通知もこれを通るし、通知のある非メッセンジャーアプリも同様
      内部のサイレント通知も含まれる。Macでカレンダーに会議を追加すると、iCloudデータが変わったので更新しろというプッシュがiPhoneに送られ、iCloud Driveのファイルを変更すると他の端末との同期のためにプッシュが飛ぶ
      着信があるとContinuityでMacも鳴るが、これもiMessageのような暗号化されたプッシュ通知だ
      このサービスを1秒あたりいったい何件のメッセージが通過しているのか気になる
  • これは Hack Club にぴったりの題材。参加してみるといいかも: https://hackclub.com/

  • 本当にすごい仕事だ
    この分野にどう入ったのかも短く書いてくれるとよさそう
    Redditには、技術が得意になりたい、プログラミングを学びたい、技術職に就く方法を考えている高校生や大学生が多いので、そういう視点はかなり役に立つと思う

    • 秘訣というより、とてつもない量の 継続的な練習 と、若い頃に好きなことへ注ぎ込めるほぼ無限のエネルギー、そして理解のある親やロールモデルがいた可能性が高そう
    • 高校時代はほぼ一日中、自分の作業に使える時間があった
      早く終わらせること、空き時間、本来そうしてはいけない場面でこっそり自分のことをやることで、約6か月でアプリを作って公開できたし、生産性も非常に高かった
  • すごく気になるのだが、話題が本当に opertunistic なのか、それとも筆者のタイプミスなのかわからない
    referer のように世代を超えて化石化していく タイプミス は興味深い

    • 残念ながら自分のコードにもタイプミスは多い :P
      ただ、これがApple側のタイプミスなのかはわからないが、確かに妙ではある。ここでは WindowsSerial のようにsを1つ多く付けたものではなく、WindowSerial を使うべきだ
      https://github.com/JJTech0130/pypush/blob/8b33c0ee5d540d8ac7...
    • コードではその値を使っていないようだが、おそらく整数コードなので、筆者の スペルミス である可能性が高そう
  • 関連する話題がもう1つある: https://news.ycombinator.com/item?id=38531759

  • 今日のiMessageリバースエンジニアリングの話題の土台になったオープンソースプロジェクト pypush は、MongoDBのServer Side Public Licenseで配布されており、所有者はBeeper
    JJTechがDiscordで話したところによると、権利をBeeperに売却したとのこと
    ライブラリ自体は素晴らしいが、非常に強いコピーレフトライセンスなので、どこに使えるかには影響がありそう

    • 次は 逆リバースエンジニアリング の番だ
  • IDS登録リクエストを作るのに必要な「validation data」は、Appleが非Apple端末にiMessageを使わせないための確認メカニズムだというが、EUの DSAやDMA が施行されたらこれが違反になるのか気になる

    • DSAやDMAは、Appleのサーバーに好きなようにリクエストする権利を魔法のように与えるわけではないし、Appleに特定の有効な応答を必ず返させるよう強制するものでもない
      AppleがどのようにDSAやDMAを順守するとしても、このやり方ではないはず
    • とりわけ、iOSが今や RCS をサポートするようになったので、なおさらそうだ
      1st-partyのクロスプラットフォームiMessageは、しょせん技術オタクたちのかなわぬ夢に近く、個人的にはそれで十分だと思う
  • Beeper Miniの発表文 [1] を見ると、ユーザーはApple IDなしでも電話番号を登録してiMessageを送受信できるとはっきり書かれている
    また、端末とAppleが直接通信すると説明している
    だがこの記事では、IDSがiMessageの鍵サーバーとして使われ、IDS登録の最初の段階ではApple IDのユーザー名とパスワードで認証トークンを受け取り、登録後に受け取ったidentity keypairで公開鍵の問い合わせを行うとある
    だとすると、Beeper Miniアプリが任意のAndroid電話番号をどうやってIDSに公開鍵として登録し、受信者の公開鍵問い合わせまで Apple IDなしで 行うのかが疑問だ
    答えは、本文や [1] のどこでもほとんど説明されていない SMS Gateway のようで、それが秘密の材料に見える
    [1] https://blog.beeper.com/i/139416474/security-and-privacy

    • AndroidスマホにBeeper Miniをインストールしてみたが、電話番号登録のためにAppleへSMSを送ろうとして失敗エラーが出た後、Apple ID の入力を求める画面が表示された
  • 本当に驚くべき仕事だ
    ただ、記事中で既存のpair形式はドキュメントがより整っていて実装しやすいが、新しいpair-ec形式のようなSignal類似の「pre-keys」を用いた 前方秘匿性 を提供しないとしている点は引っかかる
    最新、つまりECIESを使うiMessageが実際にpre-keyを使っている根拠があるのかはわからない
    自分には、暗号化、あるいは署名の部分でRSAの代わりにECIESを差し込んだ程度に見え、それだけでは前方秘匿性は生まれない
    根拠がないなら、RSA・楕円曲線・前方秘匿性の関係を誤解しているのかもしれない
    WikipediaのiMessage記事も同じ誤りを広めているようだし、引用されている参考文献も実際にはそうした主張をしていない