Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

閲覧者のユーザーエージェントを三角関数で判定できるか?

概要

先日ふと自分のPCのフィンガープリントを取ってみたところ「IPアドレス」など様々な項目が並ぶ中に「Math.tan」という変な項目を見つけました。

「なぜ三角関数が出てくるの?」と気になって調べてみたところ、三角関数の値はブラウザやOSの実装により微妙に異なることがあり、特定の式をブラウザに計算させることで利用者を識別する手段になり得る1という話でした。

面白そうだなと思ったので、本記事ではその手法で実際どの程度までブラウザ/OSを判別できるのか調査してみました。

検証方法

今回は様々な文献12の情報を参考に、以下の式を各OSの各ブラウザに計算させました。

  • tan(-1e300)
  • cosh(10)(厳密には三角関数の類似ですが)

これら以外も10数種類ほど試したのですが、判別に使えたのはこの2つのみでした。

試したOSとバージョン
  • macOS Catalina (ver.10.15.6)
  • Windows 10 (OSビルド 19041.804)
  • iOS (ver.14.4)
  • Android (ver.11)
試したブラウザ(各最新版)
  • Google Chrome
  • Mozilla Firefox
  • Safari
  • Vivaldi
  • Microsoft Edge
  • IE11

結果

macOS

ブラウザ Math.tan(-1e300) Math.cosh(10)
Chrome, Edge, Vivaldi -1.4214488238747245 11013.232920103324
safari -1.4214488238747247 11013.232920103323
Firefox -1.4214488238747247 11013.232920103324

末尾の桁に着目してください。
どうやらブラウザのJSエンジンごとに異なる計算結果が出ているようです。

Windows 10

ブラウザ Math.tan(-1e300) Math.cosh(10)
Chrome, Firefox, Edge, Vivaldi -1.4214488238747245 11013.232920103324
IE11 -4.987183803371025 非対応😌

モダンブラウザは全て同一の値で、IE のみハチャメチャな結果となりました。

iOS

ブラウザ Math.tan(-1e300) Math.cosh(10)
Chrome, Firefox, Edge, Safari -1.4214488238747243 11013.232920103323

全ブラウザで同じ値となりました。
iOS は全てのブラウザが Webkit ベースらしいので、これは納得しやすい結果です。

Android

ブラウザ名称 Math.tan(-1e300) Math.cosh(10)
Chrome, Firefox, Edge, Vivaldi -1.4214488238747245 11013.232920103324

こちらも何故か iOS 同様全ブラウザで共通の結果となりました(値自体は iOS と異なっています)。

まとめ

  • macの結果を見て「おっ、JSエンジンの判別ができるのかな?」と思ったけどそんなことはなかった
  • モバイルに限定すると、ブラウザごとの差異はなかったがOSの判別はできた

完全な判別はできなかったものの、ユーザーエージェント文字列と異なり偽装等の問題も少なそうなので補助的な特徴点としては使えるのかもしれません(ただ情報量としてはそれほど大きくないようです2)。

ちなみにいまお使いのブラウザによる計算結果は以下です。

See the Pen Trigonometry Fingerprint by Masa-Shin (@POPOPON) on CodePen.

今回調査していないOS/ブラウザをお使いの方はぜひ結果をコメント等で教えてください。

補遺A: ブラウザ/OS等により値が異なる背景

EcmaScript の仕様では、例えばMath.tan(x)は「実装に依存した近似値」を返すと定義されています。
つまり具体的にどういう手法で計算し誤差をどう丸めるかについては何も規定されていません。

また IEEE 754 標準も三角関数の(実装は推奨しているものの)計算手法自体については特に規定していないかと思います[要出典]

そのためブラウザ/OSが三角関数の計算や端数処理をどう実装しているかにより、返り値が変わる事態になってしまっているようです。

追記:CPUも関係していそう

某サイトで「macOSでもM1チップだとtanの値が違った」という興味深いコメントを目にしました。
また 32bit CPU の場合も値が異なるらしいので、ブラウザ/OSなどソフトウェア面だけではなくハードウェア面の性質も捉えた特徴点となっているようです。

関連ツイート

補遺B: 実際の値は?(改稿版)

任意精度計算ができるという Python パッケージ mpmath を利用し計算してみました。

コード
from mpmath import mp

mp.dps = 300 # 有効桁数
print(mp.tan("-1e300"))
print(mp.cosh(10))

(この節のコードはkasai氏の助言を受け改稿しています。ありがとうございました)

  • 有効桁数を300にしているのは、実際に必要な桁数よりも有効桁数を大きくした方が正確な値が求まりやすいためです(mpmathのドキュメント)。

  • -1e300は桁数が大き過ぎるため mpmath では文字列として渡す必要があります。

結果

Math.tan(-1e300) Math.cosh(10)
-5.8600819259448981 11013.232920103323
  • Math.tan(-1e300)はブラウザが計算した値と大きく異なるものとなりました。
  • Math.cosh(10)については「macOS の safari」および「iOS の各ブラウザ」が見事ピタリ賞を獲得しました🎉

参考文献

POPOPON
Vue好き
commew
ゆるく、つながる、たすけあう 困りごとの共有や相談、学習報告などを通して「ひとりで働いていても孤独ではない」空間へ
https://commew.net/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away