mirror of
https://github.com/RevenueCat/purchases-ios
synced 2026-11-10 22:45:55 +05:45
For [CSDK-379]. Extracted from #1795 to make it easier to review this in isolation. Also made `ASN1ObjectIdentifierBuilder` an `enum` since we don't need to create instances of it to use it. [CSDK-379]: https://revenuecats.atlassian.net/browse/CSDK-379?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
58 lines
2.0 KiB
Swift
58 lines
2.0 KiB
Swift
//
|
|
// 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
|
|
//
|
|
// ASN1ObjectIdentifierBuilder.swift
|
|
//
|
|
// Created by Andrés Boedo on 7/28/20.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
enum ASN1ObjectIdentifierBuilder {
|
|
|
|
// info on the format: https://docs.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier
|
|
static func build(fromPayload payload: ArraySlice<UInt8>) throws -> ASN1ObjectIdentifier? {
|
|
guard let firstByte = payload.first else { return nil }
|
|
|
|
var objectIdentifierNumbers: [UInt] = []
|
|
objectIdentifierNumbers.append(UInt(firstByte / 40))
|
|
objectIdentifierNumbers.append(UInt(firstByte % 40))
|
|
|
|
let trailingPayload = payload.dropFirst()
|
|
let variableLengthQuantityNumbers = try decodeVariableLengthQuantity(payload: trailingPayload)
|
|
objectIdentifierNumbers += variableLengthQuantityNumbers
|
|
|
|
let objectIdentifierString = objectIdentifierNumbers.map { String($0) }
|
|
.joined(separator: ".")
|
|
return ASN1ObjectIdentifier(rawValue: objectIdentifierString)
|
|
}
|
|
}
|
|
|
|
private extension ASN1ObjectIdentifierBuilder {
|
|
|
|
// https://en.wikipedia.org/wiki/Variable-length_quantity
|
|
static func decodeVariableLengthQuantity(payload: ArraySlice<UInt8>) throws -> [UInt] {
|
|
var decodedNumbers = [UInt]()
|
|
|
|
var currentBuffer: UInt = 0
|
|
var isShortLength = false
|
|
for byte in payload {
|
|
isShortLength = try byte.bitAtIndex(0) == 0
|
|
let byteValue = UInt(try byte.valueInRange(from: 1, to: 7))
|
|
|
|
currentBuffer = (currentBuffer << 7) | byteValue
|
|
if isShortLength {
|
|
decodedNumbers.append(currentBuffer)
|
|
currentBuffer = 0
|
|
}
|
|
}
|
|
return decodedNumbers
|
|
}
|
|
}
|