Files
purchases-ios/Sources/LocalReceiptParsing/Builders/ASN1ObjectIdentifierBuilder.swift
T
NachoSoto aae60d0f51 ReceiptParser: Sendable conformance (#1825)
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
2022-08-22 16:01:19 -07:00

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
}
}