Exemples de Cryptographie Android Kotlin

Exemples de cryptographie Android Kotlin incluant le calcul de hachage, le chiffrement AES et le codage Base64

💻 Encodage Base64 kotlin

🟢 simple ⭐⭐

Encoder et décoder des données en utilisant Base64 avec diverses options et jeux de caractères

⏱️ 20 min 🏷️ kotlin, android, base64, encoding
Prerequisites: Basic Kotlin
// Android Kotlin Base64 Encoding Examples
// Using java.util.Base64 (Android API 26+) and android.util.Base64

import java.util.Base64
import android.util.Base64 as AndroidBase64
import java.nio.charset.StandardCharsets

// 1. Basic Base64 Encoding/Decoding
class BasicBase64 {

    // Encode string to Base64
    fun encodeToString(input: String): String {
        val encodedBytes = Base64.getEncoder().encode(input.toByteArray())
        return String(encodedBytes)
    }

    // Decode Base64 to string
    fun decodeString(encoded: String): String {
        val decodedBytes = Base64.getDecoder().decode(encoded)
        return String(decodedBytes)
    }

    // Encode bytes to Base64
    fun encodeBytes(bytes: ByteArray): String {
        return Base64.getEncoder().encodeToString(bytes)
    }

    // Decode Base64 to bytes
    fun decodeToBytes(encoded: String): ByteArray {
        return Base64.getDecoder().decode(encoded)
    }

    // Encode with URL-safe mode
    fun encodeUrlSafe(input: String): String {
        return Base64.getUrlEncoder().encodeToString(input.toByteArray())
    }

    // Decode URL-safe Base64
    fun decodeUrlSafe(encoded: String): String {
        val decodedBytes = Base64.getUrlDecoder().decode(encoded)
        return String(decodedBytes)
    }
}

// 2. Android Base64 (Compat for older API levels)
class AndroidBase64Codec {

    // Encode using Android Base64
    fun encode(input: String, flags: Int = AndroidBase64.NO_WRAP): String {
        val inputBytes = input.toByteArray(StandardCharsets.UTF_8)
        val encoded = AndroidBase64.encode(inputBytes, flags)
        return String(encoded)
    }

    // Decode using Android Base64
    fun decode(encoded: String, flags: Int = AndroidBase64.NO_WRAP): String {
        val decoded = AndroidBase64.decode(encoded, flags)
        return String(decoded, StandardCharsets.UTF_8)
    }

    // Encode with NO_WRAP (no padding)
    fun encodeNoWrap(input: String): String {
        return encode(input, AndroidBase64.NO_WRAP)
    }

    // Encode with CRLF (line breaks)
    fun encodeWithCRLF(input: String): String {
        return encode(input, AndroidBase64.CRLF)
    }
}

// 3. Base64 for Binary Data
class BinaryBase64 {

    // Encode image to Base64
    fun encodeImage(imageBytes: ByteArray): String {
        return Base64.getEncoder().encodeToString(imageBytes)
    }

    // Decode Base64 to image bytes
    fun decodeToImage(encoded: String): ByteArray {
        return Base64.getDecoder().decode(encoded)
    }

    // Encode file to Base64
    fun encodeFile(file: java.io.File): String {
        val bytes = file.readBytes()
        return Base64.getEncoder().encodeToString(bytes)
    }

    // Decode Base64 and save to file
    fun decodeToFile(encoded: String, file: java.io.File): Boolean {
        return try {
            val bytes = Base64.getDecoder().decode(encoded)
            file.writeBytes(bytes)
            true
        } catch (e: Exception) {
            println("Error decoding to file: ${e.message}")
            false
        }
    }

    // Encode with MIME encoding (76 chars per line)
    fun encodeMime(input: String): String {
        return Base64.getMimeEncoder().encodeToString(input.toByteArray())
    }

    // Decode MIME encoding
    fun decodeMime(encoded: String): String {
        val decodedBytes = Base64.getMimeDecoder().decode(encoded)
        return String(decodedBytes)
    }
}

// 4. Base64 Streams
class Base64Streams {

    // Encode large file with streaming
    fun encodeLargeFile(inputFile: java.io.File, outputFile: java.io.File): Boolean {
        return try {
            java.io.FileInputStream(inputFile).use { inputStream ->
                java.io.FileOutputStream(outputFile).use { outputStream ->
                    val encoder = Base64.getEncoder().wrap(outputStream)

                    val buffer = ByteArray(4096)
                    var bytesRead: Int

                    while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                        encoder.write(buffer, 0, bytesRead)
                    }

                    encoder.close()
                }
            }

            true
        } catch (e: Exception) {
            println("Error encoding large file: ${e.message}")
            false
        }
    }

    // Decode large file with streaming
    fun decodeLargeFile(inputFile: java.io.File, outputFile: java.io.File): Boolean {
        return try {
            java.io.FileInputStream(inputFile).use { inputStream ->
                java.io.FileOutputStream(outputFile).use { outputStream ->
                    val decoder = Base64.getDecoder().wrap(inputStream)

                    val buffer = ByteArray(4096)
                    var bytesRead: Int

                    while (decoder.read(buffer).also { bytesRead = it } != -1) {
                        outputStream.write(buffer, 0, bytesRead)
                    }

                    decoder.close()
                }
            }

            true
        } catch (e: Exception) {
            println("Error decoding large file: ${e.message}")
            false
        }
    }
}

// 5. Base64 Validation and Utilities
class Base64Utilities {

    // Validate Base64 string
    fun isValidBase64(input: String): Boolean {
        return try {
            Base64.getDecoder().decode(input)
            true
        } catch (e: IllegalArgumentException) {
            false
        }
    }

    // Check if URL-safe Base64
    fun isValidUrlSafeBase64(input: String): Boolean {
        return try {
            Base64.getUrlDecoder().decode(input)
            true
        } catch (e: IllegalArgumentException) {
            false
        }
    }

    // Remove padding from Base64
    fun removePadding(encoded: String): String {
        return encoded.trimEnd('=')
    }

    // Add padding to Base64
    fun addPadding(encoded: String): String {
        val paddingLength = (4 - (encoded.length % 4)) % 4
        return encoded + "=".repeat(paddingLength)
    }

    // Convert standard Base64 to URL-safe
    fun toUrlSafe(encoded: String): String {
        return encoded
            .replace("+", "-")
            .replace("/", "_")
            .trimEnd('=')
    }

    // Convert URL-safe to standard Base64
    fun fromUrlSafe(encoded: String): String {
        var result = encoded
            .replace("-", "+")
            .replace("_", "/")

        // Add padding
        val paddingLength = (4 - (result.length % 4)) % 4
        result += "=".repeat(paddingLength)

        return result
    }
}

// 6. Base64 for Data URLs
class DataUrlBase64 {

    // Create data URL for image
    fun createImageDataUrl(imageBytes: ByteArray, mimeType: String = "image/png"): String {
        val base64 = Base64.getEncoder().encodeToString(imageBytes)
        return "data:$mimeType;base64,$base64"
    }

    // Create data URL for text
    fun createTextDataUrl(text: String, mimeType: String = "text/plain"): String {
        val base64 = Base64.getEncoder().encodeToString(text.toByteArray())
        return "data:$mimeType;base64,$base64"
    }

    // Extract Base64 from data URL
    fun extractFromDataUrl(dataUrl: String): String? {
        val prefix = "base64,"
        val index = dataUrl.indexOf(prefix)

        return if (index != -1) {
            dataUrl.substring(index + prefix.length)
        } else {
            null
        }
    }

    // Parse data URL
    fun parseDataUrl(dataUrl: String): Pair<String, String>? {
        val match = Regex("data:([^;]+);base64,(.+)").find(dataUrl)

        return match?.let {
            val mimeType = it.groupValues[1]
            val base64 = it.groupValues[2]
            mimeType to base64
        }
    }
}

// 7. Base64 Hash and Checksum
class Base64Hash {

    // Encode MD5 hash as Base64
    fun md5Base64(input: String): String {
        val digest = java.security.MessageDigest.getInstance("MD5")
        val hash = digest.digest(input.toByteArray())
        return Base64.getEncoder().encodeToString(hash)
    }

    // Encode SHA-256 hash as Base64
    fun sha256Base64(input: String): String {
        val digest = java.security.MessageDigest.getInstance("SHA-256")
        val hash = digest.digest(input.toByteArray())
        return Base64.getEncoder().encodeToString(hash)
    }

    // Create Basic Authentication header
    fun createBasicAuth(username: String, password: String): String {
        val credentials = "$username:$password"
        val encoded = Base64.getEncoder().encodeToString(credentials.toByteArray())
        return "Basic $encoded"
    }

    // Parse Basic Authentication
    fun parseBasicAuth(header: String): Pair<String, String>? {
        if (!header.startsWith("Basic ")) {
            return null
        }

        val encoded = header.substring(6)
        val decoded = String(Base64.getDecoder().decode(encoded))

        val parts = decoded.split(":", limit = 2)
        return if (parts.size == 2) {
            parts[0] to parts[1]
        } else {
            null
        }
    }
}

// Main demonstration
fun demonstrateBase64Encoding() {
    println("=== Android Kotlin Base64 Encoding Examples ===\n")

    // 1. Basic encoding/decoding
    println("--- 1. Basic Encoding/Decoding ---")
    val basicBase64 = BasicBase64()

    val text = "Hello, World!"
    val encoded = basicBase64.encodeToString(text)
    println("Original: $text")
    println("Encoded: $encoded")

    val decoded = basicBase64.decodeString(encoded)
    println("Decoded: $decoded")

    // 2. URL-safe encoding
    println("\n--- 2. URL-Safe Encoding ---")
    val urlText = "Hello, World! This is a test."

    val urlEncoded = basicBase64.encodeUrlSafe(urlText)
    println("URL-safe encoded: $urlEncoded")

    val urlDecoded = basicBase64.decodeUrlSafe(urlEncoded)
    println("URL-safe decoded: $urlDecoded")

    // 3. Binary data
    println("\n--- 3. Binary Data ---")
    val binaryBase64 = BinaryBase64()

    val imageData = byteArrayOf(0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A) // PNG header
    val imageEncoded = binaryBase64.encodeImage(imageData)
    println("Image data encoded: $imageEncoded")

    val imageDecoded = binaryBase64.decodeToImage(imageEncoded)
    println("Image data decoded: ${imageDecoded.joinToString(",") { "0x${it.toString(16).uppercase()}" }}")

    // 4. MIME encoding
    println("\n--- 4. MIME Encoding ---")
    val longText = "This is a very long text that will be split into multiple lines when using MIME encoding."

    val mimeEncoded = binaryBase64.encodeMime(longText)
    println("MIME encoded:")
    println(mimeEncoded)

    // 5. Utilities
    println("\n--- 5. Utilities ---")
    val utilities = Base64Utilities()

    println("Is valid Base64: ${utilities.isValidBase64(encoded)}")
    println("Is valid URL-safe: ${utilities.isValidUrlSafeBase64(urlEncoded)}")

    val withPadding = "SGVsbG8="
    println("\nRemove padding: ${utilities.removePadding(withPadding)}")
    println("Add padding: ${utilities.addPadding(utilities.removePadding(withPadding))}")

    val standardBase64 = "SGVsbG8rV29ybGQvVGVzdA=="
    val urlSafe = utilities.toUrlSafe(standardBase64)
    println("\nTo URL-safe: $urlSafe")
    println("From URL-safe: ${utilities.fromUrlSafe(urlSafe)}")

    // 6. Data URLs
    println("\n--- 6. Data URLs ---")
    val dataUrl = DataUrlBase64()

    val textBytes = "Sample text".toByteArray()
    val textDataUrl = dataUrl.createTextDataUrl(String(textBytes), "text/plain")
    println("Text data URL: $textDataUrl")

    val extracted = dataUrl.extractFromDataUrl(textDataUrl)
    println("Extracted Base64: $extracted")

    // 7. Hash and authentication
    println("\n--- 7. Hash and Authentication ---")
    val base64Hash = Base64Hash()

    val md5Base64 = base64Hash.md5Base64(text)
    println("MD5 Base64: $md5Base64")

    val sha256Base64 = base64Hash.sha256Base64(text)
    println("SHA-256 Base64: $sha256Base64")

    val basicAuth = base64Hash.createBasicAuth("alice", "password123")
    println("\nBasic Auth: $basicAuth")

    val parsedAuth = base64Hash.parseBasicAuth(basicAuth)
    println("Parsed Auth: ${parsedAuth?.first} / ${parsedAuth?.second}")

    println("\n=== All Base64 Encoding Examples Completed ===")
}

💻 Calcul de Hachage kotlin

🟡 intermediate ⭐⭐⭐⭐

Calculer les hachages MD5, SHA-1, SHA-256 et SHA-512 pour les chaînes et fichiers

⏱️ 30 min 🏷️ kotlin, android, cryptography, hash
Prerequisites: Intermediate Kotlin, Cryptography basics
// Android Kotlin Hash Calculation Examples
// Using java.security package

import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.io.File
import java.io.FileInputStream

// 1. String Hashing
class StringHasher {

    // Calculate MD5 hash
    fun md5(input: String): String {
        return try {
            val digest = MessageDigest.getInstance("MD5")
            val hash = digest.digest(input.toByteArray())
            bytesToHex(hash)
        } catch (e: NoSuchAlgorithmException) {
            throw RuntimeException("MD5 not available", e)
        }
    }

    // Calculate SHA-1 hash
    fun sha1(input: String): String {
        return try {
            val digest = MessageDigest.getInstance("SHA-1")
            val hash = digest.digest(input.toByteArray())
            bytesToHex(hash)
        } catch (e: NoSuchAlgorithmException) {
            throw RuntimeException("SHA-1 not available", e)
        }
    }

    // Calculate SHA-256 hash
    fun sha256(input: String): String {
        return try {
            val digest = MessageDigest.getInstance("SHA-256")
            val hash = digest.digest(input.toByteArray())
            bytesToHex(hash)
        } catch (e: NoSuchAlgorithmException) {
            throw RuntimeException("SHA-256 not available", e)
        }
    }

    // Calculate SHA-512 hash
    fun sha512(input: String): String {
        return try {
            val digest = MessageDigest.getInstance("SHA-512")
            val hash = digest.digest(input.toByteArray())
            bytesToHex(hash)
        } catch (e: NoSuchAlgorithmException) {
            throw RuntimeException("SHA-512 not available", e)
        }
    }

    // Calculate with salt
    fun hashWithSalt(input: String, salt: String, algorithm: String = "SHA-256"): String {
        val digest = MessageDigest.getInstance(algorithm)
        digest.update(salt.toByteArray())
        val hash = digest.digest(input.toByteArray())
        return bytesToHex(hash)
    }

    // Helper: Convert bytes to hex string
    private fun bytesToHex(bytes: ByteArray): String {
        val hexString = StringBuilder()
        for (byte in bytes) {
            val hex = Integer.toHexString(0xff and byte.toInt())
            if (hex.length == 1) hexString.append('0')
            hexString.append(hex)
        }
        return hexString.toString()
    }

    // Helper: Convert bytes to hex string (alternative)
    private fun bytesToHexAlternative(bytes: ByteArray): String {
        return bytes.joinToString("") { "%02x".format(it) }
    }
}

// 2. File Hashing
class FileHasher {

    // Calculate hash for file
    fun hashFile(file: File, algorithm: String = "SHA-256"): String {
        val digest = MessageDigest.getInstance(algorithm)

        FileInputStream(file).use { fis ->
            val buffer = ByteArray(8192)
            var bytesRead: Int

            while (fis.read(buffer).also { bytesRead = it } != -1) {
                digest.update(buffer, 0, bytesRead)
            }
        }

        val hash = digest.digest()
        return bytesToHex(hash)
    }

    // Calculate MD5 of file
    fun md5File(file: File): String {
        return hashFile(file, "MD5")
    }

    // Calculate SHA-256 of file
    fun sha256File(file: File): String {
        return hashFile(file, "SHA-256")
    }

    // Calculate hash for large file with progress
    fun hashFileWithProgress(
                    file: File,
                    algorithm: String = "SHA-256",
                    onProgress: (Long, Long) -> Unit
    ): String {
        val digest = MessageDigest.getInstance(algorithm)
        val fileSize = file.length()
        var bytesProcessed = 0L

        FileInputStream(file).use { fis ->
            val buffer = ByteArray(8192)
            var bytesRead: Int

            while (fis.read(buffer).also { bytesRead = it } != -1) {
                digest.update(buffer, 0, bytesRead)
                bytesProcessed += bytesRead
                onProgress(bytesProcessed, fileSize)
            }
        }

        val hash = digest.digest()
        return bytesToHex(hash)
    }

    private fun bytesToHex(bytes: ByteArray): String {
        return bytes.joinToString("") { "%02x".format(it) }
    }

    // Verify file integrity
    fun verifyFileIntegrity(file: File, expectedHash: String, algorithm: String = "SHA-256"): Boolean {
        val actualHash = hashFile(file, algorithm)
        return actualHash.equals(expectedHash, ignoreCase = true)
    }
}

// 3. Password Hashing
class PasswordHasher {

    // Simple password hash (not for production - use bcrypt/argon2 instead)
    fun hashPassword(password: String, salt: String): String {
        val hasher = StringHasher()
        return hasher.hashWithSalt(password, salt, "SHA-256")
    }

    // Generate random salt
    fun generateSalt(length: Int = 32): String {
        val bytes = ByteArray(length)
        java.security.SecureRandom().nextBytes(bytes)
        return bytesToHex(bytes)
    }

    private fun bytesToHex(bytes: ByteArray): String {
        return bytes.joinToString("") { "%02x".format(it) }
    }

    // Hash with iterations (slow hash)
    fun hashWithIterations(password: String, salt: String, iterations: Int = 10000): String {
        val digest = MessageDigest.getInstance("SHA-256")
        var hash = (password + salt).toByteArray()

        repeat(iterations) {
            hash = digest.digest(hash)
        }

        return bytesToHex(hash)
    }

    private fun bytesToHex(bytes: ByteArray): String {
        return bytes.joinToString("") { "%02x".format(it) }
    }

    // Verify password
    fun verifyPassword(password: String, salt: String, expectedHash: String): Boolean {
        val actualHash = hashWithIterations(password, salt, 10000)
        return actualHash.equals(expectedHash, ignoreCase = true)
    }
}

// 4. HMAC (Hash-based Message Authentication Code)
class HmacHasher {

    // Calculate HMAC-SHA256
    fun hmacSha256(data: String, key: String): String {
        val mac = javax.crypto.Mac.getInstance("HmacSHA256")
        val secretKey = javax.crypto.spec.SecretKeySpec(key.toByteArray(), "HmacSHA256")
        mac.init(secretKey)
        val hmac = mac.doFinal(data.toByteArray())
        return bytesToHex(hmac)
    }

    // Calculate HMAC-SHA512
    fun hmacSha512(data: String, key: String): String {
        val mac = javax.crypto.Mac.getInstance("HmacSHA512")
        val secretKey = javax.crypto.spec.SecretKeySpec(key.toByteArray(), "HmacSHA512")
        mac.init(secretKey)
        val hmac = mac.doFinal(data.toByteArray())
        return bytesToHex(hmac)
    }

    // Verify HMAC
    fun verifyHmac(data: String, key: String, expectedHmac: String, algorithm: String = "HmacSHA256"): Boolean {
        val actualHmac = when (algorithm) {
            "HmacSHA256" -> hmacSha256(data, key)
            "HmacSHA512" -> hmacSha512(data, key)
            else -> throw IllegalArgumentException("Unsupported algorithm: $algorithm")
        }

        return actualHmac.equals(expectedHmac, ignoreCase = true)
    }

    private fun bytesToHex(bytes: ByteArray): String {
        return bytes.joinToString("") { "%02x".format(it) }
    }
}

// 5. Hash Comparison and Utilities
class HashUtilities {

    // Compare two hashes securely (prevent timing attacks)
    fun secureCompare(hash1: String, hash2: String): Boolean {
        return MessageDigest.isEqual(hash1.toByteArray(), hash2.toByteArray())
    }

    // Generate hash for checksum file
    fun generateChecksum(file: File): String {
        val hasher = FileHasher()
        return hasher.sha256File(file)
    }

    // Create checksum file content
    fun createChecksumContent(file: File): String {
        val hash = FileHasher().sha256File(file)
        return "${hash}  ${file.name}"
    }

    // Parse checksum file
    fun parseChecksumFile(checksumFile: File): Map<String, String> {
        val checksums = mutableMapOf<String, String>()

        checksumFile.forEachLine { line ->
            val parts = line.split("  ")
            if (parts.size == 2) {
                checksums[parts[1]] = parts[0]
            }
        }

        return checksums
    }

    // Verify checksums from file
    fun verifyChecksums(directory: File, checksumFile: File): Boolean {
        val checksums = parseChecksumFile(checksumFile)

        for ((filename, expectedHash) in checksums) {
            val file = File(directory, filename)

            if (!file.exists()) {
                println("File not found: $filename")
                return false
            }

            val actualHash = FileHasher().sha256File(file)

            if (!actualHash.equals(expectedHash, ignoreCase = true)) {
                println("Checksum mismatch for $filename")
                return false
            }
        }

        return true
    }
}

// 6. Hash-based Operations
class HashBasedOperations {

    // Generate hash-based identifier
    fun generateIdentifier(input: String): String {
        val hash = StringHasher().sha256(input)
        return hash.substring(0, 16)
    }

    // Create content-based hash for deduplication
    fun contentHash(content: String): String {
        return StringHasher().sha256(content)
    }

    // Hash-based cache key
    fun createCacheKey(params: Map<String, Any>): String {
        val paramString = params.toList()
            .sortedBy { it.first }
            .joinToString("&") { "${it.first}=${it.second}" }

        return StringHasher().sha256(paramString)
    }

    // Hash-based URL shortener (simplified)
    fun shortenUrl(url: String): String {
        val hash = StringHasher().md5(url)
        return hash.substring(0, 8)
    }

    // Bloom filter hash functions
    fun bloomFilterHashes(item: String, numHashes: Int, filterSize: Int): List<Int> {
        val hashes = mutableListOf<Int>()
        val hash1 = StringHasher().sha256(item)
        val hash2 = StringHasher().md5(item)

        for (i in 0 until numHashes) {
            val combined = hash1 + hash2 + i
            val hash = StringHasher().sha256(combined)
            val index = (hash.substring(0, 8).toInt(16) % filterSize)
            hashes.add(index)
        }

        return hashes
    }
}

// Main demonstration
fun demonstrateHashCalculation() {
    println("=== Android Kotlin Hash Calculation Examples ===\n")

    // 1. String hashing
    println("--- 1. String Hashing ---")
    val stringHasher = StringHasher()

    val text = "Hello, World!"
    println("Text: $text")
    println("MD5: ${stringHasher.md5(text)}")
    println("SHA-1: ${stringHasher.sha1(text)}")
    println("SHA-256: ${stringHasher.sha256(text)}")
    println("SHA-512: ${stringHasher.sha512(text)}")

    // Hash with salt
    val salt = "random_salt_123"
    println("\nHashed with salt '$salt':")
    println("${stringHasher.hashWithSalt(text, salt)}")

    // 2. Password hashing
    println("\n--- 2. Password Hashing ---")
    val passwordHasher = PasswordHasher()

    val password = "SecurePassword123!"
    val generatedSalt = passwordHasher.generateSalt()

    println("Password: $password")
    println("Generated salt: $generatedSalt")

    val hashedPassword = passwordHasher.hashWithIterations(password, generatedSalt, 10000)
    println("Hashed password: $hashedPassword")

    val isValid = passwordHasher.verifyPassword(password, generatedSalt, hashedPassword)
    println("Password verification: $isValid")

    // 3. HMAC
    println("\n--- 3. HMAC ---")
    val hmacHasher = HmacHasher()

    val data = "Important message"
    val key = "secret_key"

    val hmac = hmacHasher.hmacSha256(data, key)
    println("Data: $data")
    println("HMAC-SHA256: $hmac")

    val hmacVerified = hmacHasher.verifyHmac(data, key, hmac)
    println("HMAC verification: $hmacVerified")

    // 4. File hashing
    println("\n--- 4. File Hashing ---")
    val fileHasher = FileHasher()

    // Note: In real usage, you'd have actual files
    println("File hashing methods:")
    println("  - hashFile(): Calculate hash for any file")
    println("  - md5File(): Calculate MD5 of file")
    println("  - sha256File(): Calculate SHA-256 of file")
    println("  - hashFileWithProgress(): Track progress for large files")
    println("  - verifyFileIntegrity(): Verify file against expected hash")

    // 5. Hash utilities
    println("\n--- 5. Hash Utilities ---")
    val hashUtils = HashUtilities()

    val hash1 = "abc123"
    val hash2 = "abc123"
    val hash3 = "xyz789"

    println("Secure compare 'abc123' vs 'abc123': ${hashUtils.secureCompare(hash1, hash2)}")
    println("Secure compare 'abc123' vs 'xyz789': ${hashUtils.secureCompare(hash1, hash3)}")

    // 6. Hash-based operations
    println("\n--- 6. Hash-Based Operations ---")
    val hashOps = HashBasedOperations()

    val identifier = hashOps.generateIdentifier("unique_item_123")
    println("Generated identifier: $identifier")

    val cacheKey = hashOps.createCacheKey(mapOf(
        "user" to "alice",
        "page" to 1,
        "limit" to 20
    ))
    println("Cache key: $cacheKey")

    val shortUrl = hashOps.shortenUrl("https://example.com/very/long/url/path")
    println("Shortened URL: $shortUrl")

    val bloomHashes = hashOps.bloomFilterHashes("test_item", 3, 1000)
    println("Bloom filter hashes: $bloomHashes")

    println("\n=== All Hash Calculation Examples Completed ===")
}

💻 Chiffrement AES kotlin

🔴 complex ⭐⭐⭐⭐⭐

Chiffrer et déchiffrer des données en utilisant AES avec divers modes et schémas de remplissage

⏱️ 40 min 🏷️ kotlin, android, cryptography, encryption
Prerequisites: Advanced Kotlin, Cryptography knowledge
// Android Kotlin AES Encryption Examples
// Using javax.crypto package

import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.PBEKeySpec
import java.security.SecureRandom
import java.security.spec.KeySpec
import java.util.Base64

// 1. Basic AES Encryption
class BasicAesEncryption {

    // Generate AES key
    fun generateKey(keySize: Int = 256): SecretKey {
        val keyGen = KeyGenerator.getInstance("AES")
        keyGen.init(keySize)
        return keyGen.generateKey()
    }

    // Encrypt with AES/GCM/NoPadding
    fun encryptGCM(plainText: String, key: SecretKey): Pair<String, String> {
        val cipher = Cipher.getInstance("AES/GCM/NoPadding")

        // Generate random IV
        val iv = ByteArray(12)
        SecureRandom().nextBytes(iv)
        val ivSpec = IvParameterSpec(iv)

        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec)

        val cipherText = cipher.doFinal(plainText.toByteArray())

        // Return IV and ciphertext as Base64
        val ivBase64 = Base64.getEncoder().encodeToString(iv)
        val cipherTextBase64 = Base64.getEncoder().encodeToString(cipherText)

        return Pair(ivBase64, cipherTextBase64)
    }

    // Decrypt with AES/GCM/NoPadding
    fun decryptGCM(cipherText: String, iv: String, key: SecretKey): String {
        val cipher = Cipher.getInstance("AES/GCM/NoPadding")

        val ivBytes = Base64.getDecoder().decode(iv)
        val cipherTextBytes = Base64.getDecoder().decode(cipherText)

        val ivSpec = IvParameterSpec(ivBytes)
        cipher.init(Cipher.DECRYPT_MODE, key, ivSpec)

        val plainText = cipher.doFinal(cipherTextBytes)
        return String(plainText)
    }

    // Encrypt with AES/CBC/PKCS5Padding
    fun encryptCBC(plainText: String, key: SecretKey): Pair<String, String> {
        val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")

        // Generate random IV (16 bytes for CBC)
        val iv = ByteArray(16)
        SecureRandom().nextBytes(iv)
        val ivSpec = IvParameterSpec(iv)

        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec)

        val cipherText = cipher.doFinal(plainText.toByteArray())

        val ivBase64 = Base64.getEncoder().encodeToString(iv)
        val cipherTextBase64 = Base64.getEncoder().encodeToString(cipherText)

        return Pair(ivBase64, cipherTextBase64)
    }

    // Decrypt with AES/CBC/PKCS5Padding
    fun decryptCBC(cipherText: String, iv: String, key: SecretKey): String {
        val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")

        val ivBytes = Base64.getDecoder().decode(iv)
        val cipherTextBytes = Base64.getDecoder().decode(cipherText)

        val ivSpec = IvParameterSpec(ivBytes)
        cipher.init(Cipher.DECRYPT_MODE, key, ivSpec)

        val plainText = cipher.doFinal(cipherTextBytes)
        return String(plainText)
    }
}

// 2. Password-Based Encryption
class PasswordBasedEncryption {

    // Derive key from password
    fun deriveKeyFromPassword(
                    password: String,
                    salt: ByteArray,
                    keySize: Int = 256,
                    iterations: Int = 65536
    ): SecretKey {
        val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")

        val spec = PBEKeySpec(
            password.toCharArray(),
            salt,
            iterations,
            keySize
        )

        val key = factory.generateSecret(spec)
        return SecretKeySpec(key.encoded, "AES")
    }

    // Generate random salt
    fun generateSalt(size: Int = 16): ByteArray {
        val salt = ByteArray(size)
        SecureRandom().nextBytes(salt)
        return salt
    }

    // Encrypt with password
    fun encryptWithPassword(plainText: String, password: String): Triple<String, String, String> {
        val salt = generateSalt()
        val key = deriveKeyFromPassword(password, salt)

        val aes = BasicAesEncryption()
        val (iv, cipherText) = aes.encryptGCM(plainText, key)

        val saltBase64 = Base64.getEncoder().encodeToString(salt)

        return Triple(saltBase64, iv, cipherText)
    }

    // Decrypt with password
    fun decryptWithPassword(
                    cipherText: String,
                    iv: String,
                    salt: String,
                    password: String
    ): String {
        val saltBytes = Base64.getDecoder().decode(salt)
        val key = deriveKeyFromPassword(password, saltBytes)

        val aes = BasicAesEncryption()
        return aes.decryptGCM(cipherText, iv, key)
    }

    // Generate key with specific iterations
    fun generateStrongKey(password: String, iterations: Int = 100000): SecretKey {
        val salt = generateSalt()
        return deriveKeyFromPassword(password, salt, 256, iterations)
    }
}

// 3. File Encryption
class FileEncryption {

    // Encrypt file
    fun encryptFile(
                    inputFile: java.io.File,
                    outputFile: java.io.File,
                    key: SecretKey
    ): Boolean {
        return try {
            val cipher = Cipher.getInstance("AES/GCM/NoPadding")

            val iv = ByteArray(12)
            SecureRandom().nextBytes(iv)
            val ivSpec = IvParameterSpec(iv)

            cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec)

            // Write IV first
            java.io.FileOutputStream(outputFile).use { fos ->
                fos.write(iv)

                // Encrypt file content
                java.io.FileInputStream(inputFile).use { fis ->
                    val cipherStream = javax.crypto.CipherOutputStream(fos, cipher)
                    val buffer = ByteArray(4096)
                    var bytesRead: Int

                    while (fis.read(buffer).also { bytesRead = it } != -1) {
                        cipherStream.write(buffer, 0, bytesRead)
                    }

                    cipherStream.close()
                }
            }

            true
        } catch (e: Exception) {
            println("Error encrypting file: ${e.message}")
            false
        }
    }

    // Decrypt file
    fun decryptFile(
                    inputFile: java.io.File,
                    outputFile: java.io.File,
                    key: SecretKey
    ): Boolean {
        return try {
            val cipher = Cipher.getInstance("AES/GCM/NoPadding")

            // Read IV first
            java.io.FileInputStream(inputFile).use { fis ->
                val iv = ByteArray(12)
                fis.read(iv)

                val ivSpec = IvParameterSpec(iv)
                cipher.init(Cipher.DECRYPT_MODE, key, ivSpec)

                // Decrypt file content
                java.io.FileOutputStream(outputFile).use { fos ->
                    val cipherStream = javax.crypto.CipherInputStream(fis, cipher)
                    val buffer = ByteArray(4096)
                    var bytesRead: Int

                    while (cipherStream.read(buffer).also { bytesRead = it } != -1) {
                        fos.write(buffer, 0, bytesRead)
                    }

                    cipherStream.close()
                }
            }

            true
        } catch (e: Exception) {
            println("Error decrypting file: ${e.message}")
            false
        }
    }
}

// 4. String Encryption Utilities
class StringEncryptionUtils {

    private val aes = BasicAesEncryption()
    private val passwordEnc = PasswordBasedEncryption()

    // Encrypt string to Base64 (combined IV + ciphertext)
    fun encryptStringToBase64(plainText: String, password: String): String {
        val (salt, iv, cipherText) = passwordEnc.encryptWithPassword(plainText, password)

        // Combine salt + iv + ciphertext
        val combined = "$salt:$iv:$cipherText"
        return Base64.getEncoder().encodeToString(combined.toByteArray())
    }

    // Decrypt string from Base64
    fun decryptStringFromBase64(encoded: String, password: String): String {
        val combined = String(Base64.getDecoder().decode(encoded))
        val parts = combined.split(":")

        if (parts.size != 3) {
            throw IllegalArgumentException("Invalid encrypted format")
        }

        val (salt, iv, cipherText) = parts
        return passwordEnc.decryptWithPassword(cipherText, iv, salt, password)
    }

    // Encrypt multiple strings
    fun encryptStrings(strings: List<String>, key: SecretKey): List<Pair<String, String>> {
        return strings.map { text ->
            val (iv, cipherText) = aes.encryptGCM(text, key)
            text to cipherText
        }
    }

    // Decrypt multiple strings
    fun decryptStrings(encryptedData: List<Pair<String, String>>, key: SecretKey): List<String> {
        return encryptedData.map { (original, cipherText) ->
            // Assuming IV is stored separately or embedded
            // For simplicity, using same IV for demo
            aes.decryptGCM(cipherText, "base64_iv_placeholder", key)
        }
    }
}

// 5. Advanced AES Operations
class AdvancedAesOperations {

    // Encrypt with custom IV
    fun encryptWithCustomIV(plainText: String, key: SecretKey, iv: ByteArray): String {
        val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")

        val ivSpec = IvParameterSpec(iv)
        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec)

        val cipherText = cipher.doFinal(plainText.toByteArray())
        return Base64.getEncoder().encodeToString(cipherText)
    }

    // Encrypt with AES-ECB (not recommended for production)
    fun encryptECB(plainText: String, key: SecretKey): String {
        val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
        cipher.init(Cipher.ENCRYPT_MODE, key)

        val cipherText = cipher.doFinal(plainText.toByteArray())
        return Base64.getEncoder().encodeToString(cipherText)
    }

    // Decrypt with AES-ECB
    fun decryptECB(cipherText: String, key: SecretKey): String {
        val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
        cipher.init(Cipher.DECRYPT_MODE, key)

        val cipherTextBytes = Base64.getDecoder().decode(cipherText)
        val plainText = cipher.doFinal(cipherTextBytes)

        return String(plainText)
    }

    // Generate AES key from bytes
    fun keyFromBytes(keyBytes: ByteArray): SecretKey {
        require(keyBytes.size == 16 || keyBytes.size == 24 || keyBytes.size == 32) {
            "Key must be 16, 24, or 32 bytes"
        }
        return SecretKeySpec(keyBytes, "AES")
    }

    // Generate AES key from password (simple version)
    fun keyFromPassword(password: String, keySize: Int = 256): SecretKey {
        val keyBytes = password.toByteArray().copyOf(keySize / 8)
        return keyFromBytes(keyBytes)
    }
}

// 6. Secure Key Management
class KeyManager {

    // Store key securely (in Android Keystore)
    fun storeKeyInKeystore(alias: String, key: SecretKey): Boolean {
        // Note: This requires Android Keystore integration
        // Simplified example
        return try {
            // In production, use AndroidKeyStore
            val keyStore = java.security.KeyStore.getInstance("AndroidKeyStore")
            keyStore.load(null)

            if (!keyStore.containsAlias(alias)) {
                keyStore.setEntry(
                    alias,
                    java.security.KeyStore.SecretKeyEntry(key),
                    java.security.KeyProtection.Builder(
                        javax.crypto.spec.SecretKeySpec(key.encoded, "AES")
                    ).build()
                )
            }

            true
        } catch (e: Exception) {
            println("Error storing key: ${e.message}")
            false
        }
    }

    // Load key from keystore
    fun loadKeyFromKeystore(alias: String): SecretKey? {
        return try {
            val keyStore = java.security.KeyStore.getInstance("AndroidKeyStore")
            keyStore.load(null)

            val entry = keyStore.getEntry(alias, null) as? java.security.KeyStore.SecretKeyEntry
            entry?.secretKey
        } catch (e: Exception) {
            println("Error loading key: ${e.message}")
            null
        }
    }

    // Generate and store key
    fun generateAndStoreKey(alias: String, keySize: Int = 256): SecretKey? {
        val key = KeyGenerator.getInstance("AES").apply {
            init(keySize)
        }.generateKey()

        return if (storeKeyInKeystore(alias, key)) {
            key
        } else {
            null
        }
    }
}

// Main demonstration
fun demonstrateAesEncryption() {
    println("=== Android Kotlin AES Encryption Examples ===\n")

    // 1. Basic encryption
    println("--- 1. Basic AES Encryption ---")
    val aes = BasicAesEncryption()

    val key = aes.generateKey(256)
    println("Generated AES key: ${key.algorithm}")

    val plainText = "This is a secret message!"
    println("Plaintext: $plainText")

    val (iv, cipherText) = aes.encryptGCM(plainText, key)
    println("\nEncrypted with AES/GCM:")
    println("IV: $iv")
    println("Ciphertext: $cipherText")

    val decrypted = aes.decryptGCM(cipherText, iv, key)
    println("\nDecrypted: $decrypted")

    // 2. CBC mode
    println("\n--- 2. CBC Mode ---")
    val (ivCbc, cipherTextCbc) = aes.encryptCBC(plainText, key)
    println("Encrypted with AES/CBC:")
    println("Ciphertext: $cipherTextCbc")

    val decryptedCbc = aes.decryptCBC(cipherTextCbc, ivCbc, key)
    println("Decrypted: $decryptedCbc")

    // 3. Password-based encryption
    println("\n--- 3. Password-Based Encryption ---")
    val passwordEnc = PasswordBasedEncryption()

    val password = "SecurePassword123!"
    val (salt, ivPbe, cipherTextPbe) = passwordEnc.encryptWithPassword(plainText, password)

    println("Encrypted with password:")
    println("Salt: $salt")
    println("Ciphertext: $cipherTextPbe")

    val decryptedPbe = passwordEnc.decryptWithPassword(cipherTextPbe, ivPbe, salt, password)
    println("Decrypted: $decryptedPbe")

    // 4. String utilities
    println("\n--- 4. String Encryption Utilities ---")
    val stringUtils = StringEncryptionUtils()

    val base64Encrypted = stringUtils.encryptStringToBase64("Hello, World!", password)
    println("Base64 encrypted: $base64Encrypted")

    val base64Decrypted = stringUtils.decryptStringFromBase64(base64Encrypted, password)
    println("Decrypted: $base64Decrypted")

    // 5. Advanced operations
    println("\n--- 5. Advanced Operations ---")
    val advancedOps = AdvancedAesOperations()

    val customIv = ByteArray(16)
    SecureRandom().nextBytes(customIv)

    val customEncrypted = advancedOps.encryptWithCustomIV(plainText, key, customIv)
    println("Encrypted with custom IV: $customEncrypted")

    // Note: File encryption requires actual files
    println("\n--- 6. File Encryption ---")
    println("File encryption methods:")
    println("  - encryptFile(): Encrypt entire file")
    println("  - decryptFile(): Decrypt encrypted file")

    // 7. Key management
    println("\n--- 7. Key Management ---")
    val keyManager = KeyManager()
    println("Key management methods:")
    println("  - generateAndStoreKey(): Generate and store in Android Keystore")
    println("  - loadKeyFromKeystore(): Load stored key")
    println("  - keyFromBytes(): Create key from byte array")
    println("  - keyFromPassword(): Derive key from password")

    println("\n=== All AES Encryption Examples Completed ===")
}