# How Sumire Implements Privacy-First Japanese Input With Zero Network Permissions

> Discover how Sumire delivers privacy-first Japanese input with zero network permissions. Learn about its offline mozc engine and AES-256-GCM encryption for secure data.

- Repository: [Kazu/japanesekeyboard](https://github.com/kazumaproject/japanesekeyboard)
- Tags: internals
- Published: 2026-03-05

---

**Sumire achieves privacy-first Japanese input by eliminating all network permissions from its Android manifest, running the open-source mozc conversion engine entirely offline, and encrypting all user learning data with AES-256-GCM via the Android Keystore.**

The Sumire Japanese Keyboard (repository: `kazumaproject/japanesekeyboard`) demonstrates that powerful Japanese IME functionality does not require cloud connectivity. By architecting every component—from dictionary lookup to AI candidate generation—as an offline operation, Sumire ensures that keystrokes and personal vocabulary never leave the device. This article examines the specific implementation details that enforce this zero-network, privacy-first design.

## The Foundation: Zero Network Permissions in AndroidManifest.xml

Sumire’s privacy guarantee begins at the system level. The [`AndroidManifest.xml`](https://github.com/kazumaproject/japanesekeyboard/blob/main/AndroidManifest.xml) deliberately omits the `INTERNET` permission, ensuring Android’s sandbox prevents any outbound network requests from the keyboard service.

```xml
<!-- app/src/main/AndroidManifest.xml -->
<manifest ...>
    <!-- No <uses-permission android:name="android.permission.INTERNET"/> -->
    <uses-permission android:name="android.permission.VIBRATE"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    ...
</manifest>

```

By restricting permissions to only `VIBRATE` and `RECORD_AUDIO` (for voice input features), Sumire eliminates the possibility of accidental or malicious data exfiltration through standard Android APIs.

## Offline-Only Conversion Engine

At the core of Sumire’s input method lies the **mozc** engine—the same open-source project that powers Google Japanese IME—modified to operate without network dependencies.

### Bundled Dictionary Architecture

All dictionary data ships inside the APK as static resources. Sumire includes multiple UT (User-Tested) dictionaries covering person names, places, Wikipedia entries, Neologd, and web-crawled terms. These are defined in [`pref_dictionary.xml`](https://github.com/kazumaproject/japanesekeyboard/blob/main/pref_dictionary.xml) and stored in the assets directory.

```xml
<!-- app/src/main/res/xml/pref_dictionary.xml -->
<PreferenceScreen ...>
    <CheckBoxPreference
        android:key="MOZCUT_PERSON_NAME"
        android:title="Person Names Dictionary"/>
    <CheckBoxPreference
        android:key="MOZCUT_PLACES"
        android:title="Places Dictionary"/>
    ...
</PreferenceScreen>

```

### Runtime Dictionary Loading

The [`IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/IMEService.kt) class dynamically loads only the dictionaries enabled by user preferences. This selective loading minimizes memory footprint while maintaining the zero-network constraint.

```kotlin
// app/src/main/java/com/kazumaproject/markdownhelperkeyboard/ime_service/IMEService.kt
private fun loadEnabledDictionaries() {
    if (mozcUTPersonName == true) kanaKanjiEngine.loadPersonNamesDictionary()
    if (mozcUTPlaces == true) kanaKanjiEngine.loadPlacesDictionary()
    if (mozcUTWiki == true) kanaKanjiEngine.loadWikiDictionary()
    if (mozcUTNeologd == true) kanaKanjiEngine.loadNeologdDictionary()
    if (mozcUTWeb == true) kanaKanjiEngine.loadWebDictionary()
}

```

All dictionary files are read from local storage via `kanaKanjiEngine.initModel()` calls, ensuring that conversion candidates derive purely from on-device data.

## Encrypted User Data With Android Keystore

Sumire protects personal learning data—such as frequently used words and custom entries—using **AES-256-GCM encryption** backed by the Android Keystore system.

The [`CryptoManager.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/CryptoManager.kt) class handles all cryptographic operations. When a user adds a custom word, the plaintext is encrypted before touching disk:

```kotlin
// core/src/main/java/com/kazumaproject/core/domain/cryptoManager/CryptoManager.kt
fun encrypt(plaintext: ByteArray): ByteArray {
    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
    cipher.init(Cipher.ENCRYPT_MODE, getOrCreateSecretKey())
    val iv = cipher.iv
    val ciphertext = cipher.doFinal(plaintext)
    // Prepend IV to ciphertext for storage
    return iv + ciphertext
}

```

The secret key is generated and stored within the Android Keystore (`AndroidKeyStore` provider), ensuring it never exists in application memory as plaintext and cannot be extracted from the device. This hardware-backed encryption guarantees that even if the device storage is compromised, the user's Japanese input history remains unreadable.

## Local AI Processing With Zenz Engine

For advanced prediction and candidate ranking, Sumire optionally integrates the **Zenz** AI engine—a native library that performs neural network inference entirely on-device.

The [`ZenzEngine.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/ZenzEngine.kt) wrapper exposes functions like `generate()` and `candidateEvaluate()` that process input sequences using bundled `.gguf` model files. Because the library is compiled into the APK and operates solely on local CPU/NPU resources, it requires no network permissions:

```kotlin
// zenz/src/main/java/com/kazumaproject/zenz/ZenzEngine.kt
class ZenzEngine {
    external fun generate(input: String, maxLength: Int): String
    external fun candidateEvaluate(candidate: String, context: String): Float
    
    init {
        System.loadLibrary("zenz")
    }
}

```

The Zenz engine accesses only the bundled model assets, maintaining the zero-network architecture while providing modern AI-enhanced Japanese input capabilities.

## Secure Lifecycle Management

Sumire ensures that sensitive data does not persist in memory longer than necessary. When the input method service is destroyed, [`IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/IMEService.kt) explicitly releases all loaded dictionary resources:

```kotlin
// app/src/main/java/com/kazumaproject/markdownhelperkeyboard/ime_service/IMEService.kt
override fun onDestroy() {
    super.onDestroy()
    // Release all UT dictionaries to prevent memory leaks
    kanaKanjiEngine.releasePersonNamesDictionary()
    kanaKanjiEngine.releasePlacesDictionary()
    kanaKanjiEngine.releaseWikiDictionary()
    kanaKanjiEngine.releaseNeologdDictionary()
    kanaKanjiEngine.releaseWebDictionary()
}

```

This cleanup routine, located at lines 1546-1550 of [`IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/IMEService.kt), ensures that dictionary data is purged from the heap when the keyboard closes, minimizing the window for memory-based attacks.

## Summary

Sumire implements privacy-first Japanese input with zero network permissions through these architectural safeguards:

- **Manifest-level blocking**: The [`AndroidManifest.xml`](https://github.com/kazumaproject/japanesekeyboard/blob/main/AndroidManifest.xml) explicitly excludes `INTERNET` permission, preventing any network access at the OS level.
- **Offline mozc engine**: All conversion dictionaries ship as local assets; [`IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/IMEService.kt) loads selected dictionaries via `kanaKanjiEngine` methods without external API calls.
- **Hardware-backed encryption**: [`CryptoManager.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/CryptoManager.kt) uses AES-256-GCM with Android Keystore to encrypt user dictionaries and learning data.
- **On-device AI**: The Zenz engine runs locally via native libraries, processing neural models without network I/O.
- **Secure lifecycle**: Explicit resource cleanup in `IMEService.onDestroy()` prevents residual data in memory.

## Frequently Asked Questions

### How does Sumire handle Japanese conversion without internet access?

Sumire embeds the open-source mozc conversion engine and all required dictionaries directly into the APK. When you type, the `kanaKanjiEngine` processes input using locally stored dictionary files (Person-Name, Places, Wiki, Neologd, Web) loaded by [`IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/IMEService.kt). Because all linguistic data resides on the device, the keyboard generates conversion candidates instantly without network latency or connectivity requirements.

### What encryption method protects my personal dictionary in Sumire?

Sumire uses **AES-256-GCM** encryption via the [`CryptoManager.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/CryptoManager.kt) class. When you add a custom word, the plaintext is encrypted using a secret key stored in the Android Keystore. This hardware-backed key never leaves the secure module, ensuring that even if someone gains access to your device storage, they cannot decrypt your personal Japanese vocabulary or input history without the hardware key.

### Can the Zenz AI feature in Sumire leak data to cloud servers?

No. The Zenz AI engine operates entirely offline through a native library (`libzenz.so`) compiled into the APK. The [`ZenzEngine.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/ZenzEngine.kt) wrapper calls native methods like `generate()` and `candidateEvaluate()` that process input using bundled `.gguf` model files stored in the app’s assets. Since the [`AndroidManifest.xml`](https://github.com/kazumaproject/japanesekeyboard/blob/main/AndroidManifest.xml) lacks `INTERNET` permission and the native code performs no socket operations, Zenz cannot transmit data externally.

### Why does Sumire explicitly release dictionaries when the keyboard closes?

Sumire calls `kanaKanjiEngine.release*Dictionary()` methods inside `IMEService.onDestroy()` (lines 1546-1550) to prevent memory leaks and reduce attack surface. By explicitly unloading Person-Name, Places, Wiki, Neologd, and Web dictionaries from heap memory when the input method service stops, Sumire ensures that sensitive linguistic data does not persist in RAM longer than necessary, protecting against memory dumping attacks.