SaQura Kotlin · Upgrade notes
Versions & compatibility — SaQura Kotlin
Before you update
Current version: 1.2.1 · Maven Central · jp.co.kyototech:saqura · to the documentation
- Data from every published version (1.1.1 to 1.2.1) is read by 1.2.1; no format has changed since the first release.
- Your license file stays valid. Since 1.2.0 there are optional binding fields; a license without them behaves byte-identically to before.
- The keep rules for R8 ship as consumer rules inside the AAR; nothing to add in your app. The MLS libraries are optional and can be excluded.
- Minimum platform is Android 8.0 (API 26): the package manifest allows API 24, but license validation and password hashing use java.time, which exists from API 26 on. If you must support 24 or 25, enable core library desugaring in your app.
The tables under each version answer the same five questions in the same order. “Drop-in update: yes” means: our cross-platform test corpus has shown that the new version reads the data of the previous one and no call needs to change.
Optional modules
- MLS (RFC 9420, from 1.2.0) has its own load path: libsaqura_mls.so and libsaqura_mls_jni.so are loaded on the first MLS call only. Size per ABI: arm64-v8a 1.18 MB, x86_64 1.47 MB, armeabi-v7a 0.90 MB, x86 1.54 MB (each plus about 17 KB JNI bridge).
- If you do not use MLS, exclude the two libraries in your app module: android { packaging { jniLibs { excludes += listOf("**/libsaqura_mls.so", "**/libsaqura_mls_jni.so") } } }. Every other feature runs unchanged; only an MLS call would then fail with a load error.
- Not optional: liboqs.so and libsaqura_oqs.so (post-quantum algorithms) for all four ABIs arm64-v8a, armeabi-v7a, x86, x86_64. The 64-bit libraries are 16 KB page-aligned since 1.2.1.
- Dependency in the POM: org.bouncycastle:bcprov-jdk18on (X25519 for Gen8 from API 24) plus kotlinx-coroutines.
Licenses & app binding
- Unbound licenses are not affected by app binding: no call changes, no re-issue needed.
- Bound distribution licenses (from 1.2.0) check the package name and the signing certificate reported by the operating system. Call ApiLicense.initialize(context) at app startup so the library can read both.
- boundSignature is the SHA-256 fingerprint of the certificate the app is signed with on the device. With Google Play App Signing that is the app signing key from the Play Console, not your upload key. Several fingerprints (for example upload and debug certificates in addition) are possible as a list.
1.2.1 · 2026-07-31
16 KB page alignment of the 64-bit libraries
- Google Play rejects app bundles with targetSdk 35 or higher whose native 64-bit libraries are not 16 KB page-aligned. Up to 1.2.0 the bundled libraries were linked with 4 KB; an app with SaQura could not be uploaded. Now every library on arm64-v8a and x86_64 reports a LOAD alignment of 0x4000.
- The 32-bit ABIs are not affected by the Play rule and are unchanged. No change to API, format or behaviour; a pure build change.
| Compatibility | Status | Note |
|---|---|---|
| Data formats (keys, ciphertexts, streams) | unchanged | — |
| License files (bound / unbound) | unchanged | — |
| Native libraries / ABI | changed | Only the alignment of the 64-bit libraries; names and count unchanged. |
| R8 / keep rules, trimming / linker | unchanged | — |
| Minimum platform | unchanged | Android 8.0 (API 26) |
| Drop-in update? | Yes | — |
1.2.0 · 2026-06-26
MLS group messaging (RFC 9420) and app binding
- New package co.kyototech.saqura.mls: SaQuraMLS (configure, generateKeyPackage, createGroup, joinGroup, loadGroup), MLSGroup (addMembers, removeMembers, update, processHandshake, encrypt, decrypt, members, epoch, serialize) plus the MLSSigner and MLSStorageProvider interfaces. Two ciphersuites: p256Standard (0x0002, RFC 9420 standard, interoperable) and saquraGen8Hybrid (0xF108, X25519 with ML-KEM-768).
- The MLS bytes are identical to the Swift SDK (verified on devices, Kotlin also reads Swift traffic). Signing goes through your MLSSigner (for example a P-256 key in the Android Keystore); the private signing key never enters the library. Active operations (create, join, send, change members) from Pro; reading and restoring existing groups stays open.
- Two additional native libraries per ABI (libsaqura_mls.so, libsaqura_mls_jni.so), loaded on the first MLS call only; excludable, see “Optional modules”.
- App binding: the optional license fields boundPackage and boundSignature tie a distribution license to the package name and the SHA-256 of the signing certificate, both read from the operating system (ApiLicense.initialize(context) at app startup). A copied license file in a foreign app is rejected. Licenses without these fields are byte-identical and behave as before.
- No change to the AES, RSA, Quantum, streaming, licensing and password APIs or their formats.
| Compatibility | Status | Note |
|---|---|---|
| Data formats (keys, ciphertexts, streams) | new, additive | MLS new; all previous formats unchanged. |
| License files (bound / unbound) | new, additive | Optional binding fields; unbound licenses byte-identical. |
| Native libraries / ABI | new, additive | Two MLS libraries per ABI, excludable. |
| R8 / keep rules, trimming / linker | new, additive | Keep rules for the MLS package in the shipped consumer rules; applied automatically. |
| Minimum platform | unchanged | Android 8.0 (API 26) |
| Drop-in update? | Yes | — |
1.1.4 · 2026-06-16
Crash of the post-quantum functions in release builds fixed
- In minified release builds Quantum.* and QuantumSignature.* aborted on the first call (affected 1.1.1, 1.1.2 and 1.1.3): R8 stripped fields that only the native layer reads. Fixed by keep rules the library ships as consumer rules in the AAR; nothing to add in your app.
- No change to API, format or behaviour. Apps on 1.1.1 to 1.1.3 that use post-quantum features on Android should upgrade.
| Compatibility | Status | Note |
|---|---|---|
| Data formats (keys, ciphertexts, streams) | unchanged | — |
| License files (bound / unbound) | unchanged | — |
| Native libraries / ABI | unchanged | — |
| R8 / keep rules, trimming / linker | changed | Keep rules corrected and shipped; nothing to do. |
| Minimum platform | unchanged | Android 8.0 (API 26) |
| Drop-in update? | Yes | — |
1.1.3 · 2026-06-06
Streaming encryption for large files (SQS1)
- New package co.kyototech.saqura.streaming: encryptStreamFile / decryptStreamFile, InputStream.encryptStream / decryptStream, readStreamInfo and countCompleteSegments (resume). Constant memory (about twice the segment size, default 1 MiB), regardless of file size.
- Two AEAD suites by header (AES-256-GCM, ChaCha20-Poly1305) and the post-quantum envelope StreamingEnvelope.encryptFile / decryptFile (Pro) with a sidecar .saqkey file or an embedded key. Streaming from Standard, envelope from Pro. Purely additive; byte-identical to .NET and Swift.
| Compatibility | Status | Note |
|---|---|---|
| Data formats (keys, ciphertexts, streams) | new, additive | New SQS1 format; all previous formats unchanged. |
| License files (bound / unbound) | unchanged | — |
| Native libraries / ABI | unchanged | — |
| R8 / keep rules, trimming / linker | unchanged | — |
| Minimum platform | unchanged | Android 8.0 (API 26) |
| Drop-in update? | Yes | — |
1.1.2 · 2026-06-05
NIST post-quantum algorithms: Gen8, ML-DSA, SLH-DSA
- Gen8 (X25519 with ML-KEM, FIPS 203) through the existing Quantum surface with QuantumGeneration.GEN8. Signatures ML-DSA (FIPS 204, 44 / 65 / 87) and SLH-DSA (FIPS 205, 128f / 192f / 256f) through QuantumSignature and SignatureAlgorithm. Signing from Pro, verifying in every tier. Byte-identical to .NET and Swift.
- Bundled liboqs rebuilt at 0.15.0 (all four ABIs). New dependency org.bouncycastle:bcprov-jdk18on in the POM (X25519 from API 24).
| Compatibility | Status | Note |
|---|---|---|
| Data formats (keys, ciphertexts, streams) | new, additive | New algorithms; previous generations unchanged. |
| License files (bound / unbound) | unchanged | — |
| Native libraries / ABI | changed | liboqs rebuilt; new BouncyCastle dependency in the POM. |
| R8 / keep rules, trimming / linker | unchanged | — |
| Minimum platform | unchanged | Android 8.0 (API 26) |
| Drop-in update? | Yes | — |
1.1.1 · 2026-05-27
First release on Maven Central
- Feature-equivalent to SaQura for .NET 1.0.8 and Swift 1.0.8: AES-256-GCM (String and ByteArray), AES-CBC with HMAC-SHA256 read-only for legacy ciphertexts, PBKDF2-SHA512, RSA-4096 (OAEP, PSS, hybrid for large payloads, PEM import PKCS#1/PKCS#8/SPKI), password hashing with JSON envelope, post-quantum encryption (FrodoKEM, Classic McEliece, Gen7 hybrid) via bundled liboqs for all four ABIs, licensing via .lic file stored in EncryptedSharedPreferences.
- All formats byte-identical to .NET and Swift, including the free-tier marking. Kotlin-idiomatic (suspend functions, extensions on String and ByteArray), every public API reachable from Java as well.
| Compatibility | Status | Note |
|---|---|---|
| Data formats (keys, ciphertexts, streams) | baseline | Baseline; byte-identical to .NET 1.0.8 and Swift 1.0.8. |
| License files (bound / unbound) | baseline | — |
| Native libraries / ABI | baseline | liboqs.so and libsaqura_oqs.so for arm64-v8a, armeabi-v7a, x86, x86_64. |
| R8 / keep rules, trimming / linker | baseline | Consumer rules in the AAR. |
| Minimum platform | baseline | Android 8.0 (API 26) |
| Drop-in update? | Yes | First version. |