Skip to content

Installation

Ron Lauren Hombre edited this page Mar 20, 2024 · 13 revisions

Installing KyberKotlin

As a Kotlin Multiplatform(KMM) library, KyberKotlin has many ways it can be installed. As of now, we support JVM(Kotlin, Java, Android), Native(C, C++, C#), and JS(NPM).

JVM (Kotlin, Java, Android)

Requirements: JAVA 8+

NOTE: if implementation does not work, replace with compile.

Gradle through Maven

build.gradle

dependencies {
    implementation 'asia.hombre:kyber:0.5.1'
}

Gradle Kotlin through Maven

build.gradle.kts

dependencies {
    implementation("asia.hombre:kyber:0.5.1")
}

Gradle as a JAR

build.gradle

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

NOTE: If you already have this line of code, you can omit it and skip to copying the JAR file into the correct directory.

Download a JAR file from Releases and copy it into libs/ of your project directory. Bonus points if you can change the directory to wherever you want.

Gradle Kotlin as a JAR

build.gradle.kts

dependencies {
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
}

NOTE: If you already have this line of code, you can omit it and skip to copying the JAR file into the correct directory.

Download a JAR file from Releases and copy it into libs/ of your project directory. Bonus points if you can change the directory to wherever you want.

Maven

pom.xml

<dependency>
    <groupId>asia.hombre</groupId>
    <artifactId>kyber</artifactId>
    <version>0.5.1</version>
</dependency>

MINGW/NATIVE (C#/C/C++)

Download and extract kyber-0.5.1-native-mingw-windows.zip from Releases and copy the contents inside your project.

NPM JS

Hello World for KyberKotlin

Now that you are done with the installation, you may move on to testing if the library works for you.

Kotlin

import asia.hombre.kyber.KyberAgreement
import asia.hombre.kyber.KyberKeyGenerator
import asia.hombre.kyber.KyberParameter

//Generate keys
//This would be done in their own systems
val keyPairAlice = KyberKeyGenerator.generate(KyberParameter.ML_KEM_512)
val keyPairBob = KyberKeyGenerator.generate(KyberParameter.ML_KEM_512)

val agreementAlice = KyberAgreement(keyPairAlice)

//Bob sends his encapsulation key to Alice
//Alice uses it to encapsulate a Secret Key
val cipherTextAlice = agreementAlice.encapsulate(keyPairBob.encapsulationKey)

val agreementBob = KyberAgreement(keyPairBob)

//Alice sends the Cipher Text to Bob
//Bob decapsulates the Cipher Text
val secretKeyBob = agreementBob.decapsulate(cipherTextAlice.cipherText)

//Alice generated the Secret Key
println("[" + cipherTextAlice.secretKey.joinToString(", ") + "]")
//Bob decapsulated the same Secret Key
println("[" + secretKeyBob.joinToString(", ") + "]")

//secretKeyBob == cipherTextAlice.secretKey

Java

import asia.hombre.kyber.KyberKeyGenerator;
import asia.hombre.kyber.KyberKEMKeyPair;
import asia.hombre.kyber.KyberParameter;
import asia.hombre.kyber.KyberAgreement;
import asia.hombre.kyber.KyberEncapsulationResult;

//Generate keys
//This would be done in their own systems
KyberKEMKeyPair keyPairAlice = KyberKeyGenerator.generate(KyberParameter.ML_KEM_512);
KyberKEMKeyPair keyPairBob = KyberKeyGenerator.generate(KyberParameter.ML_KEM_512);

KyberAgreement agreementAlice = new KyberAgreement(keyPairAlice);

//Bob sends his encapsulation key to Alice
//Alice uses it to encapsulate a Secret Key
KyberEncapsulationResult encapsResult = agreementAlice.encapsulate(keyPairBob.getEncapsulationKey());

KyberAgreement agreementBob = new KyberAgreement(keyPairBob);

//Alice sends the Cipher Text to Bob
//Bob decapsulates the Cipher Text
byte[] decapsSecretKey = agreementBob.decapsulate(encapsResult.getCipherText());

//Alice generated the Secret Key
System.out.println(Arrays.toString(encapsResult.getSecretKey()));
//Bob decapsulated the same Secret Key
System.out.println(Arrays.toString(decapsSecretKey));

//encapsResult.getSecretKey() == decapsSecretKey

C#

using System.Runtime.InteropServices;

//Use absolute path if relative does not work.
const string dllName = "KyberKotlin.dll";

//Declare methods from the DLL.
[DllImport(dllName, EntryPoint = "generateKeyPair")]
static extern IntPtr generateKeyPair(int parameterId);

[DllImport(dllName, EntryPoint = "getEncapsulationKeySize")]
static extern int getEncapsulationKeySize(int parameterId);

[DllImport(dllName, EntryPoint = "getDecapsulationKeySize")]
static extern int getDecapsulationKeySize(int parameterId);

[DllImport(dllName, EntryPoint = "getCipherTextSize")]
static extern int getCipherTextSize(int parameterId);

[DllImport(dllName, EntryPoint = "getSecretKeySize")]
static extern int getSecretKeySize();

[DllImport(dllName, EntryPoint = "encapsulate")]
static extern IntPtr encapsulate(byte[] encapsulationKey, int parameterId);

[DllImport(dllName, EntryPoint = "decapsulate")]
static extern IntPtr decapsulate(byte[] decapsulationKey, byte[] cipherText, int parameterId);

//Get sizes
int encapsulationKeySize = getEncapsulationKeySize(0); //0 = 512, 1 = 768, 2 = 1024
int decapsulationKeySize = getDecapsulationKeySize(0);
int cipherTextSize = getCipherTextSize(0);

//Generate Key Pair
IntPtr keysPtr = generateKeyPair(0);

byte[] encapsulationKey = new byte[encapsulationKeySize];
byte[] decapsulationKey = new byte[decapsulationKeySize];

Marshal.Copy(keysPtr, encapsulationKey, 0, encapsulationKey.Length);
Marshal.Copy(keysPtr + encapsulationKey.Length, decapsulationKey, 0, decapsulationKey.Length);

//Send encapsulation key to Bob
//Bob encapsulates using it
IntPtr cipherPtr = encapsulate(encapsulationKey, 0);

//Bob receives the Secret Key
byte[] secretKey = new byte[getSecretKeySize()];
byte[] cipherText = new byte[cipherTextSize];

Marshal.Copy(cipherPtr, secretKey, 0, secretKey.Length);
Marshal.Copy(cipherPtr + secretKey.Length, cipherText, 0, cipherText.Length);

//Bob sends the Cipher Text to Alice
//Alice uses it to get a copy of the Secret Key
IntPtr secretKeyPtr = decapsulate(decapsulationKey, cipherText, 0);

//Alice's Copy of the Secret Key
byte[] secretKey2 = new byte[getSecretKeySize()];

Marshal.Copy(secretKeyPtr, secretKey2, 0, secretKey2.Length);

JS

const { KyberParameter, KyberKeyGenerator, KyberAgreement } = require("kyberkotlin").asia.hombre.kyber;

//Generate keys
let aliceKeypair = KyberKeyGenerator.Companion.generate(KyberParameter.ML_KEM_512);
let bobKeypair = KyberKeyGenerator.Companion.generate(KyberParameter.ML_KEM_512);

let aliceAgreement = new KyberAgreement(aliceKeypair);
let bobAgreement = new KyberAgreement(bobKeypair);

//Bob encapsulates using Alice's encapsulation key
let results = bobAgreement.encapsulate(aliceKeypair.encapsulationKey);

let ciphertext = results.cipherText;
let bobSecretKey = results.secretKey;

//Bob sends the Cipher Text to Bob
//Alice decapsulates the Cipher Text
let aliceSecretKey = aliceAgreement.decapsulate(ciphertext);

console.assert(contentEquals(aliceSecretKey, bobSecretKey), "Secret Keys does not match!");

//Simple check
function contentEquals(a, b) {
    for(let i = 0; i < a.length; i++)
        if(a[i] !== b[i])
            return false;
    return true;
}

Expected Similar Output:

[91, 119, -51, 71, -106, 30, -66, 47, 53, -7, -119, -38, -78, 61, -27, 44, -15, -47, -115, -92, -26, -120, 124, -17, -121, 83, 0, -57, -71, 118, 2, -31]
[91, 119, -51, 71, -106, 30, -66, 47, 53, -7, -119, -38, -78, 61, -27, 44, -15, -47, -115, -92, -26, -120, 124, -17, -121, 83, 0, -57, -71, 118, 2, -31]

Of course, your output will vary, but these two output values should be 100% the same for you. Otherwise, something went wrong. Please review the Documentation or Open an issue for us to fix it.

Conclusion

If everything looks good, you may use KyberKotlin as you may deem fit. Notice how Java code is more verbose than Kotlin code. I hate it.

For a detailed documentation, visit our Documentation website.