Skip to content

Commit

Permalink
2.1.3: Fix iOS Build Number parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
JesusMcCloud committed Sep 12, 2024
1 parent 5ee54ac commit 9aa1c4f
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 98 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 2.1.3
- Fix Parsing of iOS Build Numbers
- Dependency Updates:
- Kotlin 2.0.20
- Serialization 1.7.2

## 2.1.2

- Rely on [Signum](https://github.com/a-sit-plus/signum) to transcode public keys
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

[![A-SIT Plus Official](https://img.shields.io/badge/A--SIT_Plus-official-005b79?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNDMuNzYyODYgMTg0LjgxOTk5Ij48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiIGNsaXBQYXRoVW5pdHM9InVzZXJTcGFjZU9uVXNlIj48cGF0aCBkPSJNMCA1OTUuMjhoODQxLjg5VjBIMFoiLz48L2NsaXBQYXRoPjwvZGVmcz48ZyBjbGlwLXBhdGg9InVybCgjYSkiIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMyAwIDAgLTEuMzMzMzMzMyAtNDgyLjI1IDUxNy41MykiPjxwYXRoIGZpbGw9IiMwMDViNzkiIGQ9Ik00MTUuNjcgMjQ5LjUzYy03LjE1LjA4LTEzLjk0IDEtMjAuMTcgMi43NWE1Mi4zMyA1Mi4zMyAwIDAgMC0xNy40OCA4LjQ2IDQwLjQzIDQwLjQzIDAgMCAwLTExLjk2IDE0LjU2Yy0yLjY4IDUuNDEtNC4xNCAxMS44NC00LjM1IDE5LjA5bC0uMDIgNi4xMnYyLjE3YS43MS43MSAwIDAgMCAuNy43M2gxNi41MmMuMzkgMCAuNy0uMzIuNzEtLjdsLjAxLTIuMmMwLTIuNi4wMi01LjgyLjAzLTYuMDcuMi00LjYgMS4yNC04LjY2IDMuMDgtMTIuMDZhMjguNTIgMjguNTIgMCAwIDEgOC4yMy05LjU4IDM1LjI1IDM1LjI1IDAgMCAxIDExLjk2LTUuNTggNTUuMzggNTUuMzggMCAwIDEgMTIuNTgtMS43NmM0LjMyLjEgOC42LjcgMTIuNzQgMS44YTM1LjA3IDM1LjA3IDAgMCAxIDExLjk2IDUuNTcgMjguNTQgMjguNTQgMCAwIDEgOC4yNCA5LjU3YzEuOTYgMy42NCAzIDguMDIgMy4xMiAxMy4wMnYyNC4wOUgzNjIuNGEuNy43IDAgMCAwLS43MS43VjMzNWMwIDguNDMuMDEgOC4wNS4wMSA4LjE0LjIgNy4zIDEuNjcgMTMuNzcgNC4zNiAxOS4yMmE0MC40MyA0MC40MyAwIDAgMCAxMS45NiAxNC41N2M1IDMuNzYgMTAuODcgNi42MSAxNy40OCA4LjQ2YTc3LjUgNzcuNSAwIDAgMCAyMC4wMiAyLjc3YzcuMTUtLjA3IDEzLjk0LTEgMjAuMTctMi43NGE1Mi4zIDUyLjMgMCAwIDAgMTcuNDgtOC40NiA0MC40IDQwLjQgMCAwIDAgMTEuOTUtMTQuNTdjMS42Mi0zLjI2IDMuNzctMTAuMDQgMy43Ny0xNC42OCAwLS4zOC0uMTctLjc0LS41NC0uODJsLTE2Ljg5LS40Yy0uMi0uMDQtLjM0LjM0LS4zNC41NCAwIC4yNy0uMDMuNC0uMDYuNi0uNSAyLjgyLTEuMzggNS40LTIuNjEgNy42OWEyOC41MyAyOC41MyAwIDAgMS04LjI0IDkuNTggMzUuMDEgMzUuMDEgMCAwIDEtMTEuOTYgNS41NyA1NS4yNSA1NS4yNSAwIDAgMS0xMi41NyAxLjc3Yy00LjMyLS4xLTguNjEtLjcxLTEyLjc1LTEuOGEzNS4wNSAzNS4wNSAwIDAgMS0xMS45Ni01LjU3IDI4LjUyIDI4LjUyIDAgMCAxLTguMjMtOS41OGMtMS44Ni0zLjQ0LTIuOS03LjU1LTMuMDktMTIuMmwtLjAxLTcuNDdoODkuMTZhLjcuNyAwIDAgMCAuNy0uNzJ2LTM5LjVjLS4xLTcuNjUtMS41OC0xNC40LTQuMzgtMjAuMDZhNDAuNCA0MC40IDAgMCAwLTExLjk1LTE0LjU2IDUyLjM3IDUyLjM3IDAgMCAwLTE3LjQ4LTguNDcgNzcuNTYgNzcuNTYgMCAwIDAtMjAuMDEtMi43N1oiLz48cGF0aCBmaWxsPSIjY2U0OTJlIiBkPSJNNDE5LjM4IDI4MC42M2gtNy41N2EuNy43IDAgMCAwLS43MS43MXYxNS40MmE4LjE3IDguMTcgMCAwIDAtMy43OCA2LjkgOC4yOCA4LjI4IDAgMCAwIDE2LjU0IDAgOC4yOSA4LjI5IDAgMCAwLTMuNzYtNi45di0xNS40MmEuNy43IDAgMCAwLS43Mi0uNzEiLz48L2c%2BPC9zdmc%2B&logoColor=white&labelColor=white)](https://a-sit-plus.github.io)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-brightgreen.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)
[![Kotlin](https://img.shields.io/badge/kotlin-2.0.0-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-2.0.20-blue.svg?logo=kotlin)](http://kotlinlang.org)
![Java](https://img.shields.io/badge/java-17-blue.svg?logo=OPENJDK)
![Build artifacts](https://github.com/a-sit-plus/warden/actions/workflows/gradle.yml/badge.svg)
[![Maven Central](https://img.shields.io/maven-central/v/at.asitplus/warden)](https://mvnrepository.com/artifact/at.asitplus/warden/)
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
plugins { id("at.asitplus.gradle.conventions") version "2.0.0+20240619" }
plugins { id("at.asitplus.gradle.conventions") version "2.0.0+20240904" }

group = "at.asitplus"
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
jdk.version=17
artifactVersion=2.1.2
artifactVersion=2.1.3
androidAttestationVersion=1.6.0
49 changes: 34 additions & 15 deletions warden/src/main/kotlin/AttestationService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -177,16 +177,26 @@ typealias ParsedVersions = Pair<SemVer?, BuildNumber?>
* * Major version: Within Apple, the major version is called the build train.
* * Minor version: For iOS and its descendants, the minor version tracks with the minor release; for macOS, it tracks with patch releases.
* * Daily build version: The daily build indicates how many times Apple has built the source code for the release since the previous public release.
* * Optional mastering counter; only relevant for internal builds an betas
*
* While this last bit about the daily build number is phrased somewhat fuzzy, it really is a strictly increasing decimal number.
*/
class BuildNumber private constructor(val buildTrain: UInt, val minorVersion: String, val buildVer: UInt) :
Comparable<BuildNumber> {
class BuildNumber private constructor(
val buildTrain: UInt,
val minorVersion: String,
val buildVer: UInt,
val masteringCounter: String? = null
) : Comparable<BuildNumber> {


constructor(buildNumber: String) : this(parseBuildNumber(buildNumber))

constructor(boxed: Triple<UInt, String, UInt>) : this(boxed.first, boxed.second, boxed.third)
private constructor(boxed: Pair<Triple<UInt, String, UInt>, String?>) : this(
boxed.first.first,
boxed.first.second,
boxed.first.third,
boxed.second
)


/**
Expand All @@ -195,24 +205,33 @@ class BuildNumber private constructor(val buildTrain: UInt, val minorVersion: St
* This results in a [UInt] whose MSBs are always set for correct and straight-forward comparison of build numbers.
* The implementation is inefficient but comprehensible.
*/
val intRepresentation = (
buildTrain.toString(16)
+ minorVersion.toUInt(36).toString(16)
//there will never be more than 9999 days between first release of minorVer and patch
+ buildVer.toString(10).padEnd(4, '0').toUInt(10).toString(16)
).padEnd(8, '0').toUInt(16)
val semVerRepresentation: SemVer = SemVer(
buildTrain.toInt(),
minor = minorVersion.toInt(36),
patch = buildVer.toInt(),
preRelease = masteringCounter
)

override fun compareTo(other: BuildNumber): Int = intRepresentation.compareTo(other.intRepresentation)
override fun compareTo(other: BuildNumber): Int = semVerRepresentation.compareTo(other.semVerRepresentation)

override fun toString() = "$buildTrain$minorVersion$buildVer (${intRepresentation.toString(16)})".uppercase()
override fun toString() = "$buildTrain$minorVersion$buildVer ($semVerRepresentation)"

companion object {
private fun parseBuildNumber(stringRepresentation: String): Triple<UInt, String, UInt> {
private fun parseBuildNumber(stringRepresentation: String): Pair<Triple<UInt, String, UInt>, String?> {
val buildTrain = stringRepresentation.takeWhile { it.isDigit() }
val minorVersion = stringRepresentation.substring(buildTrain.length).takeWhile { it.isLetter() }.uppercase()
val buildVer = stringRepresentation.substring(buildTrain.length + minorVersion.length).toUInt(10)

return Triple(buildTrain.toUInt(10), minorVersion, buildVer)
val minorVersion = stringRepresentation.substring(buildTrain.length).takeWhile { it.isLetter() }
val masteringCounter = stringRepresentation.takeLastWhile { it.isLetter() }
val buildVer = stringRepresentation.substring(
buildTrain.length + minorVersion.length,
stringRepresentation.length - masteringCounter.length
).toUInt(10)

return Triple(
buildTrain.toUInt(10),
minorVersion,
buildVer
) to masteringCounter.let { if (it.isEmpty()) null else it }
}
}
}
Expand Down
65 changes: 65 additions & 0 deletions warden/src/test/kotlin/BuildNumberTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import at.asitplus.attestation.BuildNumber
import io.kotest.core.spec.style.FreeSpec
import io.kotest.datatest.withData
import io.kotest.matchers.comparables.shouldBeLessThan
import java.util.*
import kotlin.random.Random

class BuildNumberTest : FreeSpec({

"presorted" - {
val buildTrains = List(50) { it }

val minorVer = listOf(
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z"
)
val buildNumber = TreeSet<Int>().apply {
repeat(50) {
add(Random.nextInt(0, Int.MAX_VALUE))
}
}

val masteringNumber = "qwertzuioplkjhgfdssayxcvbnm".toCharArray().sorted().map { it.toString() }

val testVectors = mutableListOf<String>().apply {
buildTrains.forEach { train ->
minorVer.forEach { minor ->
buildNumber.forEach { buildNum ->
this.add(train.toString() + minor + buildNum + if (buildNum.mod(3) != 0) masteringNumber.random() else "")
}
}
}
}

withData(testVectors.dropLast(1).mapIndexed { index, s -> index to s }) {
BuildNumber(it.second) shouldBeLessThan BuildNumber(testVectors[it.first + 1])
}
}


})
Loading

0 comments on commit 9aa1c4f

Please sign in to comment.