Skip to content
This repository has been archived by the owner on Aug 12, 2024. It is now read-only.

Commit

Permalink
Add readKeyFromFile and delegate setter
Browse files Browse the repository at this point in the history
  • Loading branch information
Cach30verfl0w committed Jun 13, 2024
1 parent 94f1984 commit 3f9cb08
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 1 deletion.
1 change: 1 addition & 0 deletions kmp-advcrypto/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ kotlin {
implementation(libs.bouncycastle.prov)
}
commonMain.dependencies {
implementation(libs.okio)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

package io.karma.advcrypto.algorithm.delegates

import io.karma.advcrypto.keys.Key
import io.karma.advcrypto.wrapper.KeyStore
import okio.Path

/**
* This delegate implements the functionality of a keystore. This keystore is used to load files
Expand All @@ -30,6 +32,7 @@ import io.karma.advcrypto.wrapper.KeyStore
*/
class KeyStoreFactory<C: Any>(val name: String) {
private lateinit var initialize: () -> C
private var readKeyFromFile: ((C, Path) -> Key)? = null

/**
* This method creates a new keystore with the delegate functions specified and initializes the
Expand All @@ -42,6 +45,18 @@ class KeyStoreFactory<C: Any>(val name: String) {
*/
fun createKeyStore(): KeyStore = object: KeyStore {
private val context = initialize()

/**
* This method opens the file with `okio` and reads the content as a bytearray. This content
* is used to extract information from the key and return this key to the user.
*
* @param path The path of the file
* @return The key derived from the file
*
* @author Cedric Hammes
* @since 14/06/2024
*/
override fun readKeyFromFile(path: Path): Key = readKeyFromFile!!.invoke(context, path)
}

/**
Expand All @@ -53,4 +68,17 @@ class KeyStoreFactory<C: Any>(val name: String) {
*/
fun initialize(closure: () -> C) = this.apply { initialize = closure }

/**
* This method sets the method delegate to the `readKeyFromFile` method. This delegate is used
* in the created cipher.
*
* @author Cedric Hammes
* @since 14/06/2024
*/
fun readKeyFromFile(closure: (C, Path) -> Key) = this.apply {
if (readKeyFromFile != null)
throw IllegalStateException("Unable to set readKeyFromFile delegate twice")
readKeyFromFile = closure
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package io.karma.advcrypto.wrapper

import io.karma.advcrypto.Providers
import io.karma.advcrypto.algorithm.delegates.KeyStoreFactory
import io.karma.advcrypto.keys.Key
import okio.Path

/**
* This interface represents the implementation of a keystore. A keystore is used to store the keys
Expand All @@ -29,6 +31,18 @@ import io.karma.advcrypto.algorithm.delegates.KeyStoreFactory
*/
interface KeyStore {

/**
* This method opens the file with `okio` and reads the content as a bytearray. This content is
* used to extract information from the key and return this key to the user.
*
* @param path The path of the file
* @return The key derived from the file
*
* @author Cedric Hammes
* @since 14/06/2024
*/
fun readKeyFromFile(path: Path): Key

companion object {
/**
* This method returns an instance of a keystore created by the internal architecture of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class DefaultKeyStoreProvider: AbstractProvider(
initialize {
"Placeholder"
}
readKeyFromFile { context, path ->
TODO("Read and derive key")
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2024 Cach30verfl0w
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.karma.advcrypto.linux.utils

import io.karma.advcrypto.keys.formats.KeyFormat
import kotlinx.cinterop.ByteVar
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.ExperimentalForeignApi
import libssl.BIO
import libssl.BIO_new
import libssl.BIO_s_secmem
import libssl.BIO_write
import libssl.PEM_read_bio_PrivateKey

// TODO: Detect key format, key size and algorithm (etc)

@OptIn(ExperimentalForeignApi::class)
object KeyDetectionUtil {

private fun createSecureMemoryBuffer(pointer: CPointer<ByteVar>, size: Int): CPointer<BIO> =
BIO_new(BIO_s_secmem()).apply {
BIO_write(this, pointer, size)
}?: throw RuntimeException("Error while writing key into secure memory BIO")

private fun tryParseAsPEM(pointer: CPointer<ByteVar>, size: Int): Unit? {
val privateKeyBuffer = createSecureMemoryBuffer(pointer, size)
val privateKey = PEM_read_bio_PrivateKey(privateKeyBuffer, null, null, null)
if (privateKey == null) {
val publicKeyBuffer = createSecureMemoryBuffer(pointer, size)
// TODO: Parse as public key and handle
}


return null
}

/*private fun tryParseAsPEM(pointer: CPointer<ByteVar>, size: Int): KeyInfo {
val privateKeyBuffer = createSecureMemoryBuffer(pointer, size)
val parsedPrivateKey = PEM_read_bio_PrivateKey(privateKeyBuffer, null, null, null)
val algorithm = when (EVP_PKEY_get_base_id(parsedPrivateKey)) {
EVP_PKEY_RSA -> "RSA"
EVP_PKEY_ED25519 -> "ED25519"
EVP_PKEY_EC -> {
}
else -> "Unknown"
}
BIO_free(privateKeyBuffer)
TODO("Return key info")
}*/

fun detectKeyFormat(pointer: CPointer<ByteVar>, size: Int): KeyFormat? {
/*val tempKeyBuffer = BIO_new_mem_buf(pointer, size)
// val publicKey = PEM_read_bio_RSAPublicKey(tempKeyBuffer, null, null, null)
val privateKey = PEM_read_bio_PrivateKey(tempKeyBuffer, null, null, null)
if (privateKey != null) {
println(OBJ_nid2sn(EVP_PKEY_get_base_id(privateKey))!!.toKString())
EVP_PKEY_free(privateKey)
return KeyFormat.PEM
}*/
return null
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class KeyStoreTests {
@Test
fun testFileLoading() {
val providers = Providers()
val keyStore = KeyStore.getInstance(providers, "Default")
KeyStore.getInstance(providers, "Default")
providers.close()
}

Expand Down

0 comments on commit 3f9cb08

Please sign in to comment.