Skip to content

Installation

Ron Lauren Hombre edited this page Dec 24, 2024 · 15 revisions

Installing KyberKotlin

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

JVM (Kotlin, Java, Android)

Requirements: JAVA 8+

NOTE: If implementation does not work, replace it with compile.

Gradle through Maven

build.gradle

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

Gradle Kotlin through Maven

build.gradle.kts

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

Maven

pom.xml

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

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.KyberCipherText
import asia.hombre.kyber.KyberEncapsulationKey
import asia.hombre.kyber.KyberKeyGenerator
import asia.hombre.kyber.KyberParameter

fun main() {
    //Alice generates an ML-KEM Keypair containing a Decapsulation(Private) Key and an Encapsulation(Public) Key
    val keyPairAlice = KyberKeyGenerator.generate(KyberParameter.ML_KEM_512)

    //Alice sends the Encapsulation Key to Bob
    val keyBytesToBob = keyPairAlice.encapsulationKey.fullBytes //You can convert this to any format

    //Bob creates an instance of the Encapsulation Key from the bytes Alice sent
    val aliceEncapsKey = KyberEncapsulationKey.fromBytes(keyBytesToBob)
    //NOTE: Throws UnsupportedKyberVariantException or InvalidKyberKeyException if the bytes are corrupted or incorrect.

    //Bob runs the encapsulation algorithm. Here, this is just a method you call
    val encapsResult = aliceEncapsKey.encapsulate()
    //The result contains both the Cipher Text and the Shared Secret Key

    //Bob returns the Cipher Text to Alice
    val cipherTextBytesToAlice = encapsResult.cipherText.fullBytes //You can convert this to any format

    //Alice creates an instance of a Cipher Text from the bytes Bob responds with
    val bobCipherText = KyberCipherText.fromBytes(cipherTextBytesToAlice)
    //NOTE: Throws UnsupportedKyberVariantException if the bytes are corrupted or incorrect.

    //Alice runs the decapsulation algorithm. Here, this is just a method you call
    val decapsResult = keyPairAlice.decapsulationKey.decapsulate(bobCipherText)
    //The returned value is the Shared Secret Key

    //Alice generated the Secret Key
    println("[" + encapsResult.sharedSecretKey.joinToString(", ") + "]")
    //Bob decapsulated the same Secret Key
    println("[" + decapsResult.joinToString(", ") + "]")

    println(decapsResult.contentEquals(encapsResult.sharedSecretKey))

    /* IMPORTANT NOTE:
        In this library, Bob DOES NOT need to generate an ML-KEM Key Pair. Bob only needs to ENCAPSULATE and RETURN the
    Cipher Text to Alice.

        THE RESULT OF THIS LIBRARY MUST WORK WITH ALL ML-KEM SPECIFIED LIBRARIES. THUS, IT DOES NOT MATTER IF THE BOB
    IN YOUR ARCHITECTURE OR SYSTEM USES KyberKotlin.
     */
}

Java

import asia.hombre.kyber.*;
import asia.hombre.kyber.exceptions.InvalidKyberKeyException;
import asia.hombre.kyber.exceptions.UnsupportedKyberVariantException;

import java.util.Arrays;

public class JavaMain {
    public static void main(String[] args) {
        //Alice generates an ML-KEM Keypair containing a Decapsulation(Private) Key and an Encapsulation(Public) Key
        KyberKEMKeyPair keyPairAlice = KyberKeyGenerator.generate(KyberParameter.ML_KEM_512);

        //Alice sends the Encapsulation Key to Bob
        byte[] keyBytesToBob = keyPairAlice.getEncapsulationKey().getFullBytes(); //You can convert this to any format

        //Bob creates an instance of the Encapsulation Key from the bytes Alice sent
        KyberEncapsulationKey aliceEncapsKey = null;
        try {
            aliceEncapsKey = KyberEncapsulationKey.fromBytes(keyBytesToBob);
        } catch (UnsupportedKyberVariantException | InvalidKyberKeyException e) {
            throw new RuntimeException(e); //TODO: Handle this gracefully.
        }

        //Bob runs the encapsulation algorithm. Here, this is just a method you call
        KyberEncapsulationResult encapsResult = aliceEncapsKey.encapsulate();
        //The result contains both the Cipher Text and the Shared Secret Key

        //Bob returns the Cipher Text to Alice
        byte[] cipherTextBytesToAlice = encapsResult.getCipherText().getFullBytes(); //You can convert this to any format

        //Alice creates an instance of a Cipher Text from the bytes Bob responds with
        KyberCipherText bobCipherText = null;
        try {
            bobCipherText = KyberCipherText.fromBytes(cipherTextBytesToAlice);
        } catch (UnsupportedKyberVariantException e) {
            throw new RuntimeException(e); //TODO: Handle this gracefully.
        }

        //Alice runs the decapsulation algorithm. Here, this is just a method you call
        byte[] decapsResult = keyPairAlice.getDecapsulationKey().decapsulate(bobCipherText);
        //The returned value is the Shared Secret Key

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

        System.out.println(Arrays.equals(encapsResult.getSharedSecretKey(), decapsResult));

        /* IMPORTANT NOTE:
            In this library, Bob DOES NOT need to generate an ML-KEM Key Pair. Bob only needs to ENCAPSULATE and RETURN the
        Cipher Text to Alice.

            THE RESULT OF THIS LIBRARY MUST WORK WITH ALL ML-KEM SPECIFIED LIBRARIES. THUS, IT DOES NOT MATTER IF THE BOB
        IN YOUR ARCHITECTURE OR SYSTEM USES KyberKotlin.
         */
    }
}

JS

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

function sample() {
    //Alice generates an ML-KEM Keypair containing a Decapsulation(Private) Key and an Encapsulation(Public) Key
    let keyPairAlice = KyberKeyGenerator.generate(KyberParameter.ML_KEM_512)

    //Alice sends the Encapsulation Key to Bob
    let keyBytesToBob = keyPairAlice.encapsulationKey.fullBytes //You can convert this to any format

    //Bob creates an instance of the Encapsulation Key from the bytes Alice sent
    let aliceEncapsKey = KyberEncapsulationKey.Companion.fromBytes(keyBytesToBob)
    //NOTE: Throws UnsupportedKyberVariantException or InvalidKyberKeyException if the bytes are corrupted or incorrect.

    //Bob runs the encapsulation algorithm. Here, this is just a method you call
    let encapsResult = aliceEncapsKey.encapsulate()
    //The result contains both the Cipher Text and the Shared Secret Key

    //Bob returns the Cipher Text to Alice
    let cipherTextBytesToAlice = encapsResult.cipherText.fullBytes //You can convert this to any format

    //Alice creates an instance of a Cipher Text from the bytes Bob responds with
    let bobCipherText = KyberCipherText.Companion.fromBytes(cipherTextBytesToAlice)
    //NOTE: Throws UnsupportedKyberVariantException if the bytes are corrupted or incorrect.

    //Alice runs the decapsulation algorithm. Here, this is just a method you call
    let decapsResult = keyPairAlice.decapsulationKey.decapsulate(bobCipherText)
    //The returned value is the Shared Secret Key

    //Alice generated the Secret Key
    console.log(encapsResult.sharedSecretKey)
    //Bob decapsulated the same Secret Key
    console.log(decapsResult)

    console.log(contentEquals(encapsResult.sharedSecretKey, decapsResult))

    /* IMPORTANT NOTE:
        In this library, Bob DOES NOT need to generate an ML-KEM Key Pair. Bob only needs to ENCAPSULATE and RETURN the
    Cipher Text to Alice.

        THE RESULT OF THIS LIBRARY MUST WORK WITH ALL ML-KEM SPECIFIED LIBRARIES. THUS, IT DOES NOT MATTER IF THE BOB
    IN YOUR ARCHITECTURE OR SYSTEM USES KyberKotlin.
     */
}

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

sample()

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 deem fit. Notice how Java code is more verbose than Kotlin code. I hate it.

For a detailed documentation, visit our Documentation website.