Device fingerprinting
Device fingerprinting is a method used to identify and track devices based on their unique characteristics like operating system, screen resolutions, fonts, installed plugins, etc., When we combine these data points together, they will create an unique fingerprint for the device.
How device fingerprint helps?
Device fingerprinting plays a vital role in various areas.
1. Security:
Device fingerprinting serves to assist in the detection and prevention of fraudulent activities.
Example 1: if an individual attempts to access your bank account from an unfamiliar device, the bank could utilize device fingerprinting to assess its authenticity.
Example 2: an e-commerce platform may leverage device fingerprinting to flag suspicious transactions, such as attempted credit card fraud.
2. Targeted Advertising:
This is a common occurrence you're likely to encounter frequently. Advertisers utilize device fingerprinting to track user behaviour across various websites, and construct a detailed profiles of their interests. This enables them to deliver targeted ads that are more relevant to you.
3. Content Personalization:
Websites and applications use device fingerprinting to identify what content user likes, and to identify what content is relevant to you. For instance, a news website might utilize device fingerprinting to present news articles more aligned with your interests, using the data such as your location or browsing history.
4. Rights Management:
Device fingerprinting serves to enforce digital rights management (DRM) restrictions. For instance, a streaming service could utilize device fingerprinting to deter users from sharing their accounts.
Imagine you're subscribed to a streaming service like Netflix, which employs DRM to regulate content access. To discourage account sharing, the service imposes certain limitations.
Upon logging in to Netflix on your device (whether it's a laptop, phone, etc.), a unique identifier is generated for your device. This fingerprint is crafted from various specifics concerning your device's hardware and software, such as the operating system, browser version, installed fonts, screen resolution, and more. Netflix retains data regarding the devices you've logged in from, typically allowing a specific number of devices to be linked to your account. When attempting to access Netflix from a new device, the service compares its fingerprint to the authorized ones. If a match is found, signifying login from a registered device, Netflix grants access. However, if the fingerprint fails to match any authorized devices, Netflix may restrict access or prompt you to verify your identity. This precautionary measure prevents unauthorized use of your account on unregistered devices.
Let's build a simple device fingerprint program in JavaScript and Java.
We can use following system characterstics to calculate device fingerprint.
1. User-Agent Header: This header string identifies the web browser and its version information. Whenever you visit a website, this information is typically sent automatically.
2. Screen Resolution: The width and height of your screen in pixels.
3. Color Depth: The number of bits used to represent colors on your display. For instance, a higher color depth means your device can display a wider range of colors.
4. Installed Fonts: A list of fonts available on your device. This can be unique depending on what fonts you have installed besides the default ones.
5. Timezone: The user's time zone setting.
6. System Language: The user's preferred language setting on their device.
7. WebGL Information: Details about the device's graphics card and its capabilities, obtained through the WebGL API. This can reveal information about the graphics vendor, renderer, and available extensions.
8. Hardware Vendors: Information about the device's hardware manufacturers, like the graphics card vendor or motherboard manufacturer, can sometimes be gleaned.
deviceFingerPrint.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Device Fingerprint</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
h1 {
margin-bottom: 20px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
th, td {
padding: 10px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #f2f2f2;
}
.digital-signature {
margin-top: 20px;
font-size: 18px;
}
</style>
<script>
window.onload = function() {
var fingerprintData = {
"User-Agent": navigator.userAgent,
"Screen Resolution": screen.width + "x" + screen.height,
"Color Depth": screen.colorDepth,
"Installed Fonts": getInstalledFonts(),
"Timezone": getTimezone(),
"System Language": navigator.language,
"WebGL Information": getWebGLInfo(),
"Hardware Vendors": getHardwareVendors()
};
displayFingerprintData(fingerprintData);
};
function displayFingerprintData(data) {
var table = document.createElement("table");
var tbody = table.createTBody();
for (var key in data) {
var row = tbody.insertRow();
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.textContent = key;
cell2.textContent = data[key];
}
document.body.appendChild(table);
calculateDigitalSignature(data).then(function(digitalSignature) {
var signatureElement = document.createElement("div");
signatureElement.classList.add("digital-signature");
signatureElement.textContent = "Digital Signature: " + digitalSignature;
document.body.appendChild(signatureElement);
});
}
function calculateDigitalSignature(data) {
var jsonString = JSON.stringify(data);
return sha256(jsonString);
}
function sha256(input) {
// Use the built-in Crypto API to compute SHA-256 hash
var buffer = new TextEncoder("utf-8").encode(input);
return crypto.subtle.digest("SHA-256", buffer).then(function(hash) {
return hex(hash);
});
}
function hex(buffer) {
var hexCodes = [];
var view = new DataView(buffer);
for (var i = 0; i < view.byteLength; i += 4) {
var value = view.getUint32(i);
var stringValue = value.toString(16);
var padding = '00000000';
var paddedValue = (padding + stringValue).slice(-padding.length);
hexCodes.push(paddedValue);
}
return hexCodes.join("");
}
function getInstalledFonts() {
var fonts = [];
var fontList = document.fonts;
fontList.forEach(function(font) {
fonts.push(font.family);
});
return fonts.join(", ");
}
function getTimezone() {
return new Date().getTimezoneOffset();
}
function getWebGLInfo() {
var canvas = document.createElement("canvas");
var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
if (!gl) {
return "WebGL not supported";
}
var info = {
vendor: gl.getParameter(gl.VENDOR),
renderer: gl.getParameter(gl.RENDERER),
extensions: gl.getSupportedExtensions()
};
return JSON.stringify(info);
}
function getHardwareVendors() {
// You may need to use additional libraries or APIs to gather hardware vendor information.
return "Not implemented";
}
</script>
</head>
<body>
<h1>Device Fingerprint</h1>
<p>This page collects data to create a device fingerprint:</p>
</body>
</html>
Similar application in Java.
DeviceFingerprint.java
package com.sample.app;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
public class DeviceFingerprint {
public static void main(String[] args) throws NoSuchAlgorithmException {
Map<String, String> fingerprintData = new HashMap<>();
fingerprintData.put("User-Agent", System.getProperty("http.agent"));
fingerprintData.put("Screen Resolution", getScreenResolution());
fingerprintData.put("Color Depth", String.valueOf(getColorDepth()));
fingerprintData.put("Installed Fonts", getInstalledFonts());
fingerprintData.put("Timezone", getTimezone());
fingerprintData.put("System Language", System.getProperty("user.language"));
fingerprintData.put("WebGL Information", "Not implemented"); // Add logic to get WebGL info
fingerprintData.put("Hardware Vendors", "Not implemented"); // Add logic to get hardware vendors
System.out.println("Device Fingerprint Data:");
fingerprintData.forEach((key, value) -> System.out.println(key + ": " + value));
String digitalSignature = calculateDigitalSignature(fingerprintData);
System.out.println("Digital Signature: " + digitalSignature);
}
private static String calculateDigitalSignature(Map<String, String> data) throws NoSuchAlgorithmException {
StringBuilder jsonString = new StringBuilder();
jsonString.append("{");
data.forEach((key, value) -> jsonString.append("\"").append(key).append("\":\"").append(value).append("\","));
jsonString.deleteCharAt(jsonString.length() - 1); // Remove the last comma
jsonString.append("}");
return sha256(jsonString.toString());
}
private static String sha256(String input) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashbytes = digest.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hashbytes);
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
private static String getScreenResolution() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
return screenSize.width + "x" + screenSize.height;
}
private static int getColorDepth() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getBitDepth();
}
private static String getInstalledFonts() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = ge.getAvailableFontFamilyNames();
StringBuilder fontList = new StringBuilder();
for (String fontName : fontNames) {
fontList.append(fontName).append(", ");
}
return fontList.toString();
}
private static String getTimezone() {
TimeZone timeZone = TimeZone.getDefault();
return timeZone.getDisplayName(false, TimeZone.SHORT);
}
}
References
https://dataprivacylab.org/projects/identifiability/paper1.pdf
No comments:
Post a Comment