Kotlin API Reference
Complete API documentation for MetaMUI Crypto Primitives in Kotlin.
Installation
Gradle (Kotlin DSL)
dependencies {
implementation("id.metamui:crypto:3.0.0")
}
Gradle (Groovy)
dependencies {
implementation 'id.metamui:crypto:3.0.0'
}
Maven
<dependency>
<groupId>id.metamui</groupId>
<artifactId>crypto</artifactId>
<version>3.0.0</version>
</dependency>
Quick Start
import id.metamui.crypto.*
// Generate keypair
val keypair = Ed25519.generateKeypair()
// Sign message
val message = "Hello".toByteArray()
val signature = Ed25519.sign(message, keypair.privateKey)
// Verify signature
val isValid = Ed25519.verify(signature, message, keypair.publicKey)
API Documentation
For detailed API documentation, see:
Available Modules
Hash Functions
import id.metamui.crypto.hash.*
// Simple hashing
val hash = SHA256.hash("Hello".toByteArray())
val blake3Hash = Blake3.hash("Hello".toByteArray())
// Streaming hash
val hasher = Blake3.createHasher()
hasher.update(chunk1)
hasher.update(chunk2)
val finalHash = hasher.finalize()
Digital Signatures
// Ed25519
val keypair = Ed25519.generateKeypair()
val signature = keypair.sign(message)
val isValid = keypair.verify(signature, message)
// Post-quantum signatures
val pqKeypair = Dilithium.generateKeypair()
val pqSignature = pqKeypair.sign(message)
Encryption
// ChaCha20-Poly1305
val key = ChaCha20Poly1305.generateKey()
val encrypted = ChaCha20Poly1305.encrypt(plaintext, key)
val decrypted = ChaCha20Poly1305.decrypt(
encrypted.ciphertext,
encrypted.nonce,
key
)
// AES-256-GCM
val aesKey = AES256.generateKey()
val aesEncrypted = AES256.encrypt(plaintext, aesKey)
Key Exchange
// X25519 ECDH
val alice = X25519.generateKeypair()
val bob = X25519.generateKeypair()
val sharedSecret = alice.computeSharedSecret(bob.publicKey)
// Post-quantum KEM
val kemKeypair = MLKem768.generateKeypair()
val (ciphertext, sharedSecret) = MLKem768.encapsulate(kemKeypair.publicKey)
val sharedSecret2 = kemKeypair.decapsulate(ciphertext)
Key Derivation
// Password hashing
val salt = Argon2.generateSalt()
val hash = Argon2.hash(
password = password,
salt = salt,
memory = 256 * 1024, // 256MB
iterations = 4,
parallelism = 2
)
// Key derivation
val derivedKey = HKDF.derive(
inputKey = masterKey,
salt = salt,
info = "encryption key".toByteArray(),
length = 32
)
Coroutines Support
All CPU-intensive operations support coroutines:
import kotlinx.coroutines.*
suspend fun encryptAsync(data: ByteArray): EncryptedData {
return withContext(Dispatchers.Default) {
val key = ChaCha20Poly1305.generateKey()
ChaCha20Poly1305.encrypt(data, key)
}
}
// Parallel operations
suspend fun hashMultiple(files: List<File>): List<ByteArray> {
return coroutineScope {
files.map { file ->
async {
Blake3.hashFile(file)
}
}.awaitAll()
}
}
Java Interoperability
The library is fully compatible with Java:
import id.metamui.crypto.Ed25519;
import id.metamui.crypto.KeyPair;
// Java usage
KeyPair keypair = Ed25519.generateKeypair();
byte[] signature = Ed25519.sign(message, keypair.getPrivateKey());
boolean isValid = Ed25519.verify(signature, message, keypair.getPublicKey());
Android Integration
Android Keystore
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.security.KeyStore
class AndroidSecureStorage(private val context: Context) {
private val keyAlias = "MetaMUIKey"
init {
generateKey()
}
private fun generateKey() {
val keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore"
)
val spec = KeyGenParameterSpec.Builder(
keyAlias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build()
keyGenerator.init(spec)
keyGenerator.generateKey()
}
suspend fun encryptData(data: ByteArray): ByteArray {
return withContext(Dispatchers.IO) {
// Use MetaMUI crypto with Android Keystore key
val key = getKeyFromKeystore()
AES256.encrypt(data, key).ciphertext
}
}
}
Biometric Authentication
import androidx.biometric.BiometricPrompt
class BiometricCrypto(private val activity: FragmentActivity) {
private lateinit var keypair: Ed25519.Keypair
fun authenticateAndSign(
message: ByteArray,
onSuccess: (ByteArray) -> Unit
) {
val executor = ContextCompat.getMainExecutor(activity)
val biometricPrompt = BiometricPrompt(
activity,
executor,
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(
result: BiometricPrompt.AuthenticationResult
) {
val signature = Ed25519.sign(message, keypair.privateKey)
onSuccess(signature)
}
}
)
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Sign Document")
.setSubtitle("Authenticate to sign")
.setNegativeButtonText("Cancel")
.build()
biometricPrompt.authenticate(promptInfo)
}
}
Error Handling
sealed class CryptoError : Exception() {
object InvalidKey : CryptoError()
object DecryptionFailed : CryptoError()
object VerificationFailed : CryptoError()
data class Unknown(override val message: String) : CryptoError()
}
fun safeDecrypt(ciphertext: ByteArray, key: ByteArray): Result<ByteArray> {
return try {
val decrypted = ChaCha20Poly1305.decrypt(ciphertext, nonce, key)
Result.success(decrypted)
} catch (e: Exception) {
when (e) {
is InvalidKeyException -> Result.failure(CryptoError.InvalidKey)
is DecryptionException -> Result.failure(CryptoError.DecryptionFailed)
else -> Result.failure(CryptoError.Unknown(e.message ?: "Unknown error"))
}
}
}
Extension Functions
// Convenient extension functions
fun String.sha256(): ByteArray = SHA256.hash(this.toByteArray())
fun String.blake3(): ByteArray = Blake3.hash(this.toByteArray())
fun ByteArray.toHex(): String = joinToString("") { "%02x".format(it) }
fun String.fromHex(): ByteArray = chunked(2).map { it.toInt(16).toByte() }.toByteArray()
// Secure random
fun secureRandom(size: Int): ByteArray = SecureRandom.generate(size)
Flow Integration
import kotlinx.coroutines.flow.*
class CryptoStream {
fun hashFileStream(file: File): Flow<HashProgress> = flow {
val hasher = Blake3.createHasher()
var processed = 0L
val totalSize = file.length()
file.inputStream().use { input ->
val buffer = ByteArray(8192)
while (true) {
val read = input.read(buffer)
if (read == -1) break
hasher.update(buffer, 0, read)
processed += read
emit(HashProgress(
bytesProcessed = processed,
totalBytes = totalSize,
percentage = (processed * 100 / totalSize).toInt()
))
}
}
emit(HashProgress(
bytesProcessed = totalSize,
totalBytes = totalSize,
percentage = 100,
hash = hasher.finalize()
))
}
}
data class HashProgress(
val bytesProcessed: Long,
val totalBytes: Long,
val percentage: Int,
val hash: ByteArray? = null
)
Examples
Secure Preferences
class SecurePreferences(
context: Context,
password: String
) {
private val prefs = context.getSharedPreferences("secure_prefs", Context.MODE_PRIVATE)
private val key: ByteArray
init {
val salt = prefs.getString("salt", null)?.fromHex() ?: run {
val newSalt = Argon2.generateSalt()
prefs.edit().putString("salt", newSalt.toHex()).apply()
newSalt
}
key = Argon2.deriveKey(password, salt, 32)
}
fun putString(key: String, value: String) {
val encrypted = AES256.encrypt(value.toByteArray(), this.key)
prefs.edit()
.putString(key, encrypted.ciphertext.toHex())
.putString("${key}_nonce", encrypted.nonce.toHex())
.apply()
}
fun getString(key: String): String? {
val ciphertext = prefs.getString(key, null)?.fromHex() ?: return null
val nonce = prefs.getString("${key}_nonce", null)?.fromHex() ?: return null
return try {
val decrypted = AES256.decrypt(ciphertext, nonce, this.key)
String(decrypted)
} catch (e: Exception) {
null
}
}
}
Retrofit Integration
import retrofit2.Retrofit
import okhttp3.Interceptor
class CryptoInterceptor(
private val signingKey: Ed25519.Keypair
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val body = request.body?.let { requestBody ->
val buffer = Buffer()
requestBody.writeTo(buffer)
buffer.readByteArray()
}
val signedRequest = if (body != null) {
val signature = Ed25519.sign(body, signingKey.privateKey)
request.newBuilder()
.header("X-Signature", signature.toHex())
.header("X-Public-Key", signingKey.publicKey.toHex())
.build()
} else {
request
}
return chain.proceed(signedRequest)
}
}
// Usage
val client = OkHttpClient.Builder()
.addInterceptor(CryptoInterceptor(keypair))
.build()
val retrofit = Retrofit.Builder()
.client(client)
.baseUrl("https://api.example.com")
.build()