Skip to content

Commit

Permalink
feat: AES encryption & decryption
Browse files Browse the repository at this point in the history
Supported Key Size:

- 128
- 192
- 256

Supported Block Mode:

- ECB
- CBC
- CFB
- CFB8
- CTR
- GCM
- OFB
- RC4

Supported Padding:

- No Padding
- PKCS5
- PKCS7
  • Loading branch information
hamada147 committed Dec 14, 2022
1 parent 99cec6e commit e4af9ec
Show file tree
Hide file tree
Showing 55 changed files with 2,877 additions and 0 deletions.
Empty file added aes/README.md
Empty file.
42 changes: 42 additions & 0 deletions aes/aes.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Pod::Spec.new do |spec|
spec.name = 'aes'
spec.version = '1.0.0-alpha'
spec.homepage = ''
spec.source = { :http=> ''}
spec.authors = 'IOG'
spec.license = ''
spec.summary = 'ApolloAES is an AES lib'
spec.vendored_frameworks = 'build/cocoapods/framework/ApolloAES.framework'
spec.libraries = 'c++'
spec.ios.deployment_target = '13.0'
spec.osx.deployment_target = '12.0'
spec.tvos.deployment_target = '13.0'
spec.watchos.deployment_target = '8.0'
spec.dependency 'IOHKAES', '1.0.0'

spec.pod_target_xcconfig = {
'KOTLIN_PROJECT_PATH' => ':aes',
'PRODUCT_MODULE_NAME' => 'ApolloAES',
}

spec.script_phases = [
{
:name => 'Build aes',
:execution_position => :before_compile,
:shell_path => '/bin/sh',
:script => <<-SCRIPT
if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then
echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\""
exit 0
fi
set -ev
REPO_ROOT="$PODS_TARGET_SRCROOT"
"$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \
-Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \
-Pkotlin.native.cocoapods.archs="$ARCHS" \
-Pkotlin.native.cocoapods.configuration="$CONFIGURATION"
SCRIPT
}
]

end
224 changes: 224 additions & 0 deletions aes/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import org.gradle.internal.os.OperatingSystem
import org.jetbrains.dokka.gradle.DokkaTask
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackOutput.Target

version = rootProject.version
val currentModuleName = "ApolloAES"
val os: OperatingSystem = OperatingSystem.current()

plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
id("org.jetbrains.dokka")
}

kotlin {
android {
publishAllLibraryVariants()
}
jvm {
compilations.all {
kotlinOptions {
jvmTarget = "11"
}
}
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
if (os.isMacOsX) {
ios()
// tvos()
// watchos()
// macosX64()
if (System.getProperty("os.arch") != "x86_64") { // M1Chip
iosSimulatorArm64()
// tvosSimulatorArm64()
// watchosSimulatorArm64()
// macosArm64()
}
}
// if (os.isWindows) {
// // mingwX86() // it depend on kotlinx-datetime lib to support this platform before we can support it as well
// mingwX64()
// }
js(IR) {
this.moduleName = currentModuleName
this.binaries.library()
this.useCommonJs()
this.compilations["main"].packageJson {
this.version = rootProject.version.toString()
}
this.compilations["test"].packageJson {
this.version = rootProject.version.toString()
}
browser {
this.webpackTask {
this.output.library = currentModuleName
this.output.libraryTarget = Target.VAR
}
this.commonWebpackConfig {
this.cssSupport {
this.enabled = true
}
}
this.testTask {
this.useKarma {
this.useChromeHeadless()
}
}
}
nodejs {
this.testTask {
this.useKarma {
this.useChromeHeadless()
}
}
}
}

if (os.isMacOsX) {
cocoapods {
this.summary = "ApolloAES is an AES lib"
this.version = rootProject.version.toString()
this.authors = "IOG"
this.ios.deploymentTarget = "13.0"
this.osx.deploymentTarget = "12.0"
this.tvos.deploymentTarget = "13.0"
this.watchos.deploymentTarget = "8.0"
framework {
this.baseName = currentModuleName
}

pod("IOHKAES") {
version = "1.0.0"
source = path(project.file("../iOSLibs/IOHKAES"))
}
}
}

sourceSets {
val commonMain by getting {
dependencies {
api(project(":base-symmetric-encryption"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
}
}
val jvmMain by getting
val jvmTest by getting
val androidMain by getting
val androidTest by getting {
dependencies {
implementation("junit:junit:4.13.2")
}
}
val jsMain by getting {
dependencies {
// Polyfill dependencies
implementation(npm("crypto-browserify", "3.12.0"))
implementation(npm("stream-browserify", "3.0.0"))
}
}
val jsTest by getting
if (os.isMacOsX) {
val iosMain by getting
val iosTest by getting
// val tvosMain by getting
// val tvosTest by getting
// val watchosMain by getting
// val watchosTest by getting
// val macosX64Main by getting
// val macosX64Test by getting
if (System.getProperty("os.arch") != "x86_64") { // M1Chip
val iosSimulatorArm64Main by getting {
this.dependsOn(iosMain)
}
val iosSimulatorArm64Test by getting {
this.dependsOn(iosTest)
}
// val tvosSimulatorArm64Main by getting {
// this.dependsOn(tvosMain)
// }
// val tvosSimulatorArm64Test by getting {
// this.dependsOn(tvosTest)
// }
// val watchosSimulatorArm64Main by getting {
// this.dependsOn(watchosMain)
// }
// val watchosSimulatorArm64Test by getting {
// this.dependsOn(watchosTest)
// }
// val macosArm64Main by getting {
// this.dependsOn(macosX64Main)
// }
// val macosArm64Test by getting {
// this.dependsOn(macosX64Test)
// }
}
}
// if (os.isWindows) {
// // val mingwX86Main by getting // it depend on kotlinx-datetime lib to support this platform before we can support it as well
// // val mingwX86Test by getting // it depend on kotlinx-datetime lib to support this platform before we can support it as well
// val mingwX64Main by getting
// val mingwX64Test by getting
// }
}
}

android {
compileSdk = 32
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
targetSdk = 32
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
/**
* Because Software Components will not be created automatically for Maven publishing from
* Android Gradle Plugin 8.0. To opt-in to the future behavior, set the Gradle property android.
* disableAutomaticComponentCreation=true in the `gradle.properties` file or use the new
* publishing DSL.
*/
publishing {
multipleVariants {
withSourcesJar()
withJavadocJar()
allVariants()
}
}
}

// Dokka implementation
tasks.withType<DokkaTask> {
moduleName.set(project.name)
moduleVersion.set(rootProject.version.toString())
description = """
This is a Kotlin Multiplatform Library for AES
""".trimIndent()
dokkaSourceSets {
// TODO: Figure out how to include files to the documentations
named("commonMain") {
includes.from("Module.md", "docs/Module.md")
}
}
}

// afterEvaluate {
// tasks.withType<AbstractTestTask> {
// testLogging {
// events("passed", "skipped", "failed", "standard_out", "standard_error")
// showExceptions = true
// showStackTraces = true
// }
// }
// }
9 changes: 9 additions & 0 deletions aes/karma.config.d/karma.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
config.set({
browserDisconnectTimeout: 300000,
processKillTimeout: 300000,
client: {
mocha: {
timeout: 300000
}
}
});
2 changes: 2 additions & 0 deletions aes/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="io.iohk.atala.prism.apollo.aes" />
65 changes: 65 additions & 0 deletions aes/src/androidMain/kotlin/io/iohk/atala/prism/apollo/aes/AES.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package io.iohk.atala.prism.apollo.aes

import io.iohk.atala.prism.apollo.utils.KMMSymmetricKey
import java.security.spec.AlgorithmParameterSpec
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.IvParameterSpec

actual typealias KAESAlgorithmNativeType = String
actual typealias KAESBlockModeNativeType = String
actual typealias KAESPaddingNativeType = String

actual final class AES actual constructor(
actual val algorithm: KAESAlgorithm,
actual val blockMode: KAESBlockMode,
actual val padding: KAESPadding,
actual val key: KMMSymmetricKey,
actual val iv: ByteArray?
) : AESEncryptor, AESDecryptor {

private val cipher: Cipher = Cipher.getInstance("${algorithm.nativeValue()}/${blockMode.nativeValue()}/${padding.nativeValue()}")
private val ivSpec: AlgorithmParameterSpec? = if (blockMode.needIV()) {
when (blockMode) {
KAESBlockMode.ECB -> IvParameterSpec(iv)
KAESBlockMode.CBC -> IvParameterSpec(iv)
KAESBlockMode.CFB -> IvParameterSpec(iv)
KAESBlockMode.CFB8 -> IvParameterSpec(iv)
KAESBlockMode.CTR -> IvParameterSpec(iv)
KAESBlockMode.GCM -> GCMParameterSpec(AUTH_TAG_SIZE, iv)
KAESBlockMode.OFB -> IvParameterSpec(iv)
KAESBlockMode.RC4 -> IvParameterSpec(iv)
}
} else {
null
}

override suspend fun encrypt(data: ByteArray): ByteArray {
if (ivSpec == null) {
cipher.init(Cipher.ENCRYPT_MODE, key.nativeType)
} else {
cipher.init(Cipher.ENCRYPT_MODE, key.nativeType, ivSpec)
}
return cipher.doFinal(data)
}

override suspend fun decrypt(data: ByteArray): ByteArray {
if (ivSpec == null) {
cipher.init(Cipher.DECRYPT_MODE, key.nativeType)
} else {
cipher.init(Cipher.DECRYPT_MODE, key.nativeType, ivSpec)
}
return cipher.doFinal(data)
}

actual companion object : AESKeyGeneration {
private const val AUTH_TAG_SIZE = 128

override suspend fun createRandomAESKey(algorithm: KAESAlgorithm): KMMSymmetricKey {
val keygen = KeyGenerator.getInstance("AES")
keygen.init(algorithm.keySize())
return KMMSymmetricKey(keygen.generateKey())
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.iohk.atala.prism.apollo.aes

import io.iohk.atala.prism.apollo.utils.NativeTypeInterface

actual enum class KAESAlgorithm : NativeTypeInterface<KAESAlgorithmNativeType> {
AES_128,
AES_192,
AES_256;

override fun nativeValue() = "AES"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.iohk.atala.prism.apollo.aes

import io.iohk.atala.prism.apollo.utils.NativeTypeInterface

actual enum class KAESBlockMode : NativeTypeInterface<KAESBlockModeNativeType> {
ECB,
CBC,
CFB,
CFB8,
CTR,
GCM,
OFB,
RC4;

override fun nativeValue(): KAESBlockModeNativeType {
return when (this) {
ECB -> "ECB"
CBC -> "CBC"
CFB -> "CFB"
CFB8 -> "CFB8"
CTR -> "CTR"
GCM -> "GCM"
OFB -> "OFB"
RC4 -> throw Exception("Not implemented in JVM")
}
}
}
Loading

0 comments on commit e4af9ec

Please sign in to comment.