Encrypt yo mamma with Kotlin

and also totally do some other crypto-y things.

Image for post
Image for post

These examples use Kalium, a wrapper for libsodium/NaCL encryption. A sample gradle file follows.

Our first example is a simple SHA512 hash. The library provides SHA512 hash for backwards compatibility, but SHA512 should not be used on new projects, because of the possibility of collisions.

We use the included HEX encode/decode functions.

fun main(args: Array<String>) {

val hash = Hash()
val DATA: String = "yo mamma"
val tb = hash.sha512(DATA.toByteArray())
println("SHA512 HASH:")
println (HEX.encode(tb))
}

New projects should use the Blake2b hash.

    val gb = hash.blake2(DATA.toByteArray())
println("Blake2 Hash:")
println (HEX.encode(gb))

If you are storing a password hash, you should use a secure password hash function. The following example uses scrypt/SALSA20

val password = Password()
val PWHASH_MESSAGE: String = "yo mamma"
val PWHASH_SALT: String = "[<~A 32-bytes salt for scrypt~>]"
val opslimit: Int = NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE
val memlimit: Int = NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE

val pw = password.hash(PWHASH_MESSAGE.toByteArray(),
HEX,
PWHASH_SALT.toByteArray(),
opslimit,
memlimit.toLong());

println ("Scrypt hashed password:")
println (pw)

note: You should not use the same salt more than once.

From time to time we need cryptographically secure random bytes.

val rb = Random().randomBytes(64)
println("Random Bytes:")
println (HEX.encode(rb))

For symmetric key encryption, we use the SecretBox function, providing a shared secret and nonce. Both parties use the same password to encrypt and decrypt the message.

val secretKey: String = "1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389"
val boxNonce: String = "69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37"
val yomamma: String = "yo mamma"

var box = SecretBox(secretKey, HEX)
val nonce: ByteArray = HEX.decode(boxNonce)

val message = yomamma.toByteArray()
val ciphertext = box.encrypt(nonce, message)
println("(Symmetric Key) Encrypted")
println(HEX.encode(ciphertext))

val cleartext = box.decrypt(nonce, ciphertext)
println("(Symmetric Key) Decrypted")
val omsg: String = String(cleartext)
println(omsg)

Normally we want to use Asymmetric encryption, where two parties in a communication exchange have their own public and secret keys. The message is encrypted using a public key, but the message can only be decrypted using the corresponding secret key. While the sender can have the public key, they would not have the secret key of the recipient, necessary to decrypt messages.

For asymmetric encryption we use the SealedBox function. ‘nsk’ is the secret key, ‘npk’ is the public key.

val aMessage: String = "yo mamma"
val m: ByteArray = aMessage.toByteArray()
var nkeyPair: KeyPair = KeyPair(ByteArray(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES));

val nsk: ByteArray = nkeyPair.getPrivateKey().toBytes()
val npk: ByteArray = nkeyPair.getPublicKey().toBytes()

println("pk:")
println(HEX.encode(npk))

//encrypt
var sb = SealedBox(npk)
val c: ByteArray = sb.encrypt(m);

println("Encrypted (Asymmetric Keys)")
println(HEX.encode(c))

//decrypt
var sb2 = SealedBox(npk, nsk)
val m2: ByteArray = sb2.decrypt(c)

println("Decrypted (Asymmetric Keys)")
println(String(m2))

In this example we shall sign a message and create detached signature, then verify that the signature is valid. We create a secret signing key and corresponding public verification key, which is distributed in order for a recipient to verify that we indeed signed the message.

var tkeyPair = KeyPair()

val tsk: ByteArray = tkeyPair.privateKey.toBytes()
val tpk: ByteArray = tkeyPair.publicKey.toBytes()

println("generated Secret Key (sk):")
println(HEX.encode(tsk))
println("Generated Public Key (pk):")
println(HEX.encode(tpk))



val controllerPk = "28ece8b8a0d1717fc009459f742015d169bf620992924bb11f6873bee2251b30"
val myPk = "96f1eefb3c837972e9e4a2a03b516104529b0d0e96a760f58114ac82bd898b39"
val myVk = "f09044aada58127fda6c8522f16be55ddb9e50b8132ad973306ff46ab94ef173"
val pk: ByteArray = HEX.decode(myPk)
val opk: ByteArray = HEX.decode(controllerPk)
val mySk = "433d9cbadf8f72219e3d08d406918a02366d585f1419a4777e8ae84fe6f53210"
val sk: ByteArray = HEX.decode(mySk)

val signkey = SigningKey(mySk, HEX)
val verifykey = signkey.verifyKey
println
("Verify Signing Key:" + HEX.encode(verifykey.toBytes()))

var msg: String = "yo mamma"
var xmsg: String = HEX.encode(msg.toByteArray())
val signature = signkey.sign(xmsg, HEX)
val vxkey = VerifyKey(myVk,HEX)
println("Detached Signature:")
println(signature)
val check = vxkey.verify(xmsg, signature, HEX)
if (check)
{
println("Signature Verified")
} else {
println("Signature failed")
}

Here is the sample output from our examples:

Here is the combined source code:

Example gradle build file

questions? comments? need help? Contact me at waitman@waitman.net or +1 650 900 8557

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store