This repository has been archived by the owner on May 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 440
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
529 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
Client/Frontend/Browser/User Scripts/ARC4RandomNumberGenerator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright 2022 The Brave Authors. All rights reserved. | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
import Foundation | ||
|
||
/// A seeded random number generator taken from GameplayKit which can be found here: | ||
/// https://github.com/apple/swift/blob/bc8f9e61d333b8f7a625f74d48ef0b554726e349/stdlib/public/TensorFlow/Random.swift | ||
public struct ARC4RandomNumberGenerator: RandomNumberGenerator { | ||
private var state: [UInt8] = Array(0...255) | ||
private var iPos: UInt8 = 0 | ||
private var jPos: UInt8 = 0 | ||
|
||
public init<T: BinaryInteger>(seed: T) { | ||
var newSeed: [UInt8] = [] | ||
|
||
for i in 0..<(seed.bitWidth / UInt8.bitWidth) { | ||
newSeed.append(UInt8(truncatingIfNeeded: seed >> (UInt8.bitWidth * i))) | ||
} | ||
|
||
self.init(seed: newSeed) | ||
} | ||
|
||
/// Initialize ARC4RandomNumberGenerator using an array of UInt8. The array | ||
/// must have length between 1 and 256 inclusive. | ||
public init(seed: [UInt8]) { | ||
precondition(seed.count > 0, "Length of seed must be positive") | ||
precondition(seed.count <= 256, "Length of seed must be at most 256") | ||
var j: UInt8 = 0 | ||
for i: UInt8 in 0...255 { | ||
j &+= S(i) &+ seed[Int(i) % seed.count] | ||
swapAt(i, j) | ||
} | ||
} | ||
|
||
/// Produce the next random UInt64 from the stream, and advance the internal state. | ||
public mutating func next() -> UInt64 { | ||
var result: UInt64 = 0 | ||
for _ in 0..<UInt64.bitWidth / UInt8.bitWidth { | ||
result <<= UInt8.bitWidth | ||
result += UInt64(nextByte()) | ||
} | ||
|
||
print(result) | ||
return result | ||
} | ||
|
||
/// Helper to access the state. | ||
private func S(_ index: UInt8) -> UInt8 { | ||
return state[Int(index)] | ||
} | ||
|
||
/// Helper to swap elements of the state. | ||
private mutating func swapAt(_ i: UInt8, _ j: UInt8) { | ||
state.swapAt(Int(i), Int(j)) | ||
} | ||
|
||
/// Generates the next byte in the keystream. | ||
private mutating func nextByte() -> UInt8 { | ||
iPos &+= 1 | ||
jPos &+= S(iPos) | ||
swapAt(iPos, jPos) | ||
return S(S(iPos) &+ S(jPos)) | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
Client/Frontend/Browser/User Scripts/FarblingProtectionHelper.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Copyright 2022 The Brave Authors. All rights reserved. | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
import Foundation | ||
|
||
/// A class that helps in creating farbling data | ||
class FarblingProtectionHelper { | ||
/// Variables representing the prefix of a randomly generated strings used as the plugin name | ||
private static let pluginNameFirstParts: [String?] = [ | ||
"Chrome", "Chromium", "Brave", "Web", "Browser", | ||
"OpenSource", "Online", "JavaScript", "WebKit", | ||
"Web-Kit", "WK", nil | ||
] | ||
|
||
/// Variables representing the middle of a randomly generated strings used as the plugin name | ||
private static let pluginNameSecondParts: [String?] = [ | ||
"PDF", "Portable Document Format", | ||
"portable-document-format", "document", "doc", | ||
"PDF and PS", "com.adobe.pdf", nil | ||
] | ||
|
||
/// Variables representing the suffix of a randomly generated strings used as the plugin name | ||
private static let pluginNameThirdParts: [String?] = [ | ||
"Viewer", "Renderer", "Display", "Plugin", | ||
"plug-in", "plug in", "extension", nil | ||
] | ||
|
||
/// Generate fake plugin data to be injected into the farbling protection script | ||
static func makeFakePluginData(from randomManager: RandomManager) -> String { | ||
var generator = ARC4RandomNumberGenerator(seed: randomManager.seed) | ||
let pluginCount = Int.random(in: 1...3, using: &generator) | ||
|
||
// Generate 1 to 3 fake plugins | ||
let fakePlugins = (0..<pluginCount).map { pluginIndex -> JSDataType in | ||
let mimeTypesCount = Int.random(in: 1...3, using: &generator) | ||
|
||
// Generate 1 to 3 fake mime types | ||
let mimeTypes = (0..<mimeTypesCount).map { mimeTypeIndex -> JSDataType in | ||
return .object([ | ||
"suffixes": .string("pdf"), | ||
"type": .string("application/pdf"), | ||
"description": .string(randomPluginName(from: &generator)) | ||
]) | ||
} | ||
|
||
return .object([ | ||
"name": .string(randomPluginName(from: &generator)), | ||
"filename": .string(""), | ||
"description": .string(randomPluginName(from: &generator)), | ||
"mimeTypes": .array(mimeTypes) | ||
]) | ||
} | ||
|
||
// Convert the object into a string and return it | ||
let fakeData: JSDataType = .array(fakePlugins) | ||
return String(describing: fakeData) | ||
} | ||
|
||
/// Generate a random string using a prefix, middle and suffix where any of those may be empty. | ||
/// - Note: May result in an empty string. | ||
static func randomPluginName<T: RandomNumberGenerator>(from generator: inout T) -> String { | ||
return [ | ||
pluginNameFirstParts.randomElement(using: &generator) ?? nil, | ||
pluginNameSecondParts.randomElement(using: &generator) ?? nil, | ||
pluginNameThirdParts.randomElement(using: &generator) ?? nil | ||
].compactMap({ $0 }).joined(separator: " ") | ||
} | ||
} |
Oops, something went wrong.