개요
많은 회사에서 retargeting 을 위해서 사용자를 특정하고, 추적하고싶어한다. 하지만 최근의 트렌드는 개인정보에 민감해서 점점 native 앱들이 정보를 제한함으로써 tracking 을 하기 어려워지고있다. (최근 iOS 의 업데이트로 인해서 광고 회사의 매출이 조 단위로 줄었다는 기사를 보았다 (기사))
이로 인해 rebitly 팀 내에서도 targeting 정확성을 높일 방법을 찾는 도중 browser fingerprint(이하 BFP) 라는 기술이란 것을 발견했다.
BFP 는 웹사이트 소유자가 client 가 가진 변수들의 데이터 집합을 통해서 데이터들을 수집하고, user 를 특정할 수 있도록 하는 것이다. 수집할 수 있는 데이터들은 아래와 같다
•
Device model
•
Operating system (OS)
•
Screen resolution
•
Time zones
•
File format identifiers
•
Timestamp
•
User-agent (UA) string
•
Language settings
•
Plugins
•
Extensions
example of browser fingerprint
attributes and their entropy
이 정보들을 합치면 통계적으로 286,777개 중 1개만 일치한다고 한다 (참고)(해외의 사례라 우리나라에서는 얼마만큼의 정확성을 가질지 모른다. 내 가설로는 해외는 상대적으로 다양한 기기를 사용하고, 다양한 케이스들이 있을 것이라고 생각한다. 따라서 상대적으로 정확도는 국내에서는 낮을수도 있다.)
ID 위조 및 불법적인 신용카드 사용 등을 파악하거나 방지하는 용도로도 쓰이지만 마케팅 개인화를 위해서 사용자를 특정하기 위해서 사용되기도 한다.
기존 cookie 사용 방식과의 차이점
•
Europe 에서는 마케팅 목적을 위해서 사용되는 fingerprint 수집은 명시적으로 사용자의 동의를 구해야함 (cookie 와 마찬가지인듯)
•
미국에서는 웹 추적을 규율하는 법 규제는 없지만 최소한 California Consumer Privacy Act, Vermont's Data Broker Law 에서는 온라인 추적 및 데이터 수집에 대해서 다루려고 한다. 하지만 여기에서 fingerprint 관련 언급은 없다.
•
쿠키는 사용자가 브라우저 단에서 지우거나 초기화가 가능하고, 설정을 통해서 cookie 를 사용하지 않는 등의 사용이 가능하지만, BFP 의 경우 정상적인 Javascript 및 browser 에서 제공하는 API 를 사용하기 때문에 아예 방지할 수 없다.
Attributes
다양한 browser 를 특정하는 다양한 attribute 들이 있지만 기술적으로 리서치가 필요한 canvas fingerprint, audio fingerprint 만 살펴보려고 한다.
canvas fingerprint
원리
canvas 는 javascript 를 통해서 텍스트나 그래픽을 그리기 위해서 사용되는 HTML5 API 다. CFP (canvas fingerprint) 는 다른 컴퓨터가 이미지 형식 수준 또는 시스템 수준의 이유에 따라 동일한 캔버스 이미지를 다르게 렌더링한다는 것을 기반으로 작동한다. 시스템 수준의 경우 운영 체제가 다른 글꼴로 제공되고 하위 픽셀 렌더링 및 앤티앨리어싱(참고)에 대해 다른 알고리즘과 설정을 사용하기 때문에 컴퓨터마다 동일한 이미지를 다르게 렌더링할 수 있다. (운영체제, 폰트 라이브러리, 그래픽카드, 그래픽 드라이버, 브라우저, sub-pixel somoothing, API 구현 차이, 디스플레이 등의 변수로 인해서 차이가 발생) 최대한 다양한 글자를 사용하면 더 잘 식별할 수 있다.
Arial 20px 를 렌더링하는 13가지 폰트들. 다 같은 소스 코드다.
code
canvas API toDataURL 함수를 사용해서 바이너리 픽셀 데이터의 Base64 인코딩 값을 얻은 후 hashing 하는 것을 볼 수 있다.
AudioContext fingerprint
원리
AudioContext
오디오 노드로 구성된 체인 전체를 의미함. 오디오 노드를 생성하거나 processing 을 컨트롤한다.
OfflineAudioContext
AudioCotext 와 다르게 audio 를 실제 하드웨어에 랜더링 하지 않는다는 특징을 가진다. 대신에 최대한 빠르게 audio 를 생성하고 AudioBuffer 에 저장한다. ⇒ 오디오 렌더링 장치가 아니라 데이터 구조가 되어 메모리에 담김.
const AudioContext =
window.OfflineAudioContext ||
window.webkitOfflineAudioContext
const context = new AudioContext(1, 5000, 44100)
// 첫 번 째 인수는 channel 수
// 두 번 째 인수는 sample 수
// 세 번 째 인수는 초당 sample 의 속도
JavaScript
복사
AdioBuffer
메모리에 저장된 audio snippet. 각 데이터는 샘플마다 1~-1 사이의 32bit 소수점 표시로 저장된다. multiple channel 을 보유할 수 있지만 목적 상 1개의 채널만 사용한다.
Oscillator
오디오 작업을 할 때 항상 소스가 필요하다. Oscillator 은 실제 오디오 파일을 재생하는 것이 아니라 수학적으로 sample 들을 생성한다.
기본적으로 sine 형태, 440Hz Frequency 로 생성하며 형태 및 Frequency 는 설정이 가능하다.
Compressor
Web Audio API 에서는 signal 이 가장 큰 부분의 소리를 줄여주거나 디스토션, 클리핑을 방지하는데 도움을 주는 DynamicsCompressorNode 를 제공한다. DynamicCompressorNode 는 다양한 properties 를 가지고 있는데, 이것을 통해서 브라우저 간에 다양성을 만들어준다.
code
code
왜 다른 결과가 나올까?
위 코드를 각각 다른 browser 에서 실행하면 다른 값이 나오는 것을 확인 할 수 있다.
역사적으로 모든 주요 브라우저 엔진(Blink, WebKit 및 Gecko)은 원래 WebKit 프로젝트를 위해 2011년과 2012년에 Google에서 개발한 코드를 기반으로 Web Audio API 구현을 기반으로 한다. 그 이후로 브라우저들은 많은 변경 작업을 거쳐왔다. 그 결과 많은 수학적 작업의 결과물은 차이점을 가지게 된다. 오디오 신호는 부동 소수점을 사용하기 때문에 특히 차이를 나타내는데 일조를 한다.
또한 브라우저는 SIMD와 같은 기능을 활용하기 위해 다양한 CPU 아키텍처 및 OS에 대해 다르게 구현한다. browser source code 를 보면 audio processing 은 OS features 를 사용하거 audio 전용 하드웨어를 사용하지 않고 오로지 CPU 에서 계산된다.
마무리
위 두가지 말고도 여러 Attribute 의 종합을 통해서 BFP 를 구현할 수 있다. 최종적으로 우리가 사용한 코드는 아래와 같다. (참고로 browser side 에서 얻을 수 있는 정보만 입력했다. ip 등과 같이 serverside 에서 얻을 수 있는 코드는 포함하지 않았다. code 는 device.info 를 참고했다.)
code
참고
Services
•
•
...