2021-06-29 12:23:00 -05:00
|
|
|
//
|
2021-08-06 14:28:11 -07:00
|
|
|
// Copyright RevenueCat Inc. All Rights Reserved.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the MIT License (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// https://opensource.org/licenses/MIT
|
|
|
|
|
//
|
2021-06-29 12:23:00 -05:00
|
|
|
// Data+Extensions.swift
|
2021-08-26 13:54:50 -07:00
|
|
|
// Purchases
|
2021-06-29 12:23:00 -05:00
|
|
|
//
|
|
|
|
|
// Created by Josh Holtz on 6/28/21.
|
|
|
|
|
//
|
|
|
|
|
|
2023-01-12 11:48:32 -08:00
|
|
|
import CommonCrypto
|
|
|
|
|
import CryptoKit
|
2021-06-29 12:23:00 -05:00
|
|
|
import Foundation
|
|
|
|
|
|
2021-08-06 14:28:11 -07:00
|
|
|
extension Data {
|
|
|
|
|
|
2021-08-25 16:08:49 -07:00
|
|
|
var asString: String {
|
2023-06-23 07:31:55 -07:00
|
|
|
return Self.hexString(
|
|
|
|
|
self
|
|
|
|
|
.lazy
|
|
|
|
|
.map { $0 } // Extract byte
|
|
|
|
|
.makeIterator()
|
|
|
|
|
)
|
2021-08-06 14:28:11 -07:00
|
|
|
}
|
|
|
|
|
|
2023-01-12 11:48:32 -08:00
|
|
|
/// - Returns: `UUID` from the first 16 bytes of the underlying data.
|
|
|
|
|
var uuid: UUID? {
|
|
|
|
|
/// This implementation is equivalent to `return NSUUID(uuidBytes: [UInt8](self)) as UUID`
|
|
|
|
|
/// but ensures that the `Data` isn't unnecessarily copied in memory.
|
|
|
|
|
return self.withUnsafeBytes {
|
|
|
|
|
guard let baseAddress = $0.bindMemory(to: UInt8.self).baseAddress else {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NSUUID(uuidBytes: baseAddress) as UUID
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// - Returns: a string representing a fetch token.
|
2021-08-25 16:08:49 -07:00
|
|
|
var asFetchToken: String {
|
2021-08-09 11:10:48 -07:00
|
|
|
return self.base64EncodedString()
|
2021-08-06 14:28:11 -07:00
|
|
|
}
|
|
|
|
|
|
2023-07-13 07:45:16 -07:00
|
|
|
/// - Returns: a hash representation of the underlying bytes, using SHA256.
|
2023-01-12 11:48:32 -08:00
|
|
|
var hashString: String {
|
2024-07-01 12:37:21 -07:00
|
|
|
var sha256 = SHA256()
|
|
|
|
|
return self.hashString(with: &sha256)
|
2023-06-23 10:45:57 -07:00
|
|
|
}
|
2023-01-12 11:48:32 -08:00
|
|
|
|
2023-06-23 10:45:57 -07:00
|
|
|
/// - Returns: the SHA1 hash of the underlying bytes.
|
|
|
|
|
var sha1: Data {
|
2024-07-01 12:37:21 -07:00
|
|
|
var sha1 = Insecure.SHA1()
|
|
|
|
|
return self.hash(with: &sha1)
|
2023-01-12 11:48:32 -08:00
|
|
|
}
|
|
|
|
|
|
2023-07-13 07:45:16 -07:00
|
|
|
fileprivate static func hexString(_ iterator: Array<UInt8>.Iterator) -> String {
|
2023-01-12 11:48:32 -08:00
|
|
|
return iterator
|
|
|
|
|
.lazy
|
|
|
|
|
.map { String(format: "%02x", $0) }
|
|
|
|
|
.joined()
|
2021-12-01 20:25:04 +01:00
|
|
|
}
|
|
|
|
|
|
2021-06-29 12:23:00 -05:00
|
|
|
}
|
2023-02-08 09:05:20 -08:00
|
|
|
|
|
|
|
|
extension Data {
|
|
|
|
|
|
|
|
|
|
static func randomNonce() -> Data {
|
|
|
|
|
return Data(ChaChaPoly.Nonce())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static let nonceLength = 12
|
|
|
|
|
|
|
|
|
|
}
|
2023-06-23 10:45:57 -07:00
|
|
|
|
|
|
|
|
// MARK: - Hashing
|
|
|
|
|
|
2023-07-13 07:45:16 -07:00
|
|
|
extension HashFunction {
|
|
|
|
|
|
|
|
|
|
func toString() -> String {
|
|
|
|
|
return Data.hexString(self.finalize().makeIterator())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 10:45:57 -07:00
|
|
|
private extension Data {
|
|
|
|
|
|
|
|
|
|
func hashString<T: HashFunction>(with digest: inout T) -> String {
|
|
|
|
|
digest.update(data: self)
|
2023-07-13 07:45:16 -07:00
|
|
|
return digest.toString()
|
2023-06-23 10:45:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func hash<T: HashFunction>(with digest: inout T) -> Data {
|
|
|
|
|
digest.update(data: self)
|
|
|
|
|
|
|
|
|
|
return Data(digest.finalize())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|