Skip to content

Commit

Permalink
RUMM-2203 Add SHA256 implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ncreated committed Jun 22, 2022
1 parent 302651b commit 7bfb5c0
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 18 deletions.
12 changes: 12 additions & 0 deletions Datadog/Datadog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,10 @@
61DA8CAA28609C5B0074A606 /* Directories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DA8CA828609C5B0074A606 /* Directories.swift */; };
61DA8CAC2861C3720074A606 /* DirectoriesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DA8CAB2861C3720074A606 /* DirectoriesTests.swift */; };
61DA8CAD2861C3720074A606 /* DirectoriesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DA8CAB2861C3720074A606 /* DirectoriesTests.swift */; };
61DA8CAF28620C760074A606 /* Cryptography.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DA8CAE28620C760074A606 /* Cryptography.swift */; };
61DA8CB028620C760074A606 /* Cryptography.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DA8CAE28620C760074A606 /* Cryptography.swift */; };
61DA8CB2286215DE0074A606 /* CryptographyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DA8CB1286215DE0074A606 /* CryptographyTests.swift */; };
61DA8CB3286215DE0074A606 /* CryptographyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DA8CB1286215DE0074A606 /* CryptographyTests.swift */; };
61DB33B225DEDFC200F7EA71 /* CustomObjcViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61DB33B125DEDFC200F7EA71 /* CustomObjcViewController.m */; };
61DC6D922539E3E300FFAA22 /* LoggingCommonAsserts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DC6D912539E3E300FFAA22 /* LoggingCommonAsserts.swift */; };
61DE332625C826E4008E3EC2 /* CrashReportingFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DE332525C826E4008E3EC2 /* CrashReportingFeature.swift */; };
Expand Down Expand Up @@ -1644,6 +1648,8 @@
61DA20EF26C40121004AFE6D /* DataUploadStatusTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataUploadStatusTests.swift; sourceTree = "<group>"; };
61DA8CA828609C5B0074A606 /* Directories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Directories.swift; sourceTree = "<group>"; };
61DA8CAB2861C3720074A606 /* DirectoriesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectoriesTests.swift; sourceTree = "<group>"; };
61DA8CAE28620C760074A606 /* Cryptography.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cryptography.swift; sourceTree = "<group>"; };
61DA8CB1286215DE0074A606 /* CryptographyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptographyTests.swift; sourceTree = "<group>"; };
61DB33B025DEDFC200F7EA71 /* CustomObjcViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomObjcViewController.h; sourceTree = "<group>"; };
61DB33B125DEDFC200F7EA71 /* CustomObjcViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomObjcViewController.m; sourceTree = "<group>"; };
61DC6D912539E3E300FFAA22 /* LoggingCommonAsserts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingCommonAsserts.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2144,6 +2150,7 @@
611529A425E3DD51004F740E /* ValuePublisher.swift */,
9EAF0CF7275A2FDC0044E8CA /* HostsSanitizer.swift */,
613C6B8F2768FDDE00870CBF /* Sampler.swift */,
61DA8CAE28620C760074A606 /* Cryptography.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -3262,6 +3269,7 @@
61363D9E24D99BAA0084CD6F /* DDErrorTests.swift */,
9EA8A7F0275E1518007D6FDB /* HostsSanitizerTests.swift */,
613C6B912768FF3100870CBF /* SamplerTests.swift */,
61DA8CB1286215DE0074A606 /* CryptographyTests.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -5158,6 +5166,7 @@
D24C27EA270C8BEE005DE596 /* DataCompression.swift in Sources */,
61133BE42423979B00786299 /* LogEventEncoder.swift in Sources */,
B3FC3C0926526F0000DEED9E /* VitalInfo.swift in Sources */,
61DA8CAF28620C760074A606 /* Cryptography.swift in Sources */,
616F1FB32840125400651A3A /* RUMV2Configuration.swift in Sources */,
613E81F025A740140084B751 /* RUMEventsMapper.swift in Sources */,
61D980BA24E28D0100E03345 /* RUMIntegrations.swift in Sources */,
Expand Down Expand Up @@ -5252,6 +5261,7 @@
61C3638324361BE200C4D4E6 /* DatadogPrivateMocks.swift in Sources */,
61AD4E182451C7FF006E34EA /* TracingFeatureMocks.swift in Sources */,
9EAF0CF6275A21100044E8CA /* WKUserContentController+DatadogTests.swift in Sources */,
61DA8CB2286215DE0074A606 /* CryptographyTests.swift in Sources */,
615A4A8924A34FD700233986 /* DDTracerTests.swift in Sources */,
615A4A8724A3452800233986 /* DDTracerConfigurationTests.swift in Sources */,
613E81F725A743600084B751 /* RUMEventsMapperTests.swift in Sources */,
Expand Down Expand Up @@ -5692,6 +5702,7 @@
D2CB6E4527C50EAE00A62B57 /* RUMResourceScope.swift in Sources */,
D2CB6E4627C50EAE00A62B57 /* RUMSessionScope.swift in Sources */,
D2B3F04B2829510600C2B5EE /* DatadogCoreProtocol.swift in Sources */,
61DA8CB028620C760074A606 /* Cryptography.swift in Sources */,
D2DC4BF727F484AA00E4FB96 /* DataEncryption.swift in Sources */,
D2CB6E4727C50EAE00A62B57 /* TracingUUID.swift in Sources */,
D2CB6E4827C50EAE00A62B57 /* ServerDateProvider.swift in Sources */,
Expand Down Expand Up @@ -5882,6 +5893,7 @@
D2CB6F0027C520D400A62B57 /* RUMSessionMatcher.swift in Sources */,
D2CB6F0127C520D400A62B57 /* DatadogPrivateMocks.swift in Sources */,
D2CB6F0227C520D400A62B57 /* TracingFeatureMocks.swift in Sources */,
61DA8CB3286215DE0074A606 /* CryptographyTests.swift in Sources */,
D2CB6F0327C520D400A62B57 /* WKUserContentController+DatadogTests.swift in Sources */,
D2CB6F0427C520D400A62B57 /* DDTracerTests.swift in Sources */,
D2CB6F0527C520D400A62B57 /* DDTracerConfigurationTests.swift in Sources */,
Expand Down
32 changes: 32 additions & 0 deletions Sources/Datadog/Core/Utils/Cryptography.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2019-2020 Datadog, Inc.
*/

import Foundation
import CryptoKit
import CommonCrypto

/// Computes SHA256 for given `string`.
///
/// The implementation is portable between iOS versions - it uses `CryptoKit` on iOS13+ and fallbacks
/// to `CommonCrypto` on older devices.
internal func sha256(_ string: String) -> String {
guard let data = string.data(using: .utf8) else {
return string
}

if #available(iOS 13.0, tvOS 13.0, *) { // Compute SHA256 with `CryptoKit`
let digest = SHA256.hash(data: data)
return digest
.map({ byte in String(format: "%02x", byte) })
.joined(separator: "")
} else { // Fallback to SHA256 with `CommonCrypto`
var digest: [UInt8] = Array(repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
_ = data.withUnsafeBytes { CC_SHA256($0.baseAddress, UInt32(data.count), &digest) }
return digest
.map({ byte in String(format: "%02x", byte) })
.joined(separator: "")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class FeaturesConfigurationTests: XCTestCase {
}

func testClientToken() throws {
let clientToken: String = .mockRandom(among: "abcdefgh")
let clientToken: String = .mockRandom(among: .alphanumerics)
let configuration = try createConfiguration(clientToken: clientToken)

XCTAssertEqual(configuration.common.clientToken, clientToken)
Expand Down
31 changes: 31 additions & 0 deletions Tests/DatadogTests/Datadog/Core/Utils/CryptographyTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2019-2020 Datadog, Inc.
*/

import XCTest
@testable import Datadog

class CryptographyTests: XCTestCase {
func testItComputesSHA256ForArbitraryString() {
(0..<20).forEach { _ in
// Given
let string: String = .mockRandom(among: .allUnicodes, length: .mockRandom(min: 1, max: 500))

// When
let sha = sha256(string)

// Then
XCTAssertEqual(sha.count, 64, "It must use 64 characters")
XCTAssertFalse(sha.contains(where: { !$0.isASCII }), "It must contain only ASCII characters")
}
}

func testWhenComputingSHA256_itGivesStableResults() {
XCTAssertEqual(sha256(""), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
XCTAssertEqual(sha256("foo"), "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae")
XCTAssertEqual(sha256("Bar Bizz"), "ad81f738a40902ef4bb3e4d5f5b83d3e2b3b7edfcd1669ddd4004d4815d03a75")
XCTAssertEqual(sha256(".//,"), "822236197264817e14fdd2939d9dc68c7d0151a6265798dd29511315cb428c66")
}
}
2 changes: 1 addition & 1 deletion Tests/DatadogTests/Datadog/Mocks/CoreMocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ extension RequestBuilder.HTTPHeader: RandomMockable, AnyMockable {
static func mockRandom() -> RequestBuilder.HTTPHeader {
let all: [RequestBuilder.HTTPHeader] = [
.contentTypeHeader(contentType: Bool.random() ? .applicationJSON : .textPlainUTF8),
.userAgentHeader(appName: .mockRandom(among: .alphanumerics), appVersion: .alphanumerics, device: .mockAny()),
.userAgentHeader(appName: .mockRandom(among: .alphanumerics), appVersion: .mockRandom(among: .alphanumerics), device: .mockAny()),
.ddAPIKeyHeader(clientToken: .mockRandom(among: .alphanumerics)),
.ddEVPOriginHeader(source: .mockRandom(among: .alphanumerics)),
.ddEVPOriginVersionHeader(sdkVersion: .mockRandom(among: .alphanumerics)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,30 +224,76 @@ extension String: AnyMockable, RandomMockable {
}

static func mockRandom(length: Int) -> String {
return mockRandom(
among: .alphanumerics + " ",
length: length
)
return mockRandom(among: .alphanumericsAndWhitespace, length: length)
}

static func mockRandom(among characters: String, length: Int = 10) -> String {
return String((0..<length).map { _ in characters.randomElement()! })
static func mockRandom(among characters: RandomStringCharacterSet, length: Int = 10) -> String {
return characters.random(ofLength: length)
}

static func mockRepeating(character: Character, times: Int) -> String {
let characters = (0..<times).map { _ in character }
return String(characters)
}

static let alphanumerics = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
static let decimalDigits = "0123456789"
enum RandomStringCharacterSet {
private static let alphanumericCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
private static let decimalDigitCharacters = "0123456789"

/// Only letters and numbers (lower and upper cased).
case alphanumerics
/// Letters, numbers and whitespace (lower and upper cased).
case alphanumericsAndWhitespace
/// Only numbers.
case decimalDigits
/// Custom characters.
case custom(characters: String)
/// All Unicode scalars.
case allUnicodes

func random(ofLength length: Int) -> String {
var characters: String
switch self {
case .alphanumerics:
characters = RandomStringCharacterSet.alphanumericCharacters
case .alphanumericsAndWhitespace:
characters = RandomStringCharacterSet.alphanumericCharacters + " "
case .decimalDigits:
characters = RandomStringCharacterSet.decimalDigitCharacters
case .custom(let customCharacters):
characters = customCharacters
case .allUnicodes:
var view = UnicodeScalarView()
(0..<length).forEach { _ in view.append(Unicode.Scalar.mockRandom()) }
return String(view)
}

return String((0..<length).map { _ in characters.randomElement()! })
}
}
}

extension Character: AnyMockable, RandomMockable {
static func mockAny() -> Character { "c" }

static func mockRandom() -> Character {
String.alphanumerics.randomElement()!
return Character(Unicode.Scalar.mockRandom())
}
}

extension Unicode.Scalar: RandomMockable {
static func mockRandom() -> Self {
// From `Unicode.Scalar.init?(_ v: UInt32))`:
//
// > - Parameter v: The Unicode code point to use for the scalar. The
// > initializer succeeds if `v` is a valid Unicode scalar value---that is,
// > if `v` is in the range `0...0xD7FF` or `0xE000...0x10FFFF`. If `v` is
// > an invalid Unicode scalar value, the result is `nil`.
var codePoint: UInt32 = .mockRandom(min: 0x0, max: 0x10FFFF)
while codePoint > 0xD7FF && codePoint < 0xE000 {
codePoint = .mockRandom(min: 0x0, max: 0x10FFFF)
}
return Unicode.Scalar(codePoint)! // force-unwrap as we guarantee `randomCodePoint` is correct
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class RUMViewIdentityTests: XCTestCase {

func testGivenTwoUIViewControllers_whenComparingTheirRUMViewIdentity_itEqualsOnlyForTheSameInstance() {
// Given
let vc1 = createMockView(viewControllerClassName: .mockRandom(among: "abcdefghijklmnopqrstuvwxyz"))
let vc2 = createMockView(viewControllerClassName: .mockRandom(among: "abcdefghijklmnopqrstuvwxyz"))
let vc1 = createMockView(viewControllerClassName: .mockRandom(among: .alphanumerics))
let vc2 = createMockView(viewControllerClassName: .mockRandom(among: .alphanumerics))
let vc3: UIViewController? = nil

// When
Expand Down Expand Up @@ -53,7 +53,7 @@ class RUMViewIdentityTests: XCTestCase {

func testGivenTwoRUMViewIdentitiesOfDifferentKind_whenComparing_theyDoNotEqual() {
// Given
let vc = createMockView(viewControllerClassName: .mockRandom(among: "abcdefghijklmnopqrstuvwxyz"))
let vc = createMockView(viewControllerClassName: .mockRandom(among: .alphanumerics))
let key: String = .mockRandom()

// When
Expand Down
8 changes: 4 additions & 4 deletions Tests/DatadogTests/Datadog/TracerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -874,11 +874,11 @@ class TracerTests: XCTestCase {
testThreadSafety(
closures: [
// swiftlint:disable opening_brace
{ span in span.setTag(key: .mockRandom(among: "abcde", length: 1), value: "value") },
{ span in span.setBaggageItem(key: .mockRandom(among: "abcde", length: 1), value: "value") },
{ span in _ = span.baggageItem(withKey: .mockRandom(among: "abcde")) },
{ span in span.setTag(key: .mockRandom(among: .alphanumerics, length: 1), value: "value") },
{ span in span.setBaggageItem(key: .mockRandom(among: .alphanumerics, length: 1), value: "value") },
{ span in _ = span.baggageItem(withKey: .mockRandom(among: .alphanumerics)) },
{ span in _ = span.context.forEachBaggageItem { _, _ in return false } },
{ span in span.log(fields: [.mockRandom(among: "abcde", length: 1): "value"]) },
{ span in span.log(fields: [.mockRandom(among: .alphanumerics, length: 1): "value"]) },
{ span in span.finish() }
// swiftlint:enable opening_brace
]
Expand Down

0 comments on commit 7bfb5c0

Please sign in to comment.