Crypto
Krypto is a cryptography library for Multiplatform Kotlin.
SecureRandom
Krypto provides a SecureRandom
object that extends the kotlin.random.Random
class,
but it generates cryptographic secure values. It is a singleton, and you cannot provide an initial seed.
Instead of a pseudo-random and reproducible, its result values are fully random, making it suitable for cryptographic purposes, and not suitable for reproductible results.
It uses SecureRandom
on the JVM + PRNGFixes
on Android.
On Native POSIX (including Linux, macOS and iOS), it uses /dev/urandom
, on Windows
BCryptGenRandom
Using the SecureRandom instance
Since it is an object, you can use it directly as a Random
instance:
val random: Random = SecureRandom
Seeding extra bytes
In addition to the standard kotlin Random
interface, SecureRandom provides a method for seeding extra random bytes.
val bytes = byteArrayOf(1, 2, 3)
SecureRandom.addSeed(bytes)
Hash (MD4/MD5/SHA1/SHA256/SHA512)
Korlibs crypto supports hashing byte arrays, and synchronous and asynchronous streams for different algorithms in an extensible fashion.
There are a few predefined hashing methods available out of the box:
object MD4 : HasherFactory
object MD5 : HasherFactory
object SHA1 : HasherFactory
object SHA256 : HasherFactory
object SHA512 : HasherFactory
Then you can hash different binary sources like ByteArray
, AsyncInputStream
, AsyncOpenableStream
or a SyncInputStream
:
// Synchronous hashing
fun ByteArray.hash(algo: HashFactory): Hash
fun SyncInputStream.hash(algo: HasherFactory): Hash
// Asynchronous hashing
suspend fun AsyncInputOpenable.hash(algo: HasherFactory): Hash
suspend fun AsyncInputStream.hash(algo: HasherFactory): Hash
// In the JVM:
fun InputStream.hash(algo: HasherFactory): Hash
So for example, to get the hex representation of a SHA1 hash for the bytes 1, 2, 3
you would:
println(byteArrayOf(1, 2, 3).hash(SHA1).hex)
There are shortcuts for the out of the box provided HashFactory
:
fun ByteArray.md4(): Hash
fun ByteArray.md5(): Hash
fun ByteArray.sha1(): Hash
fun ByteArray.sha256(): Hash
fun ByteArray.sha512(): Hash
The HasherFactory
looks like this:
open class HasherFactory() {
operator fun invoke(): Hasher
}
// Shortcuts to digest from it
fun HasherFactory.digest(data: ByteArray): Hash
inline fun HasherFactory.digest(readBytes: (data: ByteArray) -> Int): Hash
Then the Hasher
class looks like this:
abstract class Hasher(val chunkSize: Int, val digestSize: Int, val name: String) {
open fun reset(): Hasher
open fun update(data: ByteArray, offset: Int, count: Int): Hasher
open fun digestOut(out: ByteArray)
fun update(data: ByteArray)
fun digest(): Hash
}
Getting raw, hex or base64 representations from a Hash
instance
From a Hash class, it is possible to get itβs raw bytes, or the hexadecimal or base64 representations:
println(hash.bytes.toList())
println(hash.base64)
println(hash.base64Url)
println(hash.hex)
println(hash.hexLower)
println(hash.hexUpper)
class Hash {
constructor(bytes: ByteArray)
companion object {
fun fromHex(hex: String): Hash
fun fromBase64(base64: String): Hash
}
val bytes: ByteArray
val base64: String
val base64Url: String
val hex: String
val hexLower: String
val hexUpper: String
}
HMAC
PBKDF2
AES
object AES {
fun decryptAes128Cbc(encryptedMessage: ByteArray, cipherKey: ByteArray): ByteArray
fun encryptEes128Cbc(plainMessage: ByteArray, cipherKey: ByteArray): ByteArray
}