5.4 KiB
GajuMobile
The Android implementation of the Gajumaru client application (essentially GajuDesk-lite).
This app is primarily a signature device. Its purpose is not to be an all-in-one app for every possible Gajumaru feature. It is also not intended to integrate directly with every major app that is integrated with the Gajumaru.
Scope
GajuMobile covers the bare minimum features necessary to interact with the Gajumaru and, specifically, support functionality that can be expressed via GRIDS.
App-specific functionality (direct integration with a DEX or other type of exchange, interpretation of NFTs, transaction history tracking, etc.) are out of scope for GajuMobile.
Other applications can be linked to by GajuMobile via clickable URL components, and other applications can form Gajumaru transactions that GajuMobile can then be prompted to sign through GRIDS, whether over the LAN or WAN.
Project rules
To maintain the security posture of this project, every contributor must strictly adhere to these rules. "Industry standards" and "best practices" are generally regarded here as vectors for collective incompetence and unvetted dependency bloat. We write our own code.
Reasoning
It is impossible to tell from the code alone what is actually going to happen in the runtime, or even understand what is going to happen in the potentially limitless number of pre-compilation steps based on what files are even included in a given module, much less pin down a truly deterministic build profile if external dependencies are included. This is the primary reason for the "no foreign deps" rule.
1. No Foreign Dependencies
GajuMobile (whether on Android, iOS, or Pine) is not permitted to include any foreign dependencies. A "foreign" dependency is defined as any library originating from outside the Gajumaru project itself.
Since we cannot escape the platforms we target, we accept the baseline trust of the OS, its core UI toolkits, and primary languages (Jetpack Compose/Kotlin, SwiftUI/Swift). Any attempt to import external convenience libraries will be rejected. I don't like it, but my opinions are objectively correct, and this is the boundary of trust we accept because it is at least well-defined.
2. The Airlock Pattern & Memory Hygiene
Kotlin is a rats' nest of antisensical decisions and techniques. Kotlin is hipster junk food created by smart people for consumption by less smart people. It is a midwit's wet dream of "expressive" garbage, a language suffering an extreme case of featuritis that can't decide what paradigm it lives in, so it lives in them all while achieving none of them.
It is impossible to achieve memory hygiene in Kotlin. Therefore, all
sensitive cryptographic operations -- key generation, signing, and mnemonic
derivation -- must occur within AccountAirlock.java.
- Secrets Isolation: Sensitive material may never exist as Kotlin
StringorByteArrayobjects for longer than a single stack frame, and only when the user actually must interact with secrets directly, namely when viewing or entering their mnemonic. - Explicit Decontamination: All secret buffers must be explicitly
zeroed using
CryptoUtils.wipe()in afinallyblock before leaving scope. (See the gm-java project README.) - gm-java Primitives: Primitives providing functionality found in
Hakuzaru/Erlang must be implemented in the self-contained
gm-javaproject. This project is written to ensure that fragments of old object memory are not left scattered across the heap awaiting GC.
3. Forbidden Primitives
Do not use java.math.BigInteger for any key-related material (seeds,
private keys, mnemonics). Use the Radix-2^25.5 field arithmetic implemented
in gm-java. BigInteger is a leak-prone abstraction that has no place in
security sensitive contexts.
4. Hardware-Enforced Security
As the security facilities required for a proper signature device did not exist prior to Android 14, that is the oldest version we support. We must exploit the strongest security facilities available:
- Keystore Policy: The Master Key must use
setUserAuthenticationRequired(true), delegating authorization to the system's secure lock. - Entropy: Use
setRandomizedEncryptionRequired(true)to ensure the hardware module generates high-entropy IVs. - StrongBox: Use
setIsStrongBoxBacked(true)with a graceful TEE fallback.
5. Explicit Imports
All import directives must be fully specified. import foo.bar.baz.* style
wildcard imports are strictly forbidden. Wildcards hide intent, create
ambiguity in the build, and are potentially dangerous in Kotlin.
Terms
Copyright (c) 2026 QPQ AG info@qpq.swiss. All rights reserved. Project: Gajumaru Core Java Libraries
This program is dual-licensed:
-
Under the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version (AGPL-3.0-or-later). (See LICENSE file.)
-
Under a commercial/proprietary license available directly from QPQ AG. If you wish to use this software outside the strict constraints of the AGPLv3 (e.g. within a closed-source or proprietary product), you must purchase a commercial license from QPQ AG.
Authors:
- Craig Everett craigeverett@qpq.swiss
SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-QPQ-Commercial