First steps

This commit is contained in:
Ugljesa Jovanovic 2020-05-24 10:16:53 +02:00 committed by Ugljesa Jovanovic
parent aecad37e64
commit 9858eaa5fb
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
52 changed files with 5088 additions and 526 deletions

View File

@ -0,0 +1,418 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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.
*
*/
@file:Suppress("UnstableApiUsage")
import org.gradle.api.tasks.testing.logging.TestLogging
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
plugins {
kotlin(PluginsDeps.multiplatform)
id (PluginsDeps.mavenPublish)
id (PluginsDeps.signing)
id (PluginsDeps.dokka) version Versions.dokkaPlugin
}
repositories {
mavenCentral()
jcenter()
}
group = "com.ionspin.kotlin"
version = "0.0.4-SNAPSHOT"
val ideaActive = System.getProperty("idea.active") == "true"
fun getHostOsName(): String {
val target = System.getProperty("os.name")
if (target == "Linux") return "linux"
if (target.startsWith("Windows")) return "windows"
if (target.startsWith("Mac")) return "macos"
return "unknown"
}
kotlin {
val hostOsName = getHostOsName()
if (ideaActive) {
when(hostOsName) {
"linux" -> linuxX64("native")
"macos" -> macosX64("native")
"windows" -> mingwX64("native")
}
}
if (hostOsName == "linux") {
jvm()
js {
compilations {
this.forEach {
it.compileKotlinTask.kotlinOptions.sourceMap = true
it.compileKotlinTask.kotlinOptions.moduleKind = "commonjs"
it.compileKotlinTask.kotlinOptions.metaInfo = true
if (it.name == "main") {
it.compileKotlinTask.kotlinOptions.main = "call"
}
println("Compilation name ${it.name} set")
println("Destination dir ${it.compileKotlinTask.destinationDir}")
}
}
//Until I figure out how to run headless chrome on travis
// browser {
//
// testTask {
// useKarma {
// useChrome()
// }
// }
// }
nodejs {
testTask {
useMocha() {
timeout = "10s"
}
}
}
}
linuxX64("linux") {
binaries {
staticLib {
optimized = true
}
}
}
//Not supported in coroutines at the moment
// linuxArm32Hfp() {
// binaries {
// staticLib {
// }
// }
// }
//Not supported in coroutines at the moment
// linuxArm64() {
// binaries {
// staticLib {
// }
// }
// }
}
if (hostOsName == "macos") {
iosX64("ios") {
binaries {
framework {
optimized = true
}
}
}
iosArm64("ios64Arm") {
binaries {
framework {
optimized = true
}
}
}
iosArm32("ios32Arm") {
binaries {
framework {
optimized = true
}
}
}
macosX64() {
binaries {
framework {
optimized = true
}
}
}
}
if (hostOsName == "windows") {
mingwX64() {
binaries {
staticLib {
optimized = true
}
}
}
}
// No coroutines support for mingwX86
// mingwX86() {
// binaries {
// staticLib {
//
// }
// }
// }
println(targets.names)
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin(Deps.Common.stdLib))
implementation(kotlin(Deps.Common.test))
implementation(Deps.Common.coroutines)
implementation(Deps.Common.kotlinBigNum)
}
}
val commonTest by getting {
dependencies {
implementation(kotlin(Deps.Common.test))
implementation(kotlin(Deps.Common.testAnnotation))
}
}
val nativeMain = if (ideaActive) {
val nativeMain by getting {
dependsOn(commonMain)
dependencies {
implementation(Deps.Native.coroutines)
}
}
nativeMain
} else {
val nativeMain by creating {
dependsOn(commonMain)
dependencies {
implementation(Deps.Native.coroutines)
}
}
nativeMain
}
val nativeTest = if (ideaActive) {
val nativeTest by getting {
dependsOn(commonTest)
dependencies {
implementation(Deps.Native.coroutines)
}
}
nativeTest
} else {
val nativeTest by creating {
dependsOn(commonTest)
dependencies {
implementation(Deps.Native.coroutines)
}
}
nativeTest
}
if (hostOsName == "linux") {
val jvmMain by getting {
dependencies {
implementation(kotlin(Deps.Jvm.stdLib))
implementation(kotlin(Deps.Jvm.test))
implementation(kotlin(Deps.Jvm.testJUnit))
implementation(Deps.Jvm.coroutinesCore)
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin(Deps.Jvm.test))
implementation(kotlin(Deps.Jvm.testJUnit))
implementation(Deps.Jvm.coroutinesTest)
implementation(kotlin(Deps.Jvm.reflection))
}
}
val jsMain by getting {
dependencies {
implementation(kotlin(Deps.Js.stdLib))
implementation(Deps.Js.coroutines)
}
}
val jsTest by getting {
dependencies {
implementation(Deps.Js.coroutines)
implementation(kotlin(Deps.Js.test))
}
}
val linuxMain by getting {
dependsOn(nativeMain)
}
val linuxTest by getting {
dependsOn(nativeTest)
}
//Not supported in coroutines at the moment
// val linuxArm32HfpMain by getting {
// dependsOn(nativeMain)
// }
//
// val linuxArm32HfpTest by getting {
// dependsOn(nativeTest)
// }
// val linuxArm64Main by getting {
// dependsOn(nativeMain)
// }
//
// val linuxArm64Test by getting {
// dependsOn(nativeTest)
// }
}
if (hostOsName == "macos") {
val iosMain by getting {
dependsOn(nativeMain)
}
val iosTest by getting {
dependsOn(nativeTest)
}
val ios64ArmMain by getting {
dependsOn(nativeMain)
}
val ios64ArmTest by getting {
dependsOn(nativeTest)
}
val ios32ArmMain by getting {
dependsOn(nativeMain)
}
val ios32ArmTest by getting {
dependsOn(nativeTest)
}
val macosX64Main by getting {
dependsOn(nativeMain)
}
val macosX64Test by getting {
dependsOn(nativeTest)
}
}
// Coroutines don't support mingwx86 yet
// val mingwX86Main by getting {
// dependsOn(commonMain)
// dependencies {
// implementation(Deps.Native.coroutines)
// }
// }
// val mingwX86Test by getting {
// dependsOn(commonTest)
// }
//
if (hostOsName == "windows") {
val mingwX64Main by getting {
dependsOn(commonMain)
dependencies {
implementation(Deps.Native.coroutines)
}
}
val mingwX64Test by getting {
dependsOn(commonTest)
}
}
all {
languageSettings.enableLanguageFeature("InlineClasses")
}
}
}
tasks {
create<Jar>("javadocJar") {
dependsOn(dokka)
archiveClassifier.set("javadoc")
from(dokka.get().outputDirectory)
}
dokka {
println ("Dokka !")
impliedPlatforms = mutableListOf("Common")
kotlinTasks {
listOf()
}
sourceRoot {
println ("Common !")
path = "/home/ionspin/Projects/Future/kotlin-multiplatform-crypto/crypto/src/commonMain" //TODO remove static path!
platforms = listOf("Common")
}
}
if (getHostOsName() == "linux") {
val compileKotlinJs by getting(AbstractCompile::class)
val compileTestKotlinJs by getting(Kotlin2JsCompile::class)
val jvmTest by getting(Test::class) {
testLogging {
events("PASSED", "FAILED", "SKIPPED")
}
}
val linuxTest by getting(KotlinNativeTest::class) {
testLogging {
events("PASSED", "FAILED", "SKIPPED")
// showStandardStreams = true
}
}
val jsNodeTest by getting(KotlinJsTest::class) {
testLogging {
events("PASSED", "FAILED", "SKIPPED")
showStandardStreams = true
}
}
// val legacyjsNodeTest by getting(KotlinJsTest::class) {
//
// testLogging {
// events("PASSED", "FAILED", "SKIPPED")
// showStandardStreams = true
// }
// }
// val jsIrBrowserTest by getting(KotlinJsTest::class) {
// testLogging {
// events("PASSED", "FAILED", "SKIPPED")
// showStandardStreams = true
// }
// }
}
if (getHostOsName() == "windows") {
val mingwX64Test by getting(KotlinNativeTest::class) {
testLogging {
events("PASSED", "FAILED", "SKIPPED")
showStandardStreams = true
}
}
}
}

201
multiplatform-crypto-api/package-lock.json generated Normal file
View File

@ -0,0 +1,201 @@
{
"name": "kotlin-multiplatform-crypto-js",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"browser-stdout": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
"dev": true
},
"commander": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"diff": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
"dev": true
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"growl": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
"dev": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"he": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
"dev": true
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"kotlin": {
"version": "1.3.40",
"resolved": "https://registry.npmjs.org/kotlin/-/kotlin-1.3.40.tgz",
"integrity": "sha512-3l718c3QznxsFNUrnsyGworQZrczyzKRhf+Rx/+7XhSS95S/QrCnlUVuEXA1l9iJpfxx4t9Ecc7+jC1JD28aYg=="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": {
"minimist": "0.0.8"
}
},
"mocha": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
"integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
"dev": true,
"requires": {
"browser-stdout": "1.3.1",
"commander": "2.15.1",
"debug": "3.1.0",
"diff": "3.5.0",
"escape-string-regexp": "1.0.5",
"glob": "7.1.2",
"growl": "1.10.5",
"he": "1.1.1",
"minimatch": "3.0.4",
"mkdirp": "0.5.1",
"supports-color": "5.4.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"supports-color": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
}
}
}

View File

@ -0,0 +1,15 @@
{
"name": "kotlin-multiplatform-crypto-js",
"version": "0.0.1",
"description": "Kotlin Multiplatform Crypto",
"main": "crypto.js",
"author": "Ugljesa Jovanovic",
"license": "Apache 2.0",
"homepage": "",
"dependencies": {
"kotlin": "1.3.40"
},
"devDependencies": {
"mocha": "5.2.0"
}
}

View File

@ -0,0 +1,13 @@
package com.ionspin.kotlin.crypto.hash.blake2b
import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdatableHash
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 24-May-2020
*/
interface Blake2b : UpdatableHash
interface Blake2bStatelessInterface : StatelessHash

View File

@ -0,0 +1,12 @@
package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdatableHash
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 24-May-2020
*/
interface Sha256 : UpdatableHash
interface StatelessSha256 : StatelessHash

View File

@ -0,0 +1,12 @@
package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdatableHash
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 24-May-2020
*/
interface Sha512 : UpdatableHash
interface StatelessSha512 : StatelessHash

View File

@ -0,0 +1,159 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
import com.ionspin.kotlin.crypto.hash.sha.Sha256
import com.ionspin.kotlin.crypto.hash.sha.Sha512
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
import com.ionspin.kotlin.crypto.util.testBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 20-Jul-2019
*/
@ExperimentalUnsignedTypes
@ExperimentalStdlibApi
class ReadmeTest {
@Test
fun blake2bObjectExample() {
val input = "abc"
val result = Blake2b.digest(input)
//@formatter:off
val expectedResult = ubyteArrayOf(
0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U,
0x4CU,0x21U,0x2FU,0x14U,0x68U,0x5AU,0xC4U,0xB7U,0x4BU,0x12U,0xBBU,0x6FU,0xDBU,0xFFU,0xA2U,0xD1U,
0x7DU,0x87U,0xC5U,0x39U,0x2AU,0xABU,0x79U,0x2DU,0xC2U,0x52U,0xD5U,0xDEU,0x45U,0x33U,0xCCU,0x95U,
0x18U,0xD3U,0x8AU,0xA8U,0xDBU,0xF1U,0x92U,0x5AU,0xB9U,0x23U,0x86U,0xEDU,0xD4U,0x00U,0x99U,0x23U
)
//@formatter:on
assertTrue {
result.contentEquals(expectedResult)
}
}
@Test
fun blake2bInstanceExample() {
val test = "abc"
val key = "key"
val blake2b = Blake2b(key)
blake2b.update(test)
val result = blake2b.digest()
assertTrue {
result.isNotEmpty()
}
val expectedResult = ("5c6a9a4ae911c02fb7e71a991eb9aea371ae993d4842d206e" +
"6020d46f5e41358c6d5c277c110ef86c959ed63e6ecaaaceaaff38019a43264ae06acf73b9550b1")
.chunked(2).map { it.toUByte(16) }.toUByteArray()
assertTrue {
result.contentEquals(expectedResult)
}
}
@ExperimentalStdlibApi
@Test
fun sha256Example() {
val input = "abc"
val result = Sha256.digest(inputString = input)
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun sha512Example() {
val input = "abc"
val result = Sha512.digest(inputMessage = input.encodeToByteArray().map { it.toUByte() }.toUByteArray())
println(result.map { it.toString(16) })
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun sha256UpdatableExample() {
val sha256 = Sha256()
sha256.update("abc")
val result = sha256.digest()
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun sha512UpdatableExample() {
val sha512 = Sha512()
sha512.update("abc")
val result = sha512.digest()
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalTime
@Test
fun argon2StringExample() = testBlocking {
val argon2Instance = Argon2(
password = "Password",
salt = "RandomSalt",
parallelism = 1,
tagLength = 64U,
requestedMemorySize = 4096U,
numberOfIterations = 2,
key = "",
associatedData = "",
argonType = ArgonType.Argon2id
)
val time = measureTime {
val tag = argon2Instance.derive()
val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
val expectedTagString = "c19db7e22d1480702b943872c863baf8c43b53d0c3e2c782cd07bfc613eda159233bd821a945c239c5085c70257f7c93d8a809f81c4af367f4ad8f0443a8fc47"
println("Tag: ${tagString}")
assertEquals(tagString, expectedTagString)
}
println("Time $time")
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 21-Sep-2019
*/
class SRNGTest {
@Test
fun testSrng() {
//Just a sanity test, need to add better srng tests.
val randomBytes1 = SRNG.getRandomBytes(10)
val randomBytes2 = SRNG.getRandomBytes(10)
randomBytes1.forEach { println("RB1: $it")}
randomBytes2.forEach { println("RB2: $it")}
assertTrue { !randomBytes1.contentEquals(randomBytes2) }
}
}

View File

@ -0,0 +1,158 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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.
*/
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE")
package com.ionspin.kotlin.crypto.hash.argon
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
import com.ionspin.kotlin.crypto.util.hexColumsPrint
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Known Answer.. TestTest
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 10-May-2020
*/
@ExperimentalStdlibApi
class Argon2KATTest {
@Test
fun argon2dKATTest() {
val expected : UByteArray = ubyteArrayOf(
0x51U, 0x2BU, 0x39U, 0x1BU, 0x6FU, 0x11U, 0x62U, 0x97U,
0x53U, 0x71U, 0xD3U, 0x09U, 0x19U, 0x73U, 0x42U, 0x94U,
0xF8U, 0x68U, 0xE3U, 0xBEU, 0x39U, 0x84U, 0xF3U, 0xC1U,
0xA1U, 0x3AU, 0x4DU, 0xB9U, 0xFAU, 0xBEU, 0x4AU, 0xCBU
)
val memory = 32U //KiB
val iterations = 3
val parallelism = 4U
val tagLength = 32U
val password: UByteArray = ubyteArrayOf(
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U
)
val salt: UByteArray = ubyteArrayOf(0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U)
val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U)
val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U)
val digest = Argon2(
password,
salt,
parallelism.toInt(),
tagLength,
memory,
iterations,
secret,
associatedData,
ArgonType.Argon2d
)
val result = digest.derive()
result.hexColumsPrint(8)
assertTrue { expected.contentEquals(result) }
}
@Test
fun argon2iKATTest() {
val expected : UByteArray = ubyteArrayOf(
0xc8U, 0x14U, 0xd9U, 0xd1U, 0xdcU, 0x7fU, 0x37U, 0xaaU,
0x13U, 0xf0U, 0xd7U, 0x7fU, 0x24U, 0x94U, 0xbdU, 0xa1U,
0xc8U, 0xdeU, 0x6bU, 0x01U, 0x6dU, 0xd3U, 0x88U, 0xd2U,
0x99U, 0x52U, 0xa4U, 0xc4U, 0x67U, 0x2bU, 0x6cU, 0xe8U
)
val memory = 32U //KiB
val iterations = 3
val parallelism = 4U
val tagLength = 32U
val password: UByteArray = ubyteArrayOf(
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U
)
val salt: UByteArray = ubyteArrayOf(0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U)
val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U)
val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U)
val digest = Argon2(
password,
salt,
parallelism.toInt(),
tagLength,
memory,
iterations,
secret,
associatedData,
ArgonType.Argon2i
)
val result = digest.derive()
result.hexColumsPrint(8)
assertTrue { expected.contentEquals(result) }
}
@Test
fun argon2idKATTest() {
val expected : UByteArray = ubyteArrayOf(
0x0dU, 0x64U, 0x0dU, 0xf5U, 0x8dU, 0x78U, 0x76U, 0x6cU,
0x08U, 0xc0U, 0x37U, 0xa3U, 0x4aU, 0x8bU, 0x53U, 0xc9U,
0xd0U, 0x1eU, 0xf0U, 0x45U, 0x2dU, 0x75U, 0xb6U, 0x5eU,
0xb5U, 0x25U, 0x20U, 0xe9U, 0x6bU, 0x01U, 0xe6U, 0x59U
)
val memory = 32U //KiB
val iterations = 3
val parallelism = 4U
val tagLength = 32U
val password: UByteArray = ubyteArrayOf(
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U,
0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U
)
val salt: UByteArray = ubyteArrayOf(0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U, 0x02U)
val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U)
val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U)
val digest = Argon2(
password,
salt,
parallelism.toInt(),
tagLength,
memory,
iterations,
secret,
associatedData,
ArgonType.Argon2id
)
val result = digest.derive()
result.hexColumsPrint(8)
assertTrue { expected.contentEquals(result) }
}
}

View File

@ -0,0 +1,142 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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.
*/
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package com.ionspin.kotlin.crypto.hash.argon
import com.ionspin.kotlin.crypto.keyderivation.argon2.*
import com.ionspin.kotlin.crypto.util.arrayChunked
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToULong
import kotlin.random.Random
import kotlin.random.nextUBytes
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 21-May-2020
*/
class Argon2MatrixTest {
val zeroesBlock = UByteArray(1024) { 0U }
val onesBlock = UByteArray(1024) { 1U }
val twosBlock = UByteArray(1024) { 2U }
val threesBlock = UByteArray(1024) { 3U }
val random = Random(1)
val randomBlockArray = random.nextUBytes(1024)
@Test
fun indexAccessTest() {
val argon2Matrix = ArgonMatrix(2, 2)
(zeroesBlock + onesBlock + twosBlock + threesBlock).copyInto(argon2Matrix.storage)
println(argon2Matrix[0, 0, 0])
println(argon2Matrix[0, 1, 0])
println(argon2Matrix[1, 0, 0])
println(argon2Matrix[1, 1, 0])
// argon2Matrix.storage.hexColumsPrint(1024)
var expectedByteValue = 0U.toUByte()
for (lane in 0 until 2) {
for (column in 0 until 2) {
for (blockPosition in 0 until 1024) {
assertTrue {
argon2Matrix[lane, column, blockPosition] == expectedByteValue
}
}
expectedByteValue++
}
}
assertTrue {
argon2Matrix[0, 0, 0] == 0U.toUByte() &&
argon2Matrix[0, 1, 0] == 1U.toUByte() &&
argon2Matrix[1, 0, 0] == 2U.toUByte() &&
argon2Matrix[1, 1, 0] == 3U.toUByte()
}
}
@Test
fun blockRetrievalTest() {
val argon2Matrix = ArgonMatrix(2, 2)
(zeroesBlock + onesBlock + twosBlock + threesBlock).copyInto(argon2Matrix.storage)
assertTrue {
zeroesBlock.contentEquals(argon2Matrix.getBlockAt(0, 0)) &&
onesBlock.contentEquals(argon2Matrix.getBlockAt(0, 1)) &&
twosBlock.contentEquals(argon2Matrix.getBlockAt(1, 0)) &&
threesBlock.contentEquals(argon2Matrix.getBlockAt(1, 1))
}
}
@Test
fun blockColumnToUlongTest() {
val randomBlock = ArgonBlock(randomBlockArray)
for (columnIndex in 0 until 8) {
val startOfRow = (columnIndex * 8 * 16)
val endOfRow = startOfRow + (8 * 16)
val rowToMix = randomBlockArray.copyOfRange(startOfRow, endOfRow)
val expected = rowToMix.arrayChunked(8).map { it.fromLittleEndianArrayToULong() }.toULongArray()
val result = randomBlock.getBlockPointer().getRowOfULongsForMixing(columnIndex)
assertTrue { expected.contentEquals(result) }
}
}
@Test
fun blockRowToULongTest() {
val randomBlock = ArgonBlock(randomBlockArray)
for (rowIndex in 0 until 8) {
val columnToMix = Argon2Utils.extractColumnFromGBlock(randomBlockArray, rowIndex)
val expected = columnToMix.arrayChunked(8).map { it.fromLittleEndianArrayToULong() }.toULongArray()
val result = randomBlock.getBlockPointer().getColumnOfULongsForMixing(rowIndex)
assertTrue { expected.contentEquals(result) }
}
}
@Test
fun blockSetMixedRowTest() {
val randomBlock = ArgonBlock(randomBlockArray)
val targetBlockArray = zeroesBlock.copyOf()
val targetBlock = ArgonBlock(targetBlockArray)
for (rowIndex in 0 until 8) {
val extracted = randomBlock.getBlockPointer().getRowOfULongsForMixing(rowIndex)
targetBlock.getBlockPointer().setRowFromMixedULongs(rowIndex, extracted)
}
assertTrue {
randomBlockArray.contentEquals(targetBlock.storage)
}
}
@Test
fun blockSetMixedColumnTest() {
val randomBlock = ArgonBlock(randomBlockArray)
val targetBlockArray = zeroesBlock.copyOf()
val targetBlock = ArgonBlock(targetBlockArray)
for (columnIndex in 0 until 8) {
val extracted = randomBlock.getBlockPointer().getColumnOfULongsForMixing(columnIndex)
targetBlock.getBlockPointer().setColumnFromMixedULongs(columnIndex, extracted)
}
assertTrue {
randomBlockArray.contentEquals(targetBlock.storage)
}
}
}

View File

@ -0,0 +1,403 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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.
*/
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package com.ionspin.kotlin.crypto.hash.argon
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonBlock
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToULong
import kotlin.random.Random
import kotlin.random.nextUBytes
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 21-May-2020
*/
class Argon2Test {
val seededRandom = Random(1L)
val randomBlockAsArray = seededRandom.nextUBytes(1024)
val randomBlockAsArray2 = seededRandom.nextUBytes(1024)
val randomBlockAsArray3 = seededRandom.nextUBytes(1024)
@Test
fun mixRoundTest() {
val input = ubyteArrayOf(
0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
0x08U, 0x09U, 0x0aU, 0x0bU, 0x0cU, 0x0dU, 0x0eU, 0x0fU,
0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
0x18U, 0x19U, 0x1aU, 0x1bU, 0x1cU, 0x1dU, 0x1eU, 0x1fU,
0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
0x28U, 0x29U, 0x2aU, 0x2bU, 0x2cU, 0x2dU, 0x2eU, 0x2fU,
0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
0x38U, 0x39U, 0x3aU, 0x3bU, 0x3cU, 0x3dU, 0x3eU, 0x3fU,
0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU,
0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
0x58U, 0x59U, 0x5aU, 0x5bU, 0x5cU, 0x5dU, 0x5eU, 0x5fU,
0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU,
0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
0x78U, 0x79U, 0x7aU, 0x7bU, 0x7cU, 0x7dU, 0x7eU, 0x7fU
)
val expected = arrayOf(
16438755999881694465U,
2631578750119870528U,
8840261388583117524U,
13886387434724287670U,
14214935523062117944U,
6768869593113706780U,
12323449447979969623U,
7512951229622659062U,
9291745133539598579U,
11220895723773995914U,
2509429320847842905U,
5637172405908834370U,
8517838221434905893U,
14206719563334097702U,
6500029010075826286U,
16957672821843227543U
)
val preparedInput = input.chunked(8).map { it.toTypedArray().fromLittleEndianArrayToULong() }.toULongArray()
val result = Argon2Utils.inplaceMixRound(preparedInput)
assertTrue {
expected.contentEquals(result.toTypedArray())
}
}
@Test
fun testExtractColumnFromGBlock() {
val expected = ubyteArrayOf(
0x1AU, 0x2AU, 0xC5U, 0x23U, 0xB0U, 0x05U, 0xB1U, 0xA4U,
0x61U, 0x48U, 0x93U, 0xE0U, 0x6DU, 0x33U, 0xB6U, 0xA0U,
0x63U, 0x13U, 0xFFU, 0xEBU, 0x56U, 0x48U, 0xE7U, 0xD0U,
0x47U, 0x58U, 0x8EU, 0xD7U, 0xDEU, 0x01U, 0xCFU, 0x96U,
0xB4U, 0xE0U, 0x2AU, 0xF0U, 0x16U, 0x33U, 0x54U, 0xA9U,
0xF3U, 0xC3U, 0x98U, 0x2CU, 0xB7U, 0xECU, 0x1AU, 0x66U,
0xE0U, 0x6CU, 0xA5U, 0x66U, 0x73U, 0xE8U, 0x8AU, 0xF7U,
0x50U, 0x96U, 0xB8U, 0x16U, 0x47U, 0x41U, 0xA6U, 0x4CU,
0xAEU, 0x89U, 0xBAU, 0x5DU, 0x3CU, 0x49U, 0x33U, 0x23U,
0xD3U, 0xFBU, 0xD4U, 0x04U, 0x11U, 0x8FU, 0x98U, 0x10U,
0xDCU, 0xB7U, 0x06U, 0xE0U, 0x58U, 0xCFU, 0x48U, 0xE3U,
0x1FU, 0x33U, 0xE6U, 0x66U, 0x20U, 0xD2U, 0x34U, 0x43U,
0x62U, 0xA0U, 0x02U, 0x7FU, 0xE9U, 0x36U, 0xB3U, 0xB5U,
0x6BU, 0x07U, 0x8CU, 0xA7U, 0xB1U, 0x11U, 0x28U, 0x6FU,
0x6BU, 0xD0U, 0x09U, 0x4FU, 0xACU, 0x48U, 0x18U, 0xDCU,
0x70U, 0xB6U, 0xD6U, 0x27U, 0x69U, 0x50U, 0x97U, 0x87U,
)
val extracted = Argon2Utils.extractColumnFromGBlock(randomBlockAsArray, 0)
assertTrue {
expected.contentEquals(extracted)
}
}
@Test
fun testCompressionFunctionGWithoutXor() {
val expectedWithoutXor = ubyteArrayOf(
0x94U, 0xE8U, 0x52U, 0x79U, 0xA7U, 0xE5U, 0x66U, 0xAAU,
0xD7U, 0xE1U, 0x8EU, 0x72U, 0x42U, 0xA2U, 0xE1U, 0x50U,
0x5FU, 0x77U, 0x7DU, 0xCDU, 0xE1U, 0xEFU, 0xAAU, 0xF5U,
0x29U, 0x94U, 0x29U, 0x17U, 0x9DU, 0x79U, 0xA5U, 0x67U,
0xD7U, 0x6CU, 0x11U, 0x18U, 0x6FU, 0xE0U, 0xA4U, 0x26U,
0xCCU, 0xF4U, 0xFDU, 0xD1U, 0xE0U, 0x42U, 0xC1U, 0x6AU,
0x33U, 0x99U, 0xC4U, 0x27U, 0x33U, 0x67U, 0xDDU, 0xC3U,
0x57U, 0x81U, 0xF5U, 0xCDU, 0x05U, 0x22U, 0x2DU, 0x5FU,
0x71U, 0x83U, 0xA9U, 0x54U, 0x1BU, 0x09U, 0x40U, 0x68U,
0x6DU, 0x78U, 0x0FU, 0x23U, 0xE2U, 0x90U, 0xC1U, 0x2DU,
0xBFU, 0x44U, 0x26U, 0xADU, 0x8BU, 0x77U, 0x0EU, 0xFBU,
0x9AU, 0x95U, 0x7AU, 0x8DU, 0xEAU, 0xCAU, 0xA2U, 0x1BU,
0xBDU, 0xC0U, 0x90U, 0x85U, 0x37U, 0xD9U, 0xF3U, 0x94U,
0x59U, 0x9EU, 0xB4U, 0xC4U, 0xBCU, 0xC1U, 0x47U, 0x31U,
0x66U, 0xE4U, 0x66U, 0x0EU, 0x86U, 0x11U, 0x4AU, 0x4CU,
0x36U, 0xA1U, 0x1CU, 0xDEU, 0xE9U, 0xA4U, 0x03U, 0x1FU,
0x9CU, 0x7AU, 0x1BU, 0x7AU, 0x8FU, 0x17U, 0xA3U, 0xD4U,
0x5BU, 0x23U, 0x8AU, 0x55U, 0x53U, 0x86U, 0x64U, 0xEDU,
0x24U, 0x97U, 0xFAU, 0x70U, 0xD4U, 0xF1U, 0x9AU, 0x10U,
0xBCU, 0x24U, 0x03U, 0xACU, 0x24U, 0x91U, 0x83U, 0xFBU,
0x66U, 0x02U, 0xC2U, 0x37U, 0xBEU, 0x63U, 0xCEU, 0x59U,
0xEAU, 0x02U, 0xAFU, 0x6CU, 0x8DU, 0x14U, 0xECU, 0xFDU,
0x5BU, 0x0AU, 0x0EU, 0xB6U, 0x51U, 0x2FU, 0x75U, 0xF1U,
0xA9U, 0x88U, 0xD1U, 0x05U, 0x60U, 0xE6U, 0xEDU, 0x17U,
0x4AU, 0x03U, 0x1FU, 0xF7U, 0x71U, 0x86U, 0x26U, 0x18U,
0x7EU, 0xB3U, 0x31U, 0x78U, 0xD8U, 0xB7U, 0x2CU, 0xD0U,
0x6DU, 0xB5U, 0xAEU, 0xDFU, 0x85U, 0xC6U, 0x87U, 0x9FU,
0x18U, 0x85U, 0x1BU, 0x22U, 0x19U, 0x15U, 0x00U, 0xF8U,
0x03U, 0xF7U, 0x48U, 0xA4U, 0xFCU, 0xE3U, 0xE4U, 0x93U,
0x02U, 0x57U, 0x71U, 0xBCU, 0xF6U, 0x2DU, 0x45U, 0xBEU,
0x87U, 0xC1U, 0x21U, 0x11U, 0x77U, 0x23U, 0x78U, 0xFCU,
0x56U, 0xBFU, 0x92U, 0x49U, 0xA1U, 0x51U, 0xE9U, 0x22U,
0x24U, 0x10U, 0x30U, 0x2EU, 0xE1U, 0xC1U, 0xF7U, 0x96U,
0xB0U, 0x27U, 0xF7U, 0x6CU, 0x65U, 0x0CU, 0x1BU, 0xE1U,
0xB2U, 0x12U, 0xD3U, 0xBCU, 0x8BU, 0xEDU, 0x9DU, 0x14U,
0x81U, 0x82U, 0xB3U, 0x5BU, 0x70U, 0x2CU, 0x65U, 0x54U,
0xF5U, 0x1FU, 0x1CU, 0x37U, 0xD2U, 0xD1U, 0x89U, 0x35U,
0x57U, 0x52U, 0xDDU, 0xA7U, 0x02U, 0x81U, 0x14U, 0xF7U,
0x6CU, 0x4CU, 0xB9U, 0x02U, 0x96U, 0x72U, 0xD2U, 0xFEU,
0x30U, 0x66U, 0x8CU, 0x16U, 0x50U, 0xB1U, 0x51U, 0xE9U,
0x48U, 0x48U, 0x83U, 0xA6U, 0x5CU, 0xF9U, 0x98U, 0x59U,
0xBAU, 0x2DU, 0xE5U, 0x73U, 0xADU, 0xD1U, 0x6AU, 0x7AU,
0x1FU, 0x6EU, 0xD8U, 0xC9U, 0xEDU, 0x00U, 0x9AU, 0xB1U,
0x34U, 0x08U, 0x0AU, 0x81U, 0x3EU, 0xCCU, 0x44U, 0xB7U,
0xD6U, 0xFEU, 0x0FU, 0x5CU, 0x19U, 0xD8U, 0x8FU, 0xEDU,
0x46U, 0x88U, 0xF5U, 0x5DU, 0x6BU, 0xDAU, 0x4DU, 0x02U,
0xA9U, 0xFCU, 0x67U, 0xBEU, 0x0CU, 0x09U, 0x38U, 0x98U,
0x79U, 0x52U, 0x7DU, 0xA6U, 0x24U, 0xA8U, 0x3BU, 0xB1U,
0xB2U, 0x52U, 0xC8U, 0x83U, 0x6CU, 0x02U, 0xD8U, 0xBDU,
0x7FU, 0x98U, 0xCCU, 0x65U, 0x01U, 0x90U, 0x6EU, 0x60U,
0xF8U, 0xB8U, 0x94U, 0xABU, 0x7BU, 0xA9U, 0x5FU, 0xE9U,
0xDAU, 0xCCU, 0x94U, 0x00U, 0xEDU, 0x8FU, 0x03U, 0xA3U,
0xCFU, 0xB3U, 0x14U, 0x38U, 0x94U, 0x91U, 0xF3U, 0x61U,
0xEBU, 0x04U, 0xDEU, 0x9DU, 0x9DU, 0x05U, 0x98U, 0xF3U,
0x71U, 0xB1U, 0xB3U, 0xB1U, 0x1DU, 0xA3U, 0x55U, 0x47U,
0xF4U, 0xA3U, 0xF8U, 0x7AU, 0x11U, 0xBBU, 0x0DU, 0x9CU,
0xB1U, 0x57U, 0xAAU, 0xC2U, 0x3CU, 0x0BU, 0xBEU, 0x77U,
0xBCU, 0x25U, 0x03U, 0x8BU, 0x7FU, 0x81U, 0xA5U, 0x7EU,
0xA9U, 0xB4U, 0x3FU, 0x5AU, 0x11U, 0x54U, 0x75U, 0x7DU,
0x45U, 0x20U, 0x90U, 0x46U, 0x98U, 0x70U, 0xF5U, 0x5BU,
0xA5U, 0x9DU, 0x46U, 0x63U, 0x62U, 0x3DU, 0x04U, 0x2FU,
0xB9U, 0x67U, 0x31U, 0xC5U, 0x92U, 0x48U, 0x18U, 0x0FU,
0xDCU, 0x52U, 0x78U, 0xCBU, 0x7CU, 0x86U, 0x58U, 0xDBU,
0x0BU, 0x06U, 0xF2U, 0x93U, 0x83U, 0x26U, 0x99U, 0x5DU,
0xBDU, 0xFBU, 0x87U, 0xC9U, 0x55U, 0x41U, 0xACU, 0x5FU,
0xA3U, 0xF9U, 0x71U, 0x53U, 0x93U, 0x53U, 0xC5U, 0xE4U,
0x3FU, 0x78U, 0x31U, 0x8FU, 0x7CU, 0x0BU, 0x77U, 0x84U,
0x43U, 0xACU, 0x4DU, 0xD1U, 0xC9U, 0x9BU, 0x4BU, 0x60U,
0x00U, 0xFEU, 0x41U, 0x10U, 0xEFU, 0xDFU, 0x80U, 0x95U,
0x03U, 0x23U, 0xBEU, 0xF6U, 0x6BU, 0x60U, 0xE5U, 0x6FU,
0x9EU, 0x6BU, 0x7CU, 0x24U, 0xA7U, 0xC1U, 0xF8U, 0xBBU,
0x60U, 0x55U, 0x57U, 0x18U, 0x58U, 0x32U, 0x97U, 0xE8U,
0x53U, 0x71U, 0x05U, 0x59U, 0xE3U, 0x94U, 0xB1U, 0x60U,
0x8AU, 0x40U, 0x24U, 0xF6U, 0x29U, 0x49U, 0x65U, 0xADU,
0x65U, 0xE3U, 0xCEU, 0x9FU, 0x4FU, 0x47U, 0xA0U, 0x07U,
0x2FU, 0x1CU, 0xA7U, 0x3AU, 0x04U, 0x17U, 0x87U, 0x1BU,
0x06U, 0xC5U, 0x93U, 0x63U, 0x3FU, 0x18U, 0x3BU, 0x8BU,
0x3EU, 0xD4U, 0xC0U, 0xC9U, 0x7EU, 0xB6U, 0x32U, 0xD3U,
0xC3U, 0x8BU, 0x55U, 0x2CU, 0x5BU, 0xB7U, 0xEBU, 0x88U,
0x14U, 0x63U, 0xB8U, 0x3BU, 0xDBU, 0xFFU, 0x49U, 0x44U,
0x79U, 0xD2U, 0x82U, 0xD8U, 0xA6U, 0x47U, 0x45U, 0xFBU,
0xF5U, 0x4BU, 0x5AU, 0x43U, 0x19U, 0xD9U, 0xD5U, 0x52U,
0x04U, 0x0CU, 0x4BU, 0x74U, 0x87U, 0x0DU, 0x11U, 0x8DU,
0x51U, 0x9DU, 0x66U, 0x68U, 0x41U, 0xE0U, 0xFCU, 0x92U,
0x24U, 0x7FU, 0x62U, 0xAFU, 0x8BU, 0x53U, 0xDEU, 0x84U,
0xF0U, 0xA1U, 0x03U, 0xAAU, 0x17U, 0x6FU, 0xD3U, 0x10U,
0x57U, 0x25U, 0xC6U, 0xA3U, 0x8FU, 0x1AU, 0xD3U, 0xD7U,
0x0DU, 0x89U, 0x22U, 0x3CU, 0x17U, 0xC6U, 0xF7U, 0x02U,
0x0CU, 0xD9U, 0x0FU, 0xABU, 0x27U, 0xA6U, 0xE3U, 0x20U,
0xF4U, 0xB2U, 0x21U, 0x12U, 0x85U, 0xF5U, 0x98U, 0x45U,
0x16U, 0x24U, 0xF7U, 0x46U, 0x5DU, 0x1FU, 0x41U, 0x9AU,
0x0EU, 0x25U, 0x4AU, 0x99U, 0x27U, 0x5CU, 0x0BU, 0xC8U,
0x33U, 0x99U, 0x65U, 0x3CU, 0xC9U, 0xDBU, 0x78U, 0x6DU,
0x36U, 0xC6U, 0x37U, 0x35U, 0x2EU, 0x97U, 0x04U, 0x03U,
0x26U, 0x78U, 0x5AU, 0x5AU, 0xD8U, 0xEAU, 0xF7U, 0xF1U,
0xF9U, 0x22U, 0x9DU, 0xDEU, 0xB7U, 0x50U, 0xFEU, 0x91U,
0xD4U, 0x5EU, 0xA1U, 0xC2U, 0x1BU, 0xE4U, 0x3FU, 0x19U,
0x50U, 0x21U, 0x1FU, 0x38U, 0xA1U, 0x11U, 0xB1U, 0x08U,
0x7DU, 0xA2U, 0xBBU, 0xE5U, 0xECU, 0x1BU, 0x9FU, 0x51U,
0x77U, 0x6CU, 0xB9U, 0xA8U, 0xC2U, 0x76U, 0xD4U, 0xCBU,
0x11U, 0x7DU, 0x4AU, 0x92U, 0xE2U, 0x0AU, 0x96U, 0x9AU,
0x28U, 0x72U, 0xFFU, 0xAAU, 0xF8U, 0xD5U, 0x64U, 0x8AU,
0x45U, 0x71U, 0xF3U, 0xB5U, 0xD7U, 0x2AU, 0x3BU, 0x7FU,
0x5CU, 0xFCU, 0x2DU, 0x89U, 0xBCU, 0x64U, 0x2FU, 0x63U,
0x87U, 0xE6U, 0x57U, 0xECU, 0x06U, 0xE3U, 0xDDU, 0x15U,
0xB4U, 0x27U, 0xA8U, 0x6CU, 0x37U, 0x54U, 0xD3U, 0x37U,
0xCFU, 0x4DU, 0x71U, 0x04U, 0x91U, 0x08U, 0x1AU, 0xC6U,
0xBDU, 0xEBU, 0x86U, 0xC5U, 0x5AU, 0x63U, 0x19U, 0xD5U,
0xC5U, 0xCBU, 0x82U, 0xC3U, 0x54U, 0x57U, 0xD8U, 0x6CU,
0x8FU, 0x9AU, 0xF1U, 0x7BU, 0x08U, 0x61U, 0xFCU, 0x96U,
0x1AU, 0xCEU, 0x8FU, 0x11U, 0xE2U, 0xDDU, 0x96U, 0xA3U,
0x57U, 0xD7U, 0x0DU, 0x28U, 0x06U, 0x0AU, 0xC5U, 0x1FU,
0xBBU, 0xC6U, 0x67U, 0xC8U, 0xB0U, 0xA7U, 0xDAU, 0x00U,
0xC3U, 0x00U, 0x21U, 0xACU, 0xFFU, 0xE9U, 0x4FU, 0xB7U,
0x9AU, 0xC9U, 0x77U, 0xC3U, 0x96U, 0x6EU, 0x1CU, 0xC4U,
0x61U, 0xAEU, 0x6FU, 0x55U, 0x0CU, 0xDAU, 0x68U, 0x48U,
0x97U, 0xEDU, 0x9CU, 0x90U, 0x17U, 0x2AU, 0x2DU, 0xC9U,
0x2AU, 0x77U, 0x87U, 0xECU, 0x64U, 0xF5U, 0x78U, 0x99U,
0xA9U, 0xB9U, 0x11U, 0x05U, 0xE9U, 0x7BU, 0x3BU, 0x49U,
0xAEU, 0x61U, 0x70U, 0x0BU, 0xBFU, 0xB7U, 0x67U, 0xA8U,
0x9FU, 0x02U, 0x30U, 0xD3U, 0x0BU, 0x14U, 0xF0U, 0x89U,
0x95U, 0x87U, 0x5BU, 0x04U, 0xF3U, 0x27U, 0xEFU, 0x91U,
0x4AU, 0xD4U, 0x7FU, 0x9EU, 0x73U, 0x95U, 0xE5U, 0x48U,
0x7FU, 0xE4U, 0xF6U, 0x92U, 0x85U, 0x47U, 0xA5U, 0xFEU,
0x12U, 0xD7U, 0xC4U, 0x9EU, 0xCFU, 0x8AU, 0xC2U, 0xD2U,
0x10U, 0x94U, 0xE5U, 0x58U, 0xBBU, 0xE0U, 0xEEU, 0xD9U,
0x6AU, 0x59U, 0xD9U, 0xBCU, 0xD5U, 0xCDU, 0xA0U, 0xBCU,
0xD7U, 0x96U, 0xAAU, 0x23U, 0xA9U, 0x10U, 0x6CU, 0x7EU,
)
val randomBlock1 = ArgonBlock(randomBlockAsArray).getBlockPointer()
val randomBlock2 = ArgonBlock(randomBlockAsArray2).getBlockPointer()
val randomBlock3 = ArgonBlock(randomBlockAsArray3).getBlockPointer()
val resultWithoutXorAndAllocations = Argon2Utils.compressionFunctionG(randomBlock1, randomBlock2, randomBlock3, false)
assertTrue {
expectedWithoutXor.contentEquals(resultWithoutXorAndAllocations.getAsUByteArray())
}
}
@Test
fun compressionFunctionGWithXor() {
val expectedWithXor = ubyteArrayOf(
0x44U, 0xD8U, 0x76U, 0x1AU, 0xD5U, 0x31U, 0xA5U, 0xEDU,
0xFAU, 0xABU, 0x43U, 0x60U, 0x21U, 0xB6U, 0x7DU, 0x28U,
0x65U, 0xF4U, 0xAFU, 0x07U, 0x1DU, 0x01U, 0xB4U, 0x50U,
0x85U, 0x3DU, 0x03U, 0x4CU, 0x33U, 0x58U, 0x8FU, 0xDCU,
0x10U, 0xDEU, 0x26U, 0xF4U, 0xEDU, 0x58U, 0xD1U, 0x84U,
0x7AU, 0x0AU, 0x05U, 0xC7U, 0x6BU, 0xA4U, 0xADU, 0x31U,
0x18U, 0x5DU, 0x11U, 0x10U, 0x5FU, 0x2FU, 0x5EU, 0x6CU,
0x3DU, 0x7EU, 0x3BU, 0xA8U, 0x92U, 0x61U, 0x80U, 0x84U,
0xD1U, 0x45U, 0x83U, 0x85U, 0xE6U, 0x14U, 0x4CU, 0x98U,
0x30U, 0xC1U, 0xB5U, 0x7FU, 0x50U, 0x56U, 0x71U, 0x43U,
0xEAU, 0x84U, 0x38U, 0x2AU, 0x42U, 0x95U, 0xF6U, 0x28U,
0x97U, 0x6BU, 0x86U, 0x6AU, 0x67U, 0x83U, 0xD1U, 0x87U,
0xA6U, 0x19U, 0x05U, 0x7AU, 0x11U, 0xA1U, 0x6EU, 0x10U,
0xCFU, 0x51U, 0x6CU, 0xE6U, 0x63U, 0x32U, 0x45U, 0xBCU,
0x6BU, 0x40U, 0xDBU, 0x8FU, 0x47U, 0x5BU, 0x4BU, 0x36U,
0x3CU, 0xB4U, 0xC8U, 0xF2U, 0x0AU, 0xE1U, 0xE1U, 0xFEU,
0x1FU, 0x8BU, 0xE4U, 0x36U, 0x75U, 0xEBU, 0x70U, 0x52U,
0x1DU, 0xE8U, 0xDEU, 0xD0U, 0xC4U, 0x7CU, 0x9CU, 0x33U,
0xC7U, 0x42U, 0x69U, 0x85U, 0x3FU, 0x99U, 0x75U, 0x59U,
0x9BU, 0xBEU, 0x02U, 0xC0U, 0xBEU, 0xC7U, 0x24U, 0xD0U,
0x66U, 0xD2U, 0x99U, 0xD5U, 0x43U, 0xECU, 0x8FU, 0xA2U,
0x17U, 0x10U, 0x56U, 0x1DU, 0x23U, 0xBAU, 0x33U, 0xF9U,
0x9AU, 0xEBU, 0x6BU, 0x0FU, 0x32U, 0x95U, 0x5BU, 0xB5U,
0x74U, 0x1DU, 0x22U, 0x36U, 0x1FU, 0x49U, 0xD6U, 0xC2U,
0xC0U, 0xEAU, 0xA1U, 0x07U, 0x73U, 0x9CU, 0x85U, 0x78U,
0xD6U, 0x63U, 0x98U, 0x44U, 0x7FU, 0x98U, 0x80U, 0x6BU,
0xC5U, 0x99U, 0x35U, 0xBCU, 0xB3U, 0xAAU, 0x8FU, 0xEBU,
0x32U, 0x62U, 0xAEU, 0xF7U, 0xAEU, 0x23U, 0x96U, 0xCBU,
0x58U, 0x84U, 0x50U, 0xA7U, 0x4CU, 0x85U, 0x7BU, 0xE3U,
0x32U, 0xE4U, 0xFAU, 0x66U, 0x25U, 0x60U, 0x64U, 0xA2U,
0x6FU, 0xE2U, 0x68U, 0xBDU, 0x61U, 0x5DU, 0x2CU, 0xD3U,
0x58U, 0xE2U, 0xC5U, 0x8CU, 0x42U, 0xC9U, 0x9CU, 0xECU,
0x62U, 0xE5U, 0xA9U, 0xC3U, 0x20U, 0x72U, 0x59U, 0x6AU,
0xF1U, 0xEAU, 0x54U, 0xEAU, 0xE6U, 0x80U, 0x09U, 0x8BU,
0x55U, 0x6CU, 0xDDU, 0x26U, 0x69U, 0xFDU, 0x25U, 0x97U,
0xDCU, 0xAFU, 0x1BU, 0x04U, 0x08U, 0xC2U, 0x54U, 0xBAU,
0xACU, 0xCBU, 0x97U, 0x7AU, 0xDBU, 0x59U, 0x8FU, 0x7DU,
0x95U, 0xB4U, 0x41U, 0x8AU, 0xC9U, 0xB4U, 0xF3U, 0xC0U,
0x5BU, 0x75U, 0x4EU, 0xE9U, 0x24U, 0x7FU, 0x8CU, 0xA1U,
0x05U, 0x6EU, 0x3BU, 0x3EU, 0xBDU, 0x03U, 0xE4U, 0x41U,
0x26U, 0x58U, 0x09U, 0xC1U, 0xE6U, 0x8EU, 0x22U, 0x59U,
0x3BU, 0xEEU, 0x21U, 0x5BU, 0x43U, 0x37U, 0x65U, 0xD2U,
0x13U, 0x6CU, 0xF8U, 0x06U, 0x48U, 0xADU, 0x09U, 0x9AU,
0xE1U, 0xE5U, 0x0CU, 0x2DU, 0x52U, 0xADU, 0x3BU, 0xC7U,
0xE7U, 0x78U, 0x7EU, 0xCDU, 0x1EU, 0xE9U, 0x7AU, 0x5DU,
0x54U, 0x89U, 0x1EU, 0xEFU, 0xA2U, 0x44U, 0xF4U, 0x38U,
0xE7U, 0xB5U, 0x0FU, 0xC8U, 0x1FU, 0x7EU, 0x9CU, 0x93U,
0x88U, 0x71U, 0xAEU, 0x19U, 0x0DU, 0x0FU, 0xCFU, 0xF1U,
0xCFU, 0x67U, 0x94U, 0x0FU, 0x5FU, 0xB2U, 0xC3U, 0x8FU,
0xE8U, 0xC3U, 0x07U, 0x0EU, 0xECU, 0x99U, 0x36U, 0x57U,
0x7AU, 0xA6U, 0xA9U, 0x44U, 0x5BU, 0x68U, 0x5AU, 0xB4U,
0xBFU, 0xA9U, 0xC9U, 0xE5U, 0xC8U, 0x20U, 0x31U, 0xD2U,
0xE9U, 0x3EU, 0x6FU, 0x09U, 0x8FU, 0x7DU, 0x75U, 0x0EU,
0x35U, 0xE8U, 0x90U, 0x04U, 0xB8U, 0x4AU, 0x12U, 0xE5U,
0xC0U, 0xCCU, 0x6AU, 0xB0U, 0x9FU, 0x8FU, 0xAFU, 0x8CU,
0x83U, 0x13U, 0x43U, 0x8EU, 0x5FU, 0x8AU, 0x1EU, 0xD3U,
0xF2U, 0x9AU, 0xE5U, 0x95U, 0x6DU, 0xAEU, 0x4DU, 0xDBU,
0x0CU, 0x06U, 0xDEU, 0x5CU, 0xD0U, 0x68U, 0xFFU, 0x4CU,
0xECU, 0x82U, 0xC8U, 0xAFU, 0x44U, 0xC0U, 0x3BU, 0x0BU,
0x89U, 0xADU, 0x32U, 0xAEU, 0xE7U, 0x36U, 0x2AU, 0x05U,
0x18U, 0x5FU, 0xB9U, 0xBDU, 0x52U, 0x7FU, 0x73U, 0x70U,
0x5AU, 0x5BU, 0x88U, 0x20U, 0x16U, 0x84U, 0xECU, 0x91U,
0xF7U, 0xD2U, 0x2FU, 0x6DU, 0x69U, 0x37U, 0xEAU, 0x2BU,
0x24U, 0xA2U, 0x58U, 0xDAU, 0x01U, 0x32U, 0x91U, 0x94U,
0x53U, 0x4DU, 0xBDU, 0x28U, 0xEAU, 0x70U, 0x75U, 0x77U,
0xD7U, 0x5DU, 0xF0U, 0xAAU, 0x5AU, 0x39U, 0xB9U, 0xC7U,
0xDBU, 0xC0U, 0xCFU, 0x72U, 0x6DU, 0xB0U, 0x04U, 0xBDU,
0x34U, 0x58U, 0x2AU, 0x6BU, 0x46U, 0xEDU, 0x7DU, 0x1AU,
0x15U, 0x85U, 0xD3U, 0x14U, 0xC6U, 0xF9U, 0x32U, 0x72U,
0x9AU, 0xD9U, 0x1AU, 0xBFU, 0xBDU, 0x3CU, 0x45U, 0x46U,
0x17U, 0x6DU, 0xAEU, 0x1EU, 0x12U, 0xE5U, 0x00U, 0x6DU,
0xD4U, 0xC0U, 0x71U, 0x8BU, 0xAFU, 0x12U, 0x7BU, 0x1EU,
0x73U, 0xD7U, 0x68U, 0x9EU, 0x45U, 0xC1U, 0x85U, 0xD9U,
0x15U, 0x6EU, 0xCAU, 0xCCU, 0x75U, 0x62U, 0x20U, 0x27U,
0x26U, 0x6AU, 0xFAU, 0x5FU, 0xB4U, 0x9FU, 0xDFU, 0x2EU,
0x3DU, 0x5BU, 0xE5U, 0x2BU, 0xEEU, 0x56U, 0x5CU, 0x91U,
0x28U, 0x56U, 0x7DU, 0x16U, 0x78U, 0x63U, 0xB5U, 0x3BU,
0x51U, 0xA3U, 0x96U, 0x52U, 0xDAU, 0x8EU, 0xBBU, 0x92U,
0xA0U, 0xD3U, 0xBDU, 0xB8U, 0xA1U, 0x4CU, 0x83U, 0xEDU,
0x4EU, 0x29U, 0xBEU, 0x9FU, 0x73U, 0x55U, 0x47U, 0x7AU,
0x31U, 0x30U, 0xFBU, 0x41U, 0x9DU, 0x89U, 0x26U, 0xF6U,
0x19U, 0x48U, 0x6CU, 0xB9U, 0xD0U, 0x11U, 0x8DU, 0xF8U,
0x8FU, 0x0FU, 0xB1U, 0x15U, 0x96U, 0xA9U, 0x06U, 0x4EU,
0x01U, 0xCCU, 0x48U, 0xBDU, 0x65U, 0x2FU, 0x27U, 0x67U,
0x74U, 0x89U, 0x54U, 0x24U, 0x88U, 0xF8U, 0x1EU, 0x90U,
0xFBU, 0xFFU, 0xD1U, 0x57U, 0xE2U, 0x95U, 0x97U, 0x2BU,
0x67U, 0x6EU, 0x6CU, 0xACU, 0x63U, 0x2CU, 0x96U, 0x61U,
0xBEU, 0x58U, 0xD8U, 0xE4U, 0x0FU, 0x94U, 0x27U, 0x4AU,
0x75U, 0x1CU, 0xE1U, 0x49U, 0xCDU, 0xFCU, 0x17U, 0xEAU,
0x68U, 0x0EU, 0x1AU, 0x86U, 0xFBU, 0xF6U, 0x27U, 0x87U,
0x48U, 0xBFU, 0x49U, 0x9AU, 0xB2U, 0x9EU, 0xAAU, 0xA9U,
0x7DU, 0x30U, 0x0AU, 0x21U, 0x16U, 0xD5U, 0x82U, 0x86U,
0x11U, 0x0EU, 0x9FU, 0xB0U, 0xC5U, 0x1CU, 0xBAU, 0xA7U,
0xB1U, 0x31U, 0x49U, 0x41U, 0x27U, 0x26U, 0xCEU, 0xDDU,
0xC4U, 0x45U, 0xA8U, 0xD5U, 0xC0U, 0x11U, 0xACU, 0xCCU,
0x9CU, 0x2EU, 0x04U, 0xB0U, 0xF8U, 0x87U, 0x29U, 0x8EU,
0x0FU, 0x53U, 0xF9U, 0xC9U, 0x69U, 0xFFU, 0x17U, 0x18U,
0x25U, 0x95U, 0x9EU, 0x88U, 0x03U, 0xC7U, 0xE9U, 0xC5U,
0xC6U, 0x2AU, 0xD0U, 0x91U, 0x7DU, 0x93U, 0xBDU, 0x77U,
0xB8U, 0xF1U, 0x5FU, 0x8CU, 0x83U, 0xE1U, 0x85U, 0x65U,
0x36U, 0xFAU, 0x43U, 0x90U, 0xBCU, 0x8EU, 0x12U, 0x1AU,
0xF0U, 0xF3U, 0x04U, 0x1FU, 0x77U, 0x6FU, 0xB8U, 0x52U,
0xFDU, 0xA3U, 0x6BU, 0x3DU, 0xFEU, 0xD8U, 0x86U, 0x14U,
0x10U, 0xFFU, 0xCFU, 0xF2U, 0xC7U, 0x06U, 0xE9U, 0x02U,
0x5CU, 0xFDU, 0x39U, 0xBBU, 0x3CU, 0x68U, 0xA2U, 0xBAU,
0x84U, 0x02U, 0xDAU, 0xD2U, 0x10U, 0x80U, 0xD6U, 0xCAU,
0xEAU, 0xDBU, 0xB9U, 0xAEU, 0xAEU, 0x85U, 0xBEU, 0xCDU,
0x72U, 0xCFU, 0xCFU, 0x6CU, 0xA0U, 0xFBU, 0x5CU, 0x74U,
0xADU, 0x4EU, 0x92U, 0x37U, 0xDBU, 0xD5U, 0x28U, 0x71U,
0x35U, 0xD0U, 0xACU, 0xE7U, 0x71U, 0xE1U, 0xB7U, 0x9AU,
0x2EU, 0x3FU, 0x8DU, 0xB8U, 0x10U, 0xC1U, 0xEEU, 0x35U,
0x0BU, 0x83U, 0xA3U, 0xF0U, 0xBAU, 0xFCU, 0x75U, 0x43U,
0x95U, 0x86U, 0x4CU, 0x0AU, 0x22U, 0xE8U, 0xDCU, 0x7DU,
0x6EU, 0xB8U, 0xF8U, 0xE2U, 0x97U, 0x57U, 0x06U, 0xB4U,
0x89U, 0xCAU, 0x9DU, 0xD5U, 0xDEU, 0xB6U, 0x48U, 0xCDU,
0x29U, 0x3CU, 0xDFU, 0x7EU, 0x1EU, 0x37U, 0xCEU, 0x48U,
0x20U, 0x5CU, 0xE3U, 0xCDU, 0x2FU, 0xA8U, 0xE5U, 0xC0U,
0xB7U, 0xABU, 0xDFU, 0xDBU, 0x8DU, 0xD8U, 0x5DU, 0xF7U,
0xA7U, 0x5CU, 0xF7U, 0xFFU, 0xD2U, 0x04U, 0xA5U, 0xE1U,
0x35U, 0xE3U, 0x67U, 0xCEU, 0x42U, 0xC1U, 0x3EU, 0xABU,
0x4AU, 0xFFU, 0x02U, 0x9AU, 0x94U, 0x9CU, 0x9AU, 0xC5U,
0xDCU, 0xC1U, 0x50U, 0x52U, 0x1CU, 0x04U, 0xF9U, 0x23U,
0x6DU, 0xA6U, 0x5AU, 0x9BU, 0xAAU, 0x5EU, 0x08U, 0xD1U,
0xCCU, 0x35U, 0x29U, 0xF5U, 0x3DU, 0xAAU, 0xB3U, 0x25U,
0xB6U, 0x07U, 0x29U, 0x4DU, 0x75U, 0x3CU, 0xADU, 0x17U,
0xBEU, 0xD5U, 0xC0U, 0xDFU, 0x05U, 0xFEU, 0xB8U, 0x2DU,
0x52U, 0xECU, 0xA7U, 0x67U, 0x6EU, 0xBAU, 0x32U, 0xE4U,
0xD6U, 0x31U, 0x13U, 0x83U, 0xFDU, 0xEBU, 0xEBU, 0x91U,
)
val randomBlock1 = ArgonBlock(randomBlockAsArray).getBlockPointer()
val randomBlock2 = ArgonBlock(randomBlockAsArray2).getBlockPointer()
val randomBlock3 = ArgonBlock(randomBlockAsArray3).getBlockPointer()
val resultWithoutXorAndAllocations = Argon2Utils.compressionFunctionG(randomBlock1, randomBlock2, randomBlock3, true)
assertTrue {
expectedWithXor.contentEquals(resultWithoutXorAndAllocations.getAsUByteArray())
}
}
}

View File

@ -0,0 +1,293 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.hash.blake2b
import kotlin.test.Test
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 14-Jul-2019
*/
@ExperimentalUnsignedTypes
@ExperimentalStdlibApi
class Blake2BTest {
@Test
fun testMultipleBlocks() {
val test = "1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890"
val result = Blake2b.digest(test)
//Generated with b2sum 8.31
val expectedResult = ubyteArrayOf(
//@formatter:off
0x2fU, 0x49U, 0xaeU, 0xb6U, 0x13U, 0xe3U, 0x4eU, 0x92U, 0x4eU, 0x17U, 0x5aU, 0x6aU, 0xf2U, 0xfaU, 0xadU,
0x7bU, 0xc7U, 0x82U, 0x35U, 0xf9U, 0xc5U, 0xe4U, 0x61U, 0xc6U, 0x8fU, 0xd5U, 0xb4U, 0x07U, 0xeeU, 0x8eU,
0x2fU, 0x0dU, 0x2fU, 0xb4U, 0xc0U, 0x7dU, 0x7eU, 0x4aU, 0x72U, 0x40U, 0x46U, 0x12U, 0xd9U, 0x28U, 0x99U,
0xafU, 0x8aU, 0x32U, 0x8fU, 0x3bU, 0x61U, 0x4eU, 0xd7U, 0x72U, 0x44U, 0xb4U, 0x81U, 0x15U, 0x1dU, 0x40U,
0xb1U, 0x1eU, 0x32U, 0xa4U
//@formatter:on
)
assertTrue {
result.contentEquals(expectedResult)
}
}
@Test
fun singleBlockTest() {
val test = "1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890" +
"1234567890"
val result = Blake2b.digest(test)
val expectedResultString = "800bb78cd4da18995c8074713bb674" +
"3cd94b2b6490a693fe4000ed00833b88b7b474d94af9cfed246b1b" +
"4ce1935a76154d7ea7c410493557741d18ec3a08da75"
val expectedResult = expectedResultString.chunked(2).map { it.toUByte(16) }.toUByteArray()
assertTrue {
result.contentEquals(expectedResult)
}
}
@Test
fun testDigest() {
val test = "111111111122222222223333333333333"
val result = Blake2b.digest(test)
//Generated with b2sum 8.31
val expectedResult = ubyteArrayOf(
//@formatter:off
0xe0U, 0xabU, 0xb7U, 0x5dU, 0xb2U, 0xc8U, 0xe1U, 0x3cU, 0x5fU, 0x1dU, 0x9fU, 0x55U, 0xc8U, 0x4eU, 0xacU, 0xd7U,
0xa8U, 0x44U, 0x57U, 0x9bU, 0xc6U, 0x9cU, 0x47U, 0x26U, 0xebU, 0xeaU, 0x2bU, 0xafU, 0x9eU, 0x44U, 0x16U, 0xebU,
0xb8U, 0x0aU, 0xc5U, 0xfbU, 0xb0U, 0xe8U, 0xe5U, 0x6eU, 0xc5U, 0x49U, 0x0dU, 0x75U, 0x59U, 0x32U, 0x13U, 0xb4U,
0x76U, 0x50U, 0x5eU, 0x6aU, 0xd8U, 0x74U, 0x67U, 0x14U, 0x64U, 0xb0U, 0xf8U, 0xb5U, 0x50U, 0x60U, 0x62U, 0xfbU
//@formatter:on
)
assertTrue {
result.contentEquals(expectedResult)
}
}
@Test
fun testFigestWithKey() {
val test = "abc"
val key = "key"
val result = Blake2b.digest(test, key)
assertTrue {
result.isNotEmpty()
}
val expectedResult = ("5c6a9a4ae911c02fb7e71a991eb9aea371ae993d4842d206e" +
"6020d46f5e41358c6d5c277c110ef86c959ed63e6ecaaaceaaff38019a43264ae06acf73b9550b1")
.chunked(2).map { it.toUByte(16) }.toUByteArray()
assertTrue {
result.contentEquals(expectedResult)
}
}
@Test
fun testDigestFromRfc() {
val test = "abc"
val result = Blake2b.digest(test)
//@formatter:off
val expectedResult = ubyteArrayOf(
0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U,
0x4CU,0x21U,0x2FU,0x14U,0x68U,0x5AU,0xC4U,0xB7U,0x4BU,0x12U,0xBBU,0x6FU,0xDBU,0xFFU,0xA2U,0xD1U,
0x7DU,0x87U,0xC5U,0x39U,0x2AU,0xABU,0x79U,0x2DU,0xC2U,0x52U,0xD5U,0xDEU,0x45U,0x33U,0xCCU,0x95U,
0x18U,0xD3U,0x8AU,0xA8U,0xDBU,0xF1U,0x92U,0x5AU,0xB9U,0x23U,0x86U,0xEDU,0xD4U,0x00U,0x99U,0x23U
)
//@formatter:on
assertTrue {
result.contentEquals(expectedResult)
}
}
val message = arrayOf(
0x0000000000636261UL, 0x0000000000000000UL, 0x0000000000000000UL,
0x0000000000000000UL, 0x0000000000000000UL, 0x0000000000000000UL,
0x0000000000000000UL, 0x0000000000000000UL, 0x0000000000000000UL,
0x0000000000000000UL, 0x0000000000000000UL, 0x0000000000000000UL,
0x0000000000000000UL, 0x0000000000000000UL, 0x0000000000000000UL,
0x0000000000000000UL
)
val mixChain = arrayOf(
arrayOf(
0x6A09E667F2BDC948UL, 0xBB67AE8584CAA73BUL, 0x3C6EF372FE94F82BUL,
0xA54FF53A5F1D36F1UL, 0x510E527FADE682D1UL, 0x9B05688C2B3E6C1FUL,
0x1F83D9ABFB41BD6BUL, 0x5BE0CD19137E2179UL, 0x6A09E667F3BCC908UL,
0xBB67AE8584CAA73BUL, 0x3C6EF372FE94F82BUL, 0xA54FF53A5F1D36F1UL,
0x510E527FADE682D2UL, 0x9B05688C2B3E6C1FUL, 0xE07C265404BE4294UL,
0x5BE0CD19137E2179UL
),
arrayOf(
0x86B7C1568029BB79UL, 0xC12CBCC809FF59F3UL, 0xC6A5214CC0EACA8EUL,
0x0C87CD524C14CC5DUL, 0x44EE6039BD86A9F7UL, 0xA447C850AA694A7EUL,
0xDE080F1BB1C0F84BUL, 0x595CB8A9A1ACA66CUL, 0xBEC3AE837EAC4887UL,
0x6267FC79DF9D6AD1UL, 0xFA87B01273FA6DBEUL, 0x521A715C63E08D8AUL,
0xE02D0975B8D37A83UL, 0x1C7B754F08B7D193UL, 0x8F885A76B6E578FEUL,
0x2318A24E2140FC64UL
),
arrayOf(
0x53281E83806010F2UL, 0x3594B403F81B4393UL, 0x8CD63C7462DE0DFFUL,
0x85F693F3DA53F974UL, 0xBAABDBB2F386D9AEUL, 0xCA5425AEC65A10A8UL,
0xC6A22E2FF0F7AA48UL, 0xC6A56A51CB89C595UL, 0x224E6A3369224F96UL,
0x500E125E58A92923UL, 0xE9E4AD0D0E1A0D48UL, 0x85DF9DC143C59A74UL,
0x92A3AAAA6D952B7FUL, 0xC5FDF71090FAE853UL, 0x2A8A40F15A462DD0UL,
0x572D17EFFDD37358UL
),
arrayOf(
0x60ED96AA7AD41725UL, 0xE46A743C71800B9DUL, 0x1A04B543A01F156BUL,
0xA2F8716E775C4877UL, 0xDA0A61BCDE4267EAUL, 0xB1DD230754D7BDEEUL,
0x25A1422779E06D14UL, 0xE6823AE4C3FF58A5UL, 0xA1677E19F37FD5DAUL,
0x22BDCE6976B08C51UL, 0xF1DE8696BEC11BF1UL, 0xA0EBD586A4A1D2C8UL,
0xC804EBAB11C99FA9UL, 0x8E0CEC959C715793UL, 0x7C45557FAE0D4D89UL,
0x716343F52FDD265EUL
),
arrayOf(
0xBB2A77D3A8382351UL, 0x45EB47971F23B103UL, 0x98BE297F6E45C684UL,
0xA36077DEE3370B89UL, 0x8A03C4CB7E97590AUL, 0x24192E49EBF54EA0UL,
0x4F82C9401CB32D7AUL, 0x8CCD013726420DC4UL, 0xA9C9A8F17B1FC614UL,
0x55908187977514A0UL, 0x5B44273E66B19D27UL, 0xB6D5C9FCA2579327UL,
0x086092CFB858437EUL, 0x5C4BE2156DBEECF9UL, 0x2EFEDE99ED4EFF16UL,
0x3E7B5F234CD1F804UL
),
arrayOf(
0xC79C15B3D423B099UL, 0x2DA2224E8DA97556UL, 0x77D2B26DF1C45C55UL,
0x8934EB09A3456052UL, 0x0F6D9EEED157DA2AUL, 0x6FE66467AF88C0A9UL,
0x4EB0B76284C7AAFBUL, 0x299C8E725D954697UL, 0xB2240B59E6D567D3UL,
0x2643C2370E49EBFDUL, 0x79E02EEF20CDB1AEUL, 0x64B3EED7BB602F39UL,
0xB97D2D439E4DF63DUL, 0xC718E755294C9111UL, 0x1F0893F2772BB373UL,
0x1205EA4A7859807DUL
),
arrayOf(
0xE58F97D6385BAEE4UL, 0x7640AA9764DA137AUL, 0xDEB4C7C23EFE287EUL,
0x70F6F41C8783C9F6UL, 0x7127CD48C76A7708UL, 0x9E472AF0BE3DB3F6UL,
0x0F244C62DDF71788UL, 0x219828AA83880842UL, 0x41CCA9073C8C4D0DUL,
0x5C7912BC10DF3B4BUL, 0xA2C3ABBD37510EE2UL, 0xCB5668CC2A9F7859UL,
0x8733794F07AC1500UL, 0xC67A6BE42335AA6FUL, 0xACB22B28681E4C82UL,
0xDB2161604CBC9828UL
),
arrayOf(
0x6E2D286EEADEDC81UL, 0xBCF02C0787E86358UL, 0x57D56A56DD015EDFUL,
0x55D899D40A5D0D0AUL, 0x819415B56220C459UL, 0xB63C479A6A769F02UL,
0x258E55E0EC1F362AUL, 0x3A3B4EC60E19DFDCUL, 0x04D769B3FCB048DBUL,
0xB78A9A33E9BFF4DDUL, 0x5777272AE1E930C0UL, 0x5A387849E578DBF6UL,
0x92AAC307CF2C0AFCUL, 0x30AACCC4F06DAFAAUL, 0x483893CC094F8863UL,
0xE03C6CC89C26BF92UL
),
arrayOf(
0xFFC83ECE76024D01UL, 0x1BE7BFFB8C5CC5F9UL, 0xA35A18CBAC4C65B7UL,
0xB7C2C7E6D88C285FUL, 0x81937DA314A50838UL, 0xE1179523A2541963UL,
0x3A1FAD7106232B8FUL, 0x1C7EDE92AB8B9C46UL, 0xA3C2D35E4F685C10UL,
0xA53D3F73AA619624UL, 0x30BBCC0285A22F65UL, 0xBCEFBB6A81539E5DUL,
0x3841DEF6F4C9848AUL, 0x98662C85FBA726D4UL, 0x7762439BD5A851BDUL,
0xB0B9F0D443D1A889UL
),
arrayOf(
0x753A70A1E8FAEADDUL, 0x6B0D43CA2C25D629UL, 0xF8343BA8B94F8C0BUL,
0xBC7D062B0DB5CF35UL, 0x58540EE1B1AEBC47UL, 0x63C5B9B80D294CB9UL,
0x490870ECAD27DEBDUL, 0xB2A90DDF667287FEUL, 0x316CC9EBEEFAD8FCUL,
0x4A466BCD021526A4UL, 0x5DA7F7638CEC5669UL, 0xD9C8826727D306FCUL,
0x88ED6C4F3BD7A537UL, 0x19AE688DDF67F026UL, 0x4D8707AAB40F7E6DUL,
0xFD3F572687FEA4F1UL
),
arrayOf(
0xE630C747CCD59C4FUL, 0xBC713D41127571CAUL, 0x46DB183025025078UL,
0x6727E81260610140UL, 0x2D04185EAC2A8CBAUL, 0x5F311B88904056ECUL,
0x40BD313009201AABUL, 0x0099D4F82A2A1EABUL, 0x6DD4FBC1DE60165DUL,
0xB3B0B51DE3C86270UL, 0x900AEE2F233B08E5UL, 0xA07199D87AD058D8UL,
0x2C6B25593D717852UL, 0x37E8CA471BEAA5F8UL, 0x2CFC1BAC10EF4457UL,
0x01369EC18746E775UL
),
arrayOf(
0xE801F73B9768C760UL, 0x35C6D22320BE511DUL, 0x306F27584F65495EUL,
0xB51776ADF569A77BUL, 0xF4F1BE86690B3C34UL, 0x3CC88735D1475E4BUL,
0x5DAC67921FF76949UL, 0x1CDB9D31AD70CC4EUL, 0x35BA354A9C7DF448UL,
0x4929CBE45679D73EUL, 0x733D1A17248F39DBUL, 0x92D57B736F5F170AUL,
0x61B5C0A41D491399UL, 0xB5C333457E12844AUL, 0xBD696BE010D0D889UL,
0x02231E1A917FE0BDUL
),
arrayOf(
0x12EF8A641EC4F6D6UL, 0xBCED5DE977C9FAF5UL, 0x733CA476C5148639UL,
0x97DF596B0610F6FCUL, 0xF42C16519AD5AFA7UL, 0xAA5AC1888E10467EUL,
0x217D930AA51787F3UL, 0x906A6FF19E573942UL, 0x75AB709BD3DCBF24UL,
0xEE7CE1F345947AA4UL, 0xF8960D6C2FAF5F5EUL, 0xE332538A36B6D246UL,
0x885BEF040EF6AA0BUL, 0xA4939A417BFB78A3UL, 0x646CBB7AF6DCE980UL,
0xE813A23C60AF3B82UL
)
)
@Test
fun testMixRound() {
for (i in 0 until mixChain.size - 1) {
val inputRound = mixChain[i]
val round = i
val result = Blake2b.mixRound(inputRound, message, round)
val expectedResult = mixChain[i + 1]
assertTrue {
result.contentEquals(expectedResult)
}
}
}
@Test
fun testInvalidHashLength() {
val test = "1234567890"
assertFailsWith(RuntimeException::class) {
val result = Blake2b.digest(inputString = test, hashLength = 65)
}
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.hash.blake2b
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 20-Jul-2019
*/
@ExperimentalUnsignedTypes
@ExperimentalStdlibApi
class Blake2bInstanceTest {
@Test
fun testUpdatableBlake2b() {
val updates = 14
val input = "1234567890"
val expectedResult = ubyteArrayOf(
//@formatter:off
0x2fU, 0x49U, 0xaeU, 0xb6U, 0x13U, 0xe3U, 0x4eU, 0x92U, 0x4eU, 0x17U, 0x5aU, 0x6aU, 0xf2U, 0xfaU, 0xadU,
0x7bU, 0xc7U, 0x82U, 0x35U, 0xf9U, 0xc5U, 0xe4U, 0x61U, 0xc6U, 0x8fU, 0xd5U, 0xb4U, 0x07U, 0xeeU, 0x8eU,
0x2fU, 0x0dU, 0x2fU, 0xb4U, 0xc0U, 0x7dU, 0x7eU, 0x4aU, 0x72U, 0x40U, 0x46U, 0x12U, 0xd9U, 0x28U, 0x99U,
0xafU, 0x8aU, 0x32U, 0x8fU, 0x3bU, 0x61U, 0x4eU, 0xd7U, 0x72U, 0x44U, 0xb4U, 0x81U, 0x15U, 0x1dU, 0x40U,
0xb1U, 0x1eU, 0x32U, 0xa4U
//@formatter:on
)
val blake2b = Blake2b()
for (i in 0 until updates) {
blake2b.update(input)
}
val result = blake2b.digest()
assertTrue {
result.contentEquals(expectedResult)
}
}
@Test
fun testDigestToString() {
val updates = 14
val input = "1234567890"
val expectedResult = "2F49AEB613E34E924E175A6AF2FAAD7BC78235F9C5E461C68FD5B47E".toLowerCase() +
"E8E2FD2FB4C07D7E4A72404612D92899AF8A328F3B614ED77244B481151D40B11E32A4".toLowerCase()
val blake2b = Blake2b()
for (i in 0 until updates) {
blake2b.update(input)
}
val result = blake2b.digestString()
assertTrue {
result == expectedResult
}
}
@Test
fun testDigestWithKey() {
val test = "abc"
val key = "key"
val blake2b = Blake2b(key)
blake2b.update(test)
val result = blake2b.digest()
assertTrue {
result.isNotEmpty()
}
val expectedResult = ("5c6a9a4ae911c02fb7e71a991eb9aea371ae993d4842d206e" +
"6020d46f5e41358c6d5c277c110ef86c959ed63e6ecaaaceaaff38019a43264ae06acf73b9550b1")
.chunked(2).map { it.toUByte(16) }.toUByteArray()
assertTrue {
result.contentEquals(expectedResult)
}
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.hash.sha
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 17-Jul-2019
*/
@ExperimentalUnsignedTypes
class Sha256Test {
@ExperimentalStdlibApi
@Test
fun testWellKnownValue() {
val result = Sha256.digest(inputString = "abc")
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun testWellKnownDoubleBlock() {
val resultDoubleBlock = Sha256.digest(inputString = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun testWellKnown3() { //It's good that I'm consistent with names.
val resultDoubleBlock = Sha256.digest(inputString = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun testWellKnownLong() {
val inputBuilder = StringBuilder()
for (i in 0 until 1000000) {
inputBuilder.append("a")
}
val resultDoubleBlock = Sha256.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
val expectedResultForDoubleBlock = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.hash.sha
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 17-Jul-2019
*/
@ExperimentalUnsignedTypes
class Sha256UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownValue() {
val sha256 = Sha256()
sha256.update("abc")
val result = sha256.digest()
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun testWellKnownDoubleBlock() {
val sha256 = Sha256()
sha256.update(data = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val resultDoubleBlock = sha256.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun testWellKnown3() { //It's good that I'm consistent with names.
val sha256 = Sha256()
sha256.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha256.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun testWellKnownLong() {
val sha256 = Sha256()
for (i in 0 until 10000) {
sha256.update("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
}
val resultDoubleBlock = sha256.digest()
val expectedResultForDoubleBlock = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@Ignore()
@ExperimentalStdlibApi
@Test
fun testWellKnownLonger() {
val sha256 = Sha256()
for (i in 0 until 16_777_216) {
if (i % 10000 == 0) {
println("$i/16777216")
}
sha256.update("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno")
}
val resultDoubleBlock = sha256.digest()
val expectedResultForDoubleBlock = "50e72a0e26442fe2552dc3938ac58658228c0cbfb1d2ca872ae435266fcd055e"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.hash.sha
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 17-Jul-2019
*/
class Sha512Test {
@ExperimentalStdlibApi
@Test
fun testWellKnownValue() {
val result = Sha512.digest(inputMessage = "abc".encodeToByteArray().map { it.toUByte() }.toUByteArray())
println(result.map {it.toString(16)})
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalUnsignedTypes
@ExperimentalStdlibApi
@Test
fun testWellKnown3() {
val sha512 = Sha512()
sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha512.digest()
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun testWellKnownLong() {
val inputBuilder = StringBuilder()
for (i in 0 until 1000000) {
inputBuilder.append("a")
}
val resultDoubleBlock = Sha512.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
val expectedResultForDoubleBlock = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.hash.sha
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 21-Jul-2019
*/
class Sha512UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownValue() {
val sha512 = Sha512()
sha512.update("abc")
val result = sha512.digest()
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun testWellKnownDoubleBlock() {
val sha512 = Sha512()
sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha512.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@ExperimentalStdlibApi
@Test
fun testWellKnownLong() {
val sha512 = Sha512()
for (i in 0 until 10000) {
sha512.update("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
}
val resultDoubleBlock = sha512.digest()
val expectedResultForDoubleBlock = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
@Ignore() //Interestingly enough I'm not the only one having trouble with this test.
@ExperimentalStdlibApi
@Test
fun testWellKnownLonger() {
val sha512 = Sha512()
for (i in 0 until 16_777_216) {
if (i % 10000 == 0) {
println("$i/16777216")
}
sha512.update("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno")
}
val resultDoubleBlock = sha512.digest()
val expectedResultForDoubleBlock = "b47c933421ea2db149ad6e10fce6c7f93d0752380180ffd7f4629a712134831d77be6091b819ed352c2967a2e2d4fa5050723c9630691f1a05a7281dbe6c1086"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
}
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.parallelization
import com.ionspin.kotlin.crypto.util.testBlocking
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlin.test.Test
import kotlin.time.ExperimentalTime
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 17-May-2020
*/
@ExperimentalTime
class CoroutinesDebugTest {
@Test
fun debugTest() = testBlocking {
Coroutines14.argonParallel()
}
}

View File

@ -0,0 +1,108 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.symmetric
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
import com.ionspin.kotlin.crypto.util.toHexString
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 21-Sep-2019
*/
@ExperimentalUnsignedTypes
class AesCbcTest {
@Test
fun testCbcEncryption() {
assertTrue {
val key = "4278b840fb44aaa757c1bf04acbe1a3e"
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
val plaintext = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val expectedCipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val aesCbc =
AesCbc(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initializationVector = iv.hexStringToUByteArray())
aesCbc.addData(plaintext.hexStringToUByteArray())
val encrypted = aesCbc.encrypt()
println("Encrypted: ${encrypted.encryptedData.toHexString()}")
expectedCipherText == encrypted.encryptedData.toHexString() &&
iv == encrypted.initilizationVector.toHexString()
}
}
@Test
fun testEncryptionApi() {
assertTrue {
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
val key = AesKey.Aes128Key(keyString)
val plainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val encryptedDataAndInitializationVector = AesCbc.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCbc.decrypt(
key,
encryptedDataAndInitializationVector.encryptedData,
encryptedDataAndInitializationVector.initilizationVector
)
plainText == decrypted.toHexString()
}
}
@Test
fun testCbcDecryption() {
assertTrue {
val key = "4278b840fb44aaa757c1bf04acbe1a3e"
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val aesCbc =
AesCbc(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initializationVector = iv.hexStringToUByteArray())
aesCbc.addData(cipherText.hexStringToUByteArray())
val decrypted = aesCbc.decrypt()
println("Decrypted: ${decrypted.toHexString()}")
expectedPlainText == decrypted.toHexString()
}
}
@Test
fun testDecryptionApi() {
assertTrue {
val key = "4278b840fb44aaa757c1bf04acbe1a3e"
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val decrypted = AesCbc.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), iv.hexStringToUByteArray())
println("Decrypted: ${decrypted.toHexString()}")
expectedPlainText == decrypted.toHexString()
}
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.symmetric
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
import com.ionspin.kotlin.crypto.util.toHexString
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 21-Sep-2019
*/
@ExperimentalUnsignedTypes
class AesCtrTest {
@Test
fun testCtrEncryption() {
assertTrue {
val key = "2b7e151628aed2a6abf7158809cf4f3c"
val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
val plaintext =
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val expectedCipherText =
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val aesCtr = AesCtr(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initialCounter = ic.hexStringToUByteArray())
aesCtr.addData(
plaintext.hexStringToUByteArray()
)
val encrypted = aesCtr.encrypt()
println("Encrypted: ${encrypted.encryptedData.toHexString()}")
expectedCipherText == encrypted.encryptedData.toHexString() &&
ic == encrypted.initialCounter.toHexString()
}
}
@Test
fun testEncryptionApi() {
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
val key = AesKey.Aes128Key(keyString)
val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val encryptedDataAndInitializationVector = AesCtr.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCtr.decrypt(
key,
encryptedDataAndInitializationVector.encryptedData,
encryptedDataAndInitializationVector.initialCounter
)
assertTrue {
plainText == decrypted.toHexString()
}
}
@Test
fun testCtrDecryption() {
assertTrue {
val key = "2b7e151628aed2a6abf7158809cf4f3c"
val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
val cipherText =
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val expectedPlainText =
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val aesCtr = AesCtr(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initialCounter = ic.hexStringToUByteArray())
aesCtr.addData(cipherText.hexStringToUByteArray())
val decrypted = aesCtr.decrypt()
println("Decrypted: ${decrypted.toHexString()}")
expectedPlainText == decrypted.toHexString()
}
}
@Test
fun testCtrDecryptionApi() {
assertTrue {
val key = "2b7e151628aed2a6abf7158809cf4f3c"
val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
val cipherText =
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val expectedPlainText =
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val decrypted = AesCtr.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), ic.hexStringToUByteArray())
println("Decrypted: ${decrypted.toHexString()}")
expectedPlainText == decrypted.toHexString()
}
}
}

View File

@ -0,0 +1,269 @@
package com.ionspin.kotlin.crypto.symmetric
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 10/Sep/2019
*/
@ExperimentalUnsignedTypes
class AesTest {
val irrelevantKey = "01234567890123345678901234567890"
val irrelevantInput = UByteArray(16) { 0U }
@Test
fun testSubBytes() {
val fakeState = arrayOf(
ubyteArrayOf(0x53U, 0U, 0U, 0U),
ubyteArrayOf(0U, 0U, 0U, 0U),
ubyteArrayOf(0U, 0U, 0U, 0U),
ubyteArrayOf(0U, 0U, 0U, 0U)
)
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state)
aes.subBytes()
assertTrue {
aes.state[0][0] == 0xEDU.toUByte()
}
}
@Test
fun testShiftRows() {
val fakeState = arrayOf(
ubyteArrayOf(0U, 1U, 2U, 3U),
ubyteArrayOf(0U, 1U, 2U, 3U),
ubyteArrayOf(0U, 1U, 2U, 3U),
ubyteArrayOf(0U, 1U, 2U, 3U)
)
val expectedState = arrayOf(
ubyteArrayOf(0U, 1U, 2U, 3U),
ubyteArrayOf(1U, 2U, 3U, 0U),
ubyteArrayOf(2U, 3U, 0U, 1U),
ubyteArrayOf(3U, 0U, 1U, 2U)
)
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state)
aes.shiftRows()
assertTrue {
aes.state.contentDeepEquals(expectedState)
}
}
@Test
fun testGaloisMultiply() {
//Samples from FIPS-197
assertTrue {
val a = 0x57U
val b = 0x83U
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val c = aes.galoisFieldMultiply(a.toUByte(), b.toUByte())
c == 0xC1U.toUByte()
}
assertTrue {
val a = 0x57U
val b = 0x13U
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val c = aes.galoisFieldMultiply(a.toUByte(), b.toUByte())
c == 0xFEU.toUByte()
}
}
@Test
fun testMixColumns() {
//Test vectors from wikipedia
val fakeState = arrayOf(
ubyteArrayOf(0xdbU, 0xf2U, 0x01U, 0xc6U),
ubyteArrayOf(0x13U, 0x0aU, 0x01U, 0xc6U),
ubyteArrayOf(0x53U, 0x22U, 0x01U, 0xc6U),
ubyteArrayOf(0x45U, 0x5cU, 0x01U, 0xc6U)
)
val expectedState = arrayOf(
ubyteArrayOf(0x8eU, 0x9fU, 0x01U, 0xc6U),
ubyteArrayOf(0x4dU, 0xdcU, 0x01U, 0xc6U),
ubyteArrayOf(0xa1U, 0x58U, 0x01U, 0xc6U),
ubyteArrayOf(0xbcU, 0x9dU, 0x01U, 0xc6U)
)
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state)
aes.mixColumns()
assertTrue {
aes.state.contentDeepEquals(expectedState)
}
}
@Test
fun testKeyExpansion() {
assertTrue {
val key = "2b7e151628aed2a6abf7158809cf4f3c"
val expectedExpandedKey = uintArrayOf(
// @formatter:off
0x2b7e1516U, 0x28aed2a6U, 0xabf71588U, 0x09cf4f3cU, 0xa0fafe17U, 0x88542cb1U,
0x23a33939U, 0x2a6c7605U, 0xf2c295f2U, 0x7a96b943U, 0x5935807aU, 0x7359f67fU,
0x3d80477dU, 0x4716fe3eU, 0x1e237e44U, 0x6d7a883bU, 0xef44a541U, 0xa8525b7fU,
0xb671253bU, 0xdb0bad00U, 0xd4d1c6f8U, 0x7c839d87U, 0xcaf2b8bcU, 0x11f915bcU,
0x6d88a37aU, 0x110b3efdU, 0xdbf98641U, 0xca0093fdU, 0x4e54f70eU, 0x5f5fc9f3U,
0x84a64fb2U, 0x4ea6dc4fU, 0xead27321U, 0xb58dbad2U, 0x312bf560U, 0x7f8d292fU,
0xac7766f3U, 0x19fadc21U, 0x28d12941U, 0x575c006eU, 0xd014f9a8U, 0xc9ee2589U,
0xe13f0cc8U, 0xb6630ca6U
// @formatter:on
).toTypedArray()
val aes = Aes(AesKey.Aes128Key(key), irrelevantInput)
val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8))
}
}.toTypedArray()
expectedExpandedKey.contentEquals(result)
}
assertTrue {
val key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"
val expectedExpandedKey = uintArrayOf(
// @formatter:off
0x8e73b0f7U, 0xda0e6452U, 0xc810f32bU, 0x809079e5U, 0x62f8ead2U, 0x522c6b7bU,
0xfe0c91f7U, 0x2402f5a5U, 0xec12068eU, 0x6c827f6bU, 0x0e7a95b9U, 0x5c56fec2U, 0x4db7b4bdU, 0x69b54118U,
0x85a74796U, 0xe92538fdU, 0xe75fad44U, 0xbb095386U, 0x485af057U, 0x21efb14fU, 0xa448f6d9U, 0x4d6dce24U,
0xaa326360U, 0x113b30e6U, 0xa25e7ed5U, 0x83b1cf9aU, 0x27f93943U, 0x6a94f767U, 0xc0a69407U, 0xd19da4e1U,
0xec1786ebU, 0x6fa64971U, 0x485f7032U, 0x22cb8755U, 0xe26d1352U, 0x33f0b7b3U, 0x40beeb28U, 0x2f18a259U,
0x6747d26bU, 0x458c553eU, 0xa7e1466cU, 0x9411f1dfU, 0x821f750aU, 0xad07d753U, 0xca400538U, 0x8fcc5006U,
0x282d166aU, 0xbc3ce7b5U, 0xe98ba06fU, 0x448c773cU, 0x8ecc7204U, 0x01002202U
// @formatter:on
).toTypedArray()
val aes = Aes(AesKey.Aes192Key(key), irrelevantInput)
val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8))
}
}.toTypedArray()
expectedExpandedKey.contentEquals(result)
}
assertTrue {
val key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"
val expectedExpandedKey = uintArrayOf(
// @formatter:off
0x603deb10U, 0x15ca71beU, 0x2b73aef0U, 0x857d7781U, 0x1f352c07U, 0x3b6108d7U, 0x2d9810a3U, 0x0914dff4U,
0x9ba35411U, 0x8e6925afU, 0xa51a8b5fU, 0x2067fcdeU, 0xa8b09c1aU, 0x93d194cdU, 0xbe49846eU, 0xb75d5b9aU,
0xd59aecb8U, 0x5bf3c917U, 0xfee94248U, 0xde8ebe96U, 0xb5a9328aU, 0x2678a647U, 0x98312229U, 0x2f6c79b3U,
0x812c81adU, 0xdadf48baU, 0x24360af2U, 0xfab8b464U, 0x98c5bfc9U, 0xbebd198eU, 0x268c3ba7U, 0x09e04214U,
0x68007bacU, 0xb2df3316U, 0x96e939e4U, 0x6c518d80U, 0xc814e204U, 0x76a9fb8aU, 0x5025c02dU, 0x59c58239U,
0xde136967U, 0x6ccc5a71U, 0xfa256395U, 0x9674ee15U, 0x5886ca5dU, 0x2e2f31d7U, 0x7e0af1faU, 0x27cf73c3U,
0x749c47abU, 0x18501ddaU, 0xe2757e4fU, 0x7401905aU, 0xcafaaae3U, 0xe4d59b34U, 0x9adf6aceU, 0xbd10190dU,
0xfe4890d1U, 0xe6188d0bU, 0x046df344U, 0x706c631eU
// @formatter:on
).toTypedArray()
val aes = Aes(AesKey.Aes256Key(key), irrelevantInput)
val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8))
}
}.toTypedArray()
expectedExpandedKey.contentEquals(result)
}
}
@Test
fun testEncryption() {
val input = "3243f6a8885a308d313198a2e0370734"
val key = "2b7e151628aed2a6abf7158809cf4f3c"
val expectedResult = "3925841d02dc09fbdc118597196a0b32"
val aes = Aes(AesKey.Aes128Key(key), input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
val result = aes.encrypt()
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
}
@Test
fun testEncryptionAndDecryption() {
assertTrue {
val input = "3243f6a8885a308d313198a2e0370734"
val key = "2b7e151628aed2a6abf7158809cf4f3c"
val expectedResult = "3925841d02dc09fbdc118597196a0b32"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val aes = Aes(AesKey.Aes128Key(key), original)
val encrypted = aes.encrypt()
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted)
decrypted.contentEquals(original)
}
assertTrue {
val input = "00112233445566778899aabbccddeeff"
val key = "000102030405060708090a0b0c0d0e0f"
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val aes = Aes(AesKey.Aes128Key(key), original)
val encrypted = aes.encrypt()
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val aesDec = Aes(AesKey.Aes128Key(key), encrypted)
val decrypted = aesDec.decrypt()
assertTrue {
aesDec.expandedKey.contentDeepEquals(aes.expandedKey)
}
decrypted.contentEquals(original)
}
assertTrue {
val input = "00112233445566778899aabbccddeeff"
val key = "000102030405060708090a0b0c0d0e0f"
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val encrypted = Aes.encrypt(AesKey.Aes128Key(key), original)
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted)
decrypted.contentEquals(original)
}
assertTrue {
val input = "00112233445566778899aabbccddeeff"
val key = "000102030405060708090a0b0c0d0e0f1011121314151617"
val expectedResult = "dda97ca4864cdfe06eaf70a0ec0d7191"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val encrypted = Aes.encrypt(AesKey.Aes192Key(key), original)
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val decrypted = Aes.decrypt(AesKey.Aes192Key(key), encrypted)
decrypted.contentEquals(original)
}
assertTrue {
val input = "00112233445566778899aabbccddeeff"
val key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
val expectedResult = "8ea2b7ca516745bfeafc49904b496089"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val encrypted = Aes.encrypt(AesKey.Aes256Key(key), original)
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val decrypted = Aes.decrypt(AesKey.Aes256Key(key), encrypted)
decrypted.contentEquals(original)
}
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.util
import kotlinx.coroutines.CoroutineScope
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 20-Jul-2019
*/
expect fun testBlocking(block : suspend () -> Unit)

View File

@ -0,0 +1,109 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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 com.ionspin.kotlin.crypto.util
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 17-Jul-2019
*/
@ExperimentalUnsignedTypes
class UtilTest {
@Test
fun testSlicer() {
val array = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)
val chunked = array.chunked(2)
assertTrue {
chunked.size == 9 && chunked[8][0] == 17
}
}
@Test
fun testUIntToBigEndianArray() {
assertTrue {
val original = 1U
val converted = original.toBigEndianUByteArray()
converted[0] = 1U
true
}
assertTrue {
val original = 0xAABBCCDDU
val converted = original.toBigEndianUByteArray()
converted[0] == 0xAAU.toUByte() &&
converted[1] == 0xBBU.toUByte() &&
converted[2] == 0xCCU.toUByte() &&
converted[3] == 0xDDU.toUByte()
}
}
@Test
fun testUIntToLittleEndianArray() {
assertTrue {
val original = 1U
val converted = original.toLittleEndianTypedUByteArray()
converted[3] = 1U
true
}
assertTrue {
val original = 0xAABBCCDDU
val converted = original.toLittleEndianTypedUByteArray()
converted[0] == 0xDDU.toUByte() &&
converted[1] == 0xCCU.toUByte() &&
converted[2] == 0xBBU.toUByte() &&
converted[3] == 0xAAU.toUByte()
}
assertTrue {
val original = 123456U
val converted = original.toLittleEndianTypedUByteArray()
converted[0] == 0x40U.toUByte() &&
converted[1] == 0xE2U.toUByte() &&
converted[2] == 0x01U.toUByte() &&
converted[3] == 0x00U.toUByte()
}
}
@Test
fun testFromBigEndianByteArrayToLong() {
assertTrue {
val ubyteArray = ubyteArrayOf(0xA1U, 0xA2U, 0xB1U, 0xB2U, 0xC1U, 0xC2U, 0xD1U, 0xD2U).toTypedArray()
val expected = 0xA1A2B1B2C1C2D1D2U
val reconstructed = ubyteArray.fromBigEndianArrayToULong();
reconstructed == expected
}
}
@Test
fun testFromLittleEndianByteArrayToLong() {
assertTrue {
val ubyteArray = ubyteArrayOf(0xA1U, 0xA2U, 0xB1U, 0xB2U, 0xC1U, 0xC2U, 0xD1U, 0xD2U).toTypedArray()
val expected = 0xD2D1C2C1B2B1A2A1UL
val reconstructed = ubyteArray.fromLittleEndianArrayToULong();
reconstructed == expected
}
}
}

View File

@ -186,6 +186,7 @@ kotlin {
implementation(kotlin(Deps.Common.test)) implementation(kotlin(Deps.Common.test))
implementation(Deps.Common.coroutines) implementation(Deps.Common.coroutines)
implementation(Deps.Common.kotlinBigNum) implementation(Deps.Common.kotlinBigNum)
implementation(project(":multiplatform-crypto-api"))
} }
} }
val commonTest by getting { val commonTest by getting {

View File

@ -0,0 +1,14 @@
package com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bPure
import com.ionspin.kotlin.crypto.hash.sha.Sha256Pure
import com.ionspin.kotlin.crypto.hash.sha.Sha512Pure
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 24-May-2020
*/
typealias Blake2bStateless = Blake2bPure.Companion
typealias Sha256Stateless = Sha256Pure.Companion
typealias Sha512Stateless = Sha512Pure.Companion

View File

@ -19,9 +19,6 @@ package com.ionspin.kotlin.crypto.hash.blake2b
import com.ionspin.kotlin.bignum.integer.BigInteger import com.ionspin.kotlin.bignum.integer.BigInteger
import com.ionspin.kotlin.bignum.integer.toBigInteger import com.ionspin.kotlin.bignum.integer.toBigInteger
import com.ionspin.kotlin.crypto.* import com.ionspin.kotlin.crypto.*
import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdatableHash
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.util.rotateRight import com.ionspin.kotlin.crypto.util.rotateRight
/** /**
@ -31,9 +28,9 @@ import com.ionspin.kotlin.crypto.util.rotateRight
*/ */
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class Blake2b(val key: UByteArray? = null, val hashLength: Int = 64) : UpdatableHash { class Blake2bPure(val key: UByteArray? = null, val hashLength: Int = 64) : Blake2b {
companion object : StatelessHash { companion object : Blake2bStatelessInterface {
//Hack start //Hack start
//If this line is not included konanc 1.4-M1 fails to link because it cant find ByteArray which is //If this line is not included konanc 1.4-M1 fails to link because it cant find ByteArray which is
//a backing class for UByteArray //a backing class for UByteArray
@ -255,7 +252,7 @@ class Blake2b(val key: UByteArray? = null, val hashLength: Int = 64) : Updatable
requestedHashLenght requestedHashLenght
) )
override val MAX_HASH_BYTES: Int = Blake2b.MAX_HASH_BYTES override val MAX_HASH_BYTES: Int = Blake2bPure.MAX_HASH_BYTES
var h = iv.copyOf() var h = iv.copyOf()
var counter = BigInteger.ZERO var counter = BigInteger.ZERO

View File

@ -16,7 +16,6 @@
package com.ionspin.kotlin.crypto.hash.sha package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.hash.StatelessHash import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdatableHash import com.ionspin.kotlin.crypto.hash.UpdatableHash
import com.ionspin.kotlin.crypto.util.rotateRight import com.ionspin.kotlin.crypto.util.rotateRight
@ -30,12 +29,12 @@ import com.ionspin.kotlin.crypto.util.rotateRight
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class Sha256 : UpdatableHash { class Sha256Pure : Sha256 {
override val MAX_HASH_BYTES: Int = 32 override val MAX_HASH_BYTES: Int = 32
companion object : StatelessHash { companion object : StatelessSha256 {
const val BLOCK_SIZE = 512 const val BLOCK_SIZE = 512
const val BLOCK_SIZE_IN_BYTES = 64 const val BLOCK_SIZE_IN_BYTES = 64
const val UINT_MASK = 0xFFFFFFFFU const val UINT_MASK = 0xFFFFFFFFU

View File

@ -16,7 +16,6 @@
package com.ionspin.kotlin.crypto.hash.sha package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.hash.StatelessHash import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdatableHash import com.ionspin.kotlin.crypto.hash.UpdatableHash
import com.ionspin.kotlin.crypto.util.rotateRight import com.ionspin.kotlin.crypto.util.rotateRight
@ -28,11 +27,11 @@ import com.ionspin.kotlin.crypto.util.rotateRight
*/ */
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class Sha512 : UpdatableHash { class Sha512Pure : Sha512 {
override val MAX_HASH_BYTES: Int = 32 override val MAX_HASH_BYTES: Int = 32
companion object : StatelessHash { companion object : StatelessSha512 {
const val BLOCK_SIZE = 1024 const val BLOCK_SIZE = 1024
const val BLOCK_SIZE_IN_BYTES = 128 const val BLOCK_SIZE_IN_BYTES = 128
const val CHUNK_SIZE = 80 const val CHUNK_SIZE = 80

View File

@ -1,406 +1,10 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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.
*/
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package com.ionspin.kotlin.crypto.keyderivation.argon2 package com.ionspin.kotlin.crypto.keyderivation.argon2
import com.ionspin.kotlin.bignum.integer.toBigInteger
import com.ionspin.kotlin.crypto.SRNG
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
import com.ionspin.kotlin.crypto.keyderivation.KeyDerivationFunction import com.ionspin.kotlin.crypto.keyderivation.KeyDerivationFunction
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.argonBlake2bArbitraryLenghtHash
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.compressionFunctionG
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
import com.ionspin.kotlin.crypto.util.*
/** /**
* Created by Ugljesa Jovanovic * Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com * ugljesa.jovanovic@ionspin.com
* on 16-May-2020 * on 24-May-2020
*/ */
interface Argon2 : KeyDerivationFunction
enum class ArgonType(val typeId: Int) {
Argon2d(0), Argon2i(1), Argon2id(2)
}
data class SegmentPosition(
val iteration: Int,
val lane: Int,
val slice: Int
)
data class ArgonResult(
val hashBytes: UByteArray,
val salt: UByteArray
) {
val hashString by lazy { hashBytes.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
val saltString by lazy { salt.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
}
@ExperimentalStdlibApi
class Argon2(
private val password: UByteArray,
private val salt: UByteArray = ubyteArrayOf(),
private val parallelism: Int = 1,
private val tagLength: UInt = 64U,
requestedMemorySize: UInt = 0U,
private val numberOfIterations: Int = 1,
private val key: UByteArray = ubyteArrayOf(),
private val associatedData: UByteArray = ubyteArrayOf(),
private val argonType: ArgonType = ArgonType.Argon2id
) : KeyDerivationFunction {
companion object {
fun derive(
password: String,
salt: String? = null,
key: String,
associatedData: String,
parallelism: Int = 16,
tagLength: Int = 64,
memory: Int = 4096,
numberOfIterations: Int = 10,
): ArgonResult {
val salt = SRNG.getRandomBytes(64)
val argon = Argon2(
password.encodeToByteArray().toUByteArray(),
salt,
parallelism,
tagLength.toUInt(),
memory.toUInt(),
numberOfIterations,
key.encodeToByteArray().toUByteArray(),
associatedData.encodeToByteArray().toUByteArray(),
ArgonType.Argon2id
)
val resultArray = argon.derive()
return ArgonResult(resultArray, salt)
}
}
constructor(
password: String,
salt: String = "",
parallelism: Int = 1,
tagLength: UInt = 64U,
requestedMemorySize: UInt = 0U,
numberOfIterations: Int = 10,
key: String = "",
associatedData: String = "",
argonType: ArgonType = ArgonType.Argon2id
) : this(
password.encodeToByteArray().toUByteArray(),
salt.encodeToByteArray().toUByteArray(),
parallelism,
tagLength,
requestedMemorySize,
numberOfIterations,
key.encodeToByteArray().toUByteArray(),
associatedData.encodeToByteArray().toUByteArray(),
argonType
)
//We support only the latest version
private val versionNumber: UInt = 0x13U
//Use either requested memory size, or default, or throw exception if the requested amount is less than 8*parallelism
private val memorySize = if (requestedMemorySize == 0U) {
((8 * parallelism) * 2).toUInt()
} else {
requestedMemorySize
}
private val blockCount = (memorySize / (4U * parallelism.toUInt())) * (4U * parallelism.toUInt())
private val columnCount = (blockCount / parallelism.toUInt()).toInt()
private val segmentLength = columnCount / 4
private val useIndependentAddressing = argonType == ArgonType.Argon2id || argonType == ArgonType.Argon2i
// State
private val matrix: ArgonMatrix
init {
matrix = ArgonMatrix(columnCount, parallelism)
validateArgonParameters(
password,
salt,
parallelism,
tagLength,
requestedMemorySize,
numberOfIterations,
key,
associatedData,
argonType
)
}
private fun populateAddressBlock(
iteration: Int,
slice: Int,
lane: Int,
addressBlock: ArgonBlockPointer,
addressCounter: ULong
): ArgonBlockPointer {
//Calculate first pass
val zeroesBlock = ArgonBlock()
val firstPass = compressionFunctionG(
zeroesBlock.getBlockPointer(),
ArgonBlock(iteration.toULong().toLittleEndianUByteArray() +
lane.toULong().toLittleEndianUByteArray() +
slice.toULong().toLittleEndianUByteArray() +
blockCount.toULong().toLittleEndianUByteArray() +
numberOfIterations.toULong().toLittleEndianUByteArray() +
argonType.typeId.toULong().toLittleEndianUByteArray() +
addressCounter.toLittleEndianUByteArray() +
UByteArray(968) { 0U }
).getBlockPointer(),
addressBlock,
false
)
val secondPass = compressionFunctionG(
zeroesBlock.getBlockPointer(),
firstPass,
firstPass,
false
)
return secondPass
}
private fun computeReferenceBlockIndexes(
iteration: Int,
slice: Int,
lane: Int,
column: Int,
addressBlockPointer: ArgonBlockPointer?
): Pair<Int, Int> {
val segmentIndex = (column % segmentLength)
val independentIndex = segmentIndex % 128 // 128 is the number of addresses in address block
val (j1, j2) = when (argonType) {
ArgonType.Argon2d -> {
val previousBlockStart = if (column == 0) {
matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix.getBlockPointer(lane, column - 1)
}
val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
ArgonType.Argon2i -> {
val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
Pair(first32Bit, second32Bit)
}
ArgonType.Argon2id -> {
if (iteration == 0 && (slice == 0 || slice == 1)) {
val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
Pair(first32Bit, second32Bit)
} else {
val previousBlockStart = if (column == 0) {
matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix.getBlockPointer(lane, column - 1)
}
val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
}
}
//If this is first iteration and first slice, block is taken from the current lane
val l = if (iteration == 0 && slice == 0) {
lane
} else {
(j2.toBigInteger() % parallelism).intValue()
}
val referenceAreaSize = if (iteration == 0) {
if (slice == 0) {
//All indices except the previous
segmentIndex - 1
} else {
if (lane == l) {
//Same lane
column - 1
} else {
slice * (columnCount / 4) + if (segmentIndex == 0) { // Check if column is first block of the SEGMENT
-1
} else {
0
}
}
}
} else {
if (lane == l) {
columnCount - (columnCount / 4) + (segmentIndex - 1)
} else {
columnCount - (columnCount / 4) + if (segmentIndex == 0) {
-1
} else {
0
}
}
}
val x = (j1.toULong() * j1) shr 32
val y = (referenceAreaSize.toULong() * x) shr 32
val z = referenceAreaSize.toULong() - 1U - y
val startPosition = if (iteration == 0) {
0
} else {
if (slice == 3) {
0
} else {
(slice + 1) * segmentLength
}
}
val absolutePosition = (startPosition + z.toInt()) % columnCount
return Pair(l, absolutePosition)
}
override fun derive(): UByteArray {
val blakeInput = parallelism.toUInt().toLittleEndianUByteArray() +
tagLength.toLittleEndianUByteArray() +
memorySize.toLittleEndianUByteArray() +
numberOfIterations.toUInt().toLittleEndianUByteArray() +
versionNumber.toLittleEndianUByteArray() +
argonType.typeId.toUInt().toLittleEndianUByteArray() +
password.size.toUInt().toLittleEndianUByteArray() + password +
salt.size.toUInt().toLittleEndianUByteArray() + salt +
key.size.toUInt().toLittleEndianUByteArray() + key +
associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData
val h0 = Blake2b.digest(
blakeInput
)
//Compute B[i][0]
for (i in 0 until parallelism) {
matrix.setBlockAt(i, 0,
argonBlake2bArbitraryLenghtHash(
(h0 + 0.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
1024U
)
)
}
//Compute B[i][1]
for (i in 0 until parallelism) {
matrix.setBlockAt(i, 1,
argonBlake2bArbitraryLenghtHash(
(h0 + 1.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
1024U
)
)
}
//Run all iterations over all lanes and all segments
executeArgonWithSingleThread()
val acc = ArgonBlock(matrix.getBlockAt(0, columnCount - 1))
val accPointer = acc.getBlockPointer()
for (i in 1 until parallelism) {
accPointer.xorInplaceWith(matrix.getBlockPointer(i, columnCount - 1))
}
//Hash the xored last blocks
val hash = argonBlake2bArbitraryLenghtHash(acc.storage, tagLength)
matrix.clearMatrix()
return hash
}
private fun executeArgonWithSingleThread() {
for (iteration in 0 until numberOfIterations) {
for (slice in 0 until 4) {
for (lane in 0 until parallelism) {
val segmentPosition = SegmentPosition(iteration, lane, slice)
processSegment(segmentPosition)
}
}
}
}
private fun processSegment(segmentPosition: SegmentPosition) {
val iteration = segmentPosition.iteration
val slice = segmentPosition.slice
val lane = segmentPosition.lane
var addressBlock: ArgonBlockPointer? = null
var addressCounter = 1UL //Starts from 1 in each segment as defined by the spec
//Generate initial segment address block
if (useIndependentAddressing) {
addressBlock = ArgonBlock().getBlockPointer()
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock, addressCounter)
addressCounter++
}
val startColumn = if (iteration == 0 && slice == 0) {
2
} else {
slice * segmentLength
}
for (column in startColumn until (slice + 1) * segmentLength) {
val segmentIndex = column - (slice * segmentLength)
//Each address block contains 128 addresses, and we use one per iteration,
//so once we do 128 iterations we need to calculate a new address block
if (useIndependentAddressing && segmentIndex != 0 && segmentIndex % 128 == 0) {
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock!!, addressCounter)
addressCounter++
}
val previousColumn = if (column == 0) {
columnCount - 1
} else {
column - 1
}
val (l, z) = computeReferenceBlockIndexes(
iteration,
slice,
lane,
column,
addressBlock
)
matrix.setBlockAt(lane, column,
compressionFunctionG(
matrix.getBlockPointer(lane, previousColumn),
matrix.getBlockPointer(l,z),
matrix.getBlockPointer(lane,column),
true
).getAsUByteArray()
)
}
}
}

View File

@ -0,0 +1,405 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* 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.
*/
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package com.ionspin.kotlin.crypto.keyderivation.argon2
import com.ionspin.kotlin.bignum.integer.toBigInteger
import com.ionspin.kotlin.crypto.SRNG
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bStateless
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.argonBlake2bArbitraryLenghtHash
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.compressionFunctionG
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
import com.ionspin.kotlin.crypto.util.*
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 16-May-2020
*/
enum class ArgonType(val typeId: Int) {
Argon2d(0), Argon2i(1), Argon2id(2)
}
data class SegmentPosition(
val iteration: Int,
val lane: Int,
val slice: Int
)
data class ArgonResult(
val hashBytes: UByteArray,
val salt: UByteArray
) {
val hashString by lazy { hashBytes.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
val saltString by lazy { salt.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
}
@ExperimentalStdlibApi
class Argon2Pure(
private val password: UByteArray,
private val salt: UByteArray = ubyteArrayOf(),
private val parallelism: Int = 1,
private val tagLength: UInt = 64U,
requestedMemorySize: UInt = 0U,
private val numberOfIterations: Int = 1,
private val key: UByteArray = ubyteArrayOf(),
private val associatedData: UByteArray = ubyteArrayOf(),
private val argonType: ArgonType = ArgonType.Argon2id
) : Argon2 {
companion object {
fun derive(
password: String,
salt: String? = null,
key: String,
associatedData: String,
parallelism: Int = 16,
tagLength: Int = 64,
memory: Int = 4096,
numberOfIterations: Int = 10,
): ArgonResult {
val salt = SRNG.getRandomBytes(64)
val argon = Argon2Pure(
password.encodeToByteArray().toUByteArray(),
salt,
parallelism,
tagLength.toUInt(),
memory.toUInt(),
numberOfIterations,
key.encodeToByteArray().toUByteArray(),
associatedData.encodeToByteArray().toUByteArray(),
ArgonType.Argon2id
)
val resultArray = argon.derive()
return ArgonResult(resultArray, salt)
}
}
constructor(
password: String,
salt: String = "",
parallelism: Int = 1,
tagLength: UInt = 64U,
requestedMemorySize: UInt = 0U,
numberOfIterations: Int = 10,
key: String = "",
associatedData: String = "",
argonType: ArgonType = ArgonType.Argon2id
) : this(
password.encodeToByteArray().toUByteArray(),
salt.encodeToByteArray().toUByteArray(),
parallelism,
tagLength,
requestedMemorySize,
numberOfIterations,
key.encodeToByteArray().toUByteArray(),
associatedData.encodeToByteArray().toUByteArray(),
argonType
)
//We support only the latest version
private val versionNumber: UInt = 0x13U
//Use either requested memory size, or default, or throw exception if the requested amount is less than 8*parallelism
private val memorySize = if (requestedMemorySize == 0U) {
((8 * parallelism) * 2).toUInt()
} else {
requestedMemorySize
}
private val blockCount = (memorySize / (4U * parallelism.toUInt())) * (4U * parallelism.toUInt())
private val columnCount = (blockCount / parallelism.toUInt()).toInt()
private val segmentLength = columnCount / 4
private val useIndependentAddressing = argonType == ArgonType.Argon2id || argonType == ArgonType.Argon2i
// State
private val matrix: ArgonMatrix
init {
matrix = ArgonMatrix(columnCount, parallelism)
validateArgonParameters(
password,
salt,
parallelism,
tagLength,
requestedMemorySize,
numberOfIterations,
key,
associatedData,
argonType
)
}
private fun populateAddressBlock(
iteration: Int,
slice: Int,
lane: Int,
addressBlock: ArgonBlockPointer,
addressCounter: ULong
): ArgonBlockPointer {
//Calculate first pass
val zeroesBlock = ArgonBlock()
val firstPass = compressionFunctionG(
zeroesBlock.getBlockPointer(),
ArgonBlock(iteration.toULong().toLittleEndianUByteArray() +
lane.toULong().toLittleEndianUByteArray() +
slice.toULong().toLittleEndianUByteArray() +
blockCount.toULong().toLittleEndianUByteArray() +
numberOfIterations.toULong().toLittleEndianUByteArray() +
argonType.typeId.toULong().toLittleEndianUByteArray() +
addressCounter.toLittleEndianUByteArray() +
UByteArray(968) { 0U }
).getBlockPointer(),
addressBlock,
false
)
val secondPass = compressionFunctionG(
zeroesBlock.getBlockPointer(),
firstPass,
firstPass,
false
)
return secondPass
}
private fun computeReferenceBlockIndexes(
iteration: Int,
slice: Int,
lane: Int,
column: Int,
addressBlockPointer: ArgonBlockPointer?
): Pair<Int, Int> {
val segmentIndex = (column % segmentLength)
val independentIndex = segmentIndex % 128 // 128 is the number of addresses in address block
val (j1, j2) = when (argonType) {
ArgonType.Argon2d -> {
val previousBlockStart = if (column == 0) {
matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix.getBlockPointer(lane, column - 1)
}
val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
ArgonType.Argon2i -> {
val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
Pair(first32Bit, second32Bit)
}
ArgonType.Argon2id -> {
if (iteration == 0 && (slice == 0 || slice == 1)) {
val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
Pair(first32Bit, second32Bit)
} else {
val previousBlockStart = if (column == 0) {
matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix.getBlockPointer(lane, column - 1)
}
val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
}
}
//If this is first iteration and first slice, block is taken from the current lane
val l = if (iteration == 0 && slice == 0) {
lane
} else {
(j2.toBigInteger() % parallelism).intValue()
}
val referenceAreaSize = if (iteration == 0) {
if (slice == 0) {
//All indices except the previous
segmentIndex - 1
} else {
if (lane == l) {
//Same lane
column - 1
} else {
slice * (columnCount / 4) + if (segmentIndex == 0) { // Check if column is first block of the SEGMENT
-1
} else {
0
}
}
}
} else {
if (lane == l) {
columnCount - (columnCount / 4) + (segmentIndex - 1)
} else {
columnCount - (columnCount / 4) + if (segmentIndex == 0) {
-1
} else {
0
}
}
}
val x = (j1.toULong() * j1) shr 32
val y = (referenceAreaSize.toULong() * x) shr 32
val z = referenceAreaSize.toULong() - 1U - y
val startPosition = if (iteration == 0) {
0
} else {
if (slice == 3) {
0
} else {
(slice + 1) * segmentLength
}
}
val absolutePosition = (startPosition + z.toInt()) % columnCount
return Pair(l, absolutePosition)
}
override fun derive(): UByteArray {
val blakeInput = parallelism.toUInt().toLittleEndianUByteArray() +
tagLength.toLittleEndianUByteArray() +
memorySize.toLittleEndianUByteArray() +
numberOfIterations.toUInt().toLittleEndianUByteArray() +
versionNumber.toLittleEndianUByteArray() +
argonType.typeId.toUInt().toLittleEndianUByteArray() +
password.size.toUInt().toLittleEndianUByteArray() + password +
salt.size.toUInt().toLittleEndianUByteArray() + salt +
key.size.toUInt().toLittleEndianUByteArray() + key +
associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData
val h0 = Blake2bStateless.digest(
blakeInput
)
//Compute B[i][0]
for (i in 0 until parallelism) {
matrix.setBlockAt(i, 0,
argonBlake2bArbitraryLenghtHash(
(h0 + 0.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
1024U
)
)
}
//Compute B[i][1]
for (i in 0 until parallelism) {
matrix.setBlockAt(i, 1,
argonBlake2bArbitraryLenghtHash(
(h0 + 1.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
1024U
)
)
}
//Run all iterations over all lanes and all segments
executeArgonWithSingleThread()
val acc = ArgonBlock(matrix.getBlockAt(0, columnCount - 1))
val accPointer = acc.getBlockPointer()
for (i in 1 until parallelism) {
accPointer.xorInplaceWith(matrix.getBlockPointer(i, columnCount - 1))
}
//Hash the xored last blocks
val hash = argonBlake2bArbitraryLenghtHash(acc.storage, tagLength)
matrix.clearMatrix()
return hash
}
private fun executeArgonWithSingleThread() {
for (iteration in 0 until numberOfIterations) {
for (slice in 0 until 4) {
for (lane in 0 until parallelism) {
val segmentPosition = SegmentPosition(iteration, lane, slice)
processSegment(segmentPosition)
}
}
}
}
private fun processSegment(segmentPosition: SegmentPosition) {
val iteration = segmentPosition.iteration
val slice = segmentPosition.slice
val lane = segmentPosition.lane
var addressBlock: ArgonBlockPointer? = null
var addressCounter = 1UL //Starts from 1 in each segment as defined by the spec
//Generate initial segment address block
if (useIndependentAddressing) {
addressBlock = ArgonBlock().getBlockPointer()
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock, addressCounter)
addressCounter++
}
val startColumn = if (iteration == 0 && slice == 0) {
2
} else {
slice * segmentLength
}
for (column in startColumn until (slice + 1) * segmentLength) {
val segmentIndex = column - (slice * segmentLength)
//Each address block contains 128 addresses, and we use one per iteration,
//so once we do 128 iterations we need to calculate a new address block
if (useIndependentAddressing && segmentIndex != 0 && segmentIndex % 128 == 0) {
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock!!, addressCounter)
addressCounter++
}
val previousColumn = if (column == 0) {
columnCount - 1
} else {
column - 1
}
val (l, z) = computeReferenceBlockIndexes(
iteration,
slice,
lane,
column,
addressBlock
)
matrix.setBlockAt(lane, column,
compressionFunctionG(
matrix.getBlockPointer(lane, previousColumn),
matrix.getBlockPointer(l,z),
matrix.getBlockPointer(lane,column),
true
).getAsUByteArray()
)
}
}
}

View File

@ -18,10 +18,8 @@
package com.ionspin.kotlin.crypto.keyderivation.argon2 package com.ionspin.kotlin.crypto.keyderivation.argon2
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bPure
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.BLOCK_SIZE import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.BLOCK_SIZE
import com.ionspin.kotlin.crypto.util.arrayChunked
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToULong
import com.ionspin.kotlin.crypto.util.plus import com.ionspin.kotlin.crypto.util.plus
import com.ionspin.kotlin.crypto.util.rotateRight import com.ionspin.kotlin.crypto.util.rotateRight
@ -101,17 +99,17 @@ object Argon2Utils {
internal fun argonBlake2bArbitraryLenghtHash(input: UByteArray, length: UInt): UByteArray { internal fun argonBlake2bArbitraryLenghtHash(input: UByteArray, length: UInt): UByteArray {
if (length <= 64U) { if (length <= 64U) {
return Blake2b.digest(inputMessage = length + input, hashLength = length.toInt()) return Blake2bPure.digest(inputMessage = length + input, hashLength = length.toInt())
} }
//We can cast to int because UInt even if MAX_VALUE divided by 32 is guaranteed not to overflow //We can cast to int because UInt even if MAX_VALUE divided by 32 is guaranteed not to overflow
val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent to ceil(length/32) - 2 val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent to ceil(length/32) - 2
val v = Array<UByteArray>(numberOf64ByteBlocks) { ubyteArrayOf() } val v = Array<UByteArray>(numberOf64ByteBlocks) { ubyteArrayOf() }
v[0] = Blake2b.digest(length + input) v[0] = Blake2bPure.digest(length + input)
for (i in 1 until numberOf64ByteBlocks) { for (i in 1 until numberOf64ByteBlocks) {
v[i] = Blake2b.digest(v[i - 1]) v[i] = Blake2bPure.digest(v[i - 1])
} }
val remainingPartOfInput = length.toInt() - numberOf64ByteBlocks * 32 val remainingPartOfInput = length.toInt() - numberOf64ByteBlocks * 32
val vLast = Blake2b.digest(v[numberOf64ByteBlocks - 1], hashLength = remainingPartOfInput) val vLast = Blake2bPure.digest(v[numberOf64ByteBlocks - 1], hashLength = remainingPartOfInput)
val concat = val concat =
(v.map { it.copyOfRange(0, 32) }) (v.map { it.copyOfRange(0, 32) })
.plus(listOf(vLast)) .plus(listOf(vLast))

View File

@ -16,11 +16,7 @@
package com.ionspin.kotlin.crypto.parallelization package com.ionspin.kotlin.crypto.parallelization
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
/** /**
* Created by Ugljesa Jovanovic * Created by Ugljesa Jovanovic

View File

@ -17,13 +17,12 @@
package com.ionspin.kotlin.crypto.symmetric package com.ionspin.kotlin.crypto.symmetric
import com.ionspin.kotlin.crypto.SRNG import com.ionspin.kotlin.crypto.SRNG
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.util.xor import com.ionspin.kotlin.crypto.util.xor
/** /**
* Advanced encryption standard with cipher block chaining and PKCS #5 * Advanced encryption standard with cipher block chaining and PKCS #5
* *
* For bulk encryption/decryption use [AesCbc.encrypt] and [AesCbc.decrypt] * For bulk encryption/decryption use [AesCbcPure.encrypt] and [AesCbcPure.decrypt]
* *
* To get an instance of AesCbc and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor] * To get an instance of AesCbc and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
* *
@ -32,7 +31,7 @@ import com.ionspin.kotlin.crypto.util.xor
* on 21-Sep-2019 * on 21-Sep-2019
*/ */
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializationVector: UByteArray? = null) { class AesCbcPure internal constructor(val aesKey: AesKey, val mode: Mode, initializationVector: UByteArray? = null) {
companion object { companion object {
const val BLOCK_BYTES = 16 const val BLOCK_BYTES = 16
@ -40,22 +39,22 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
* Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all * Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
* data call [encrypt] * data call [encrypt]
*/ */
fun createEncryptor(aesKey: AesKey) : AesCbc { fun createEncryptor(aesKey: AesKey) : AesCbcPure {
return AesCbc(aesKey, Mode.ENCRYPT) return AesCbcPure(aesKey, Mode.ENCRYPT)
} }
/** /**
* Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all * Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
* data call [decrypt] * data call [decrypt]
*/ */
fun createDecryptor(aesKey : AesKey) : AesCbc { fun createDecryptor(aesKey : AesKey) : AesCbcPure {
return AesCbc(aesKey, Mode.DECRYPT) return AesCbcPure(aesKey, Mode.DECRYPT)
} }
/** /**
* Bulk encryption, returns encrypted data and a random initialization vector * Bulk encryption, returns encrypted data and a random initialization vector
*/ */
fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitializationVector { fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitializationVector {
val aesCbc = AesCbc(aesKey, Mode.ENCRYPT) val aesCbc = AesCbcPure(aesKey, Mode.ENCRYPT)
aesCbc.addData(data) aesCbc.addData(data)
return aesCbc.encrypt() return aesCbc.encrypt()
} }
@ -64,7 +63,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
* Bulk decryption, returns decrypted data * Bulk decryption, returns decrypted data
*/ */
fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray { fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray {
val aesCbc = AesCbc(aesKey, Mode.DECRYPT, initialCounter) val aesCbc = AesCbcPure(aesKey, Mode.DECRYPT, initialCounter)
aesCbc.addData(data) aesCbc.addData(data)
return aesCbc.decrypt() return aesCbc.decrypt()
} }
@ -199,17 +198,17 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
Mode.ENCRYPT -> { Mode.ENCRYPT -> {
currentOutput = if (currentOutput.isEmpty()) { currentOutput = if (currentOutput.isEmpty()) {
println("IV: $initVector") println("IV: $initVector")
Aes.encrypt(aesKey, data xor initVector) AesPure.encrypt(aesKey, data xor initVector)
} else { } else {
Aes.encrypt(aesKey, data xor currentOutput) AesPure.encrypt(aesKey, data xor currentOutput)
} }
currentOutput currentOutput
} }
Mode.DECRYPT -> { Mode.DECRYPT -> {
if (currentOutput.isEmpty()) { if (currentOutput.isEmpty()) {
currentOutput = Aes.decrypt(aesKey, data) xor initVector currentOutput = AesPure.decrypt(aesKey, data) xor initVector
} else { } else {
currentOutput = Aes.decrypt(aesKey, data) xor previousEncrypted currentOutput = AesPure.decrypt(aesKey, data) xor previousEncrypted
} }
previousEncrypted = data previousEncrypted = data
currentOutput currentOutput

View File

@ -20,15 +20,14 @@ import com.ionspin.kotlin.bignum.Endianness
import com.ionspin.kotlin.bignum.integer.BigInteger import com.ionspin.kotlin.bignum.integer.BigInteger
import com.ionspin.kotlin.bignum.modular.ModularBigInteger import com.ionspin.kotlin.bignum.modular.ModularBigInteger
import com.ionspin.kotlin.crypto.SRNG import com.ionspin.kotlin.crypto.SRNG
import com.ionspin.kotlin.crypto.util.chunked import com.ionspin.kotlin.crypto.symmetric.AesCtrPure.Companion.encrypt
import com.ionspin.kotlin.crypto.symmetric.AesCtr.Companion.encrypt
import com.ionspin.kotlin.crypto.util.xor import com.ionspin.kotlin.crypto.util.xor
/** /**
* *
* Advanced encryption standard with counter mode * Advanced encryption standard with counter mode
* *
* For bulk encryption/decryption use [AesCtr.encrypt] and [AesCtr.decrypt] * For bulk encryption/decryption use [AesCtrPure.encrypt] and [AesCtrPure.decrypt]
* *
* To get an instance of AesCtr and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor] * To get an instance of AesCtr and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
* *
@ -37,7 +36,7 @@ import com.ionspin.kotlin.crypto.util.xor
* on 22-Sep-2019 * on 22-Sep-2019
*/ */
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCounter: UByteArray? = null) { class AesCtrPure internal constructor(val aesKey: AesKey, val mode: Mode, initialCounter: UByteArray? = null) {
companion object { companion object {
const val BLOCK_BYTES = 16 const val BLOCK_BYTES = 16
@ -47,21 +46,21 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
* Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all * Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
* data call [encrypt] * data call [encrypt]
*/ */
fun createEncryptor(aesKey: AesKey) : AesCtr { fun createEncryptor(aesKey: AesKey) : AesCtrPure {
return AesCtr(aesKey, Mode.ENCRYPT) return AesCtrPure(aesKey, Mode.ENCRYPT)
} }
/** /**
* Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all * Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
* data call [decrypt] * data call [decrypt]
*/ */
fun createDecryptor(aesKey : AesKey) : AesCtr { fun createDecryptor(aesKey : AesKey) : AesCtrPure {
return AesCtr(aesKey, Mode.DECRYPT) return AesCtrPure(aesKey, Mode.DECRYPT)
} }
/** /**
* Bulk encryption, returns encrypted data and a random initial counter * Bulk encryption, returns encrypted data and a random initial counter
*/ */
fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitialCounter { fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitialCounter {
val aesCtr = AesCtr(aesKey, Mode.ENCRYPT) val aesCtr = AesCtrPure(aesKey, Mode.ENCRYPT)
aesCtr.addData(data) aesCtr.addData(data)
return aesCtr.encrypt() return aesCtr.encrypt()
} }
@ -69,7 +68,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
* Bulk decryption, returns decrypted data * Bulk decryption, returns decrypted data
*/ */
fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray { fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray {
val aesCtr = AesCtr(aesKey, Mode.DECRYPT, initialCounter) val aesCtr = AesCtrPure(aesKey, Mode.DECRYPT, initialCounter)
aesCtr.addData(data) aesCtr.addData(data)
return aesCtr.decrypt() return aesCtr.decrypt()
} }
@ -165,10 +164,10 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
val blockCountAsByteArray = blockCount.toUByteArray(Endianness.BIG).toUByteArray().expandCounterTo16Bytes() val blockCountAsByteArray = blockCount.toUByteArray(Endianness.BIG).toUByteArray().expandCounterTo16Bytes()
return when (mode) { return when (mode) {
Mode.ENCRYPT -> { Mode.ENCRYPT -> {
Aes.encrypt(aesKey, blockCountAsByteArray) xor data AesPure.encrypt(aesKey, blockCountAsByteArray) xor data
} }
Mode.DECRYPT -> { Mode.DECRYPT -> {
Aes.encrypt(aesKey, blockCountAsByteArray) xor data AesPure.encrypt(aesKey, blockCountAsByteArray) xor data
} }
} }

View File

@ -6,7 +6,7 @@ import com.ionspin.kotlin.crypto.util.flattenToUByteArray
* Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 07/Sep/2019 * Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 07/Sep/2019
*/ */
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
internal class Aes internal constructor(val aesKey: AesKey, val input: UByteArray) { internal class AesPure internal constructor(val aesKey: AesKey, val input: UByteArray) {
companion object { companion object {
private val debug = false private val debug = false
@ -57,11 +57,11 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: UByteArra
val rcon: UByteArray = ubyteArrayOf(0x8DU, 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1BU, 0x36U) val rcon: UByteArray = ubyteArrayOf(0x8DU, 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1BU, 0x36U)
fun encrypt(aesKey: AesKey, input: UByteArray): UByteArray { fun encrypt(aesKey: AesKey, input: UByteArray): UByteArray {
return Aes(aesKey, input).encrypt() return AesPure(aesKey, input).encrypt()
} }
fun decrypt(aesKey: AesKey, input: UByteArray): UByteArray { fun decrypt(aesKey: AesKey, input: UByteArray): UByteArray {
return Aes(aesKey, input).decrypt() return AesPure(aesKey, input).decrypt()
} }
} }

View File

@ -16,10 +16,10 @@
package com.ionspin.kotlin.crypto package com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bPure
import com.ionspin.kotlin.crypto.hash.sha.Sha256 import com.ionspin.kotlin.crypto.hash.sha.Sha256Pure
import com.ionspin.kotlin.crypto.hash.sha.Sha512 import com.ionspin.kotlin.crypto.hash.sha.Sha512Pure
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2 import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Pure
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
import com.ionspin.kotlin.crypto.util.testBlocking import com.ionspin.kotlin.crypto.util.testBlocking
import kotlin.test.Test import kotlin.test.Test
@ -40,7 +40,7 @@ class ReadmeTest {
@Test @Test
fun blake2bObjectExample() { fun blake2bObjectExample() {
val input = "abc" val input = "abc"
val result = Blake2b.digest(input) val result = Blake2bPure.digest(input)
//@formatter:off //@formatter:off
val expectedResult = ubyteArrayOf( val expectedResult = ubyteArrayOf(
0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U, 0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U,
@ -59,7 +59,7 @@ class ReadmeTest {
fun blake2bInstanceExample() { fun blake2bInstanceExample() {
val test = "abc" val test = "abc"
val key = "key" val key = "key"
val blake2b = Blake2b(key) val blake2b = Blake2bPure(key)
blake2b.update(test) blake2b.update(test)
val result = blake2b.digest() val result = blake2b.digest()
@ -79,7 +79,7 @@ class ReadmeTest {
@Test @Test
fun sha256Example() { fun sha256Example() {
val input = "abc" val input = "abc"
val result = Sha256.digest(inputString = input) val result = Sha256Pure.digest(inputString = input)
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue { assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray()) result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
@ -92,7 +92,7 @@ class ReadmeTest {
@Test @Test
fun sha512Example() { fun sha512Example() {
val input = "abc" val input = "abc"
val result = Sha512.digest(inputMessage = input.encodeToByteArray().map { it.toUByte() }.toUByteArray()) val result = Sha512Pure.digest(inputMessage = input.encodeToByteArray().map { it.toUByte() }.toUByteArray())
println(result.map { it.toString(16) }) println(result.map { it.toString(16) })
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
@ -106,7 +106,7 @@ class ReadmeTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun sha256UpdatableExample() { fun sha256UpdatableExample() {
val sha256 = Sha256() val sha256 = Sha256Pure()
sha256.update("abc") sha256.update("abc")
val result = sha256.digest() val result = sha256.digest()
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
@ -118,7 +118,7 @@ class ReadmeTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun sha512UpdatableExample() { fun sha512UpdatableExample() {
val sha512 = Sha512() val sha512 = Sha512Pure()
sha512.update("abc") sha512.update("abc")
val result = sha512.digest() val result = sha512.digest()
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
@ -133,13 +133,13 @@ class ReadmeTest {
@ExperimentalTime @ExperimentalTime
@Test @Test
fun argon2StringExample() = testBlocking { fun argon2StringExample() = testBlocking {
val argon2Instance = Argon2( val argon2Instance = Argon2Pure(
password = "Password", password = "Password",
salt = "RandomSalt", salt = "RandomSalt",
parallelism = 1, parallelism = 1,
tagLength = 64U, tagLength = 64U,
requestedMemorySize = 4096U, requestedMemorySize = 4096U,
numberOfIterations = 100, numberOfIterations = 2,
key = "", key = "",
associatedData = "", associatedData = "",
argonType = ArgonType.Argon2id argonType = ArgonType.Argon2id
@ -147,7 +147,7 @@ class ReadmeTest {
val time = measureTime { val time = measureTime {
val tag = argon2Instance.derive() val tag = argon2Instance.derive()
val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
val expectedTagString = "27c61b6538ef9f4a1250f8712cac09fc4329969295f9440249437d38c1617a005c2702d76a8a59e4cda2dfba48e1132261dacdfd31296945906992ea32f1d06e" val expectedTagString = "c19db7e22d1480702b943872c863baf8c43b53d0c3e2c782cd07bfc613eda159233bd821a945c239c5085c70257f7c93d8a809f81c4af367f4ad8f0443a8fc47"
println("Tag: ${tagString}") println("Tag: ${tagString}")
assertEquals(tagString, expectedTagString) assertEquals(tagString, expectedTagString)
} }

View File

@ -18,7 +18,7 @@
package com.ionspin.kotlin.crypto.hash.argon package com.ionspin.kotlin.crypto.hash.argon
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2 import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Pure
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
import com.ionspin.kotlin.crypto.util.hexColumsPrint import com.ionspin.kotlin.crypto.util.hexColumsPrint
import kotlin.test.Test import kotlin.test.Test
@ -57,7 +57,7 @@ class Argon2KATTest {
val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U) val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U)
val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U) val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U)
val digest = Argon2( val digest = Argon2Pure(
password, password,
salt, salt,
parallelism.toInt(), parallelism.toInt(),
@ -98,7 +98,7 @@ class Argon2KATTest {
val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U) val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U)
val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U) val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U)
val digest = Argon2( val digest = Argon2Pure(
password, password,
salt, salt,
parallelism.toInt(), parallelism.toInt(),
@ -139,7 +139,7 @@ class Argon2KATTest {
val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U) val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U)
val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U) val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U)
val digest = Argon2( val digest = Argon2Pure(
password, password,
salt, salt,
parallelism.toInt(), parallelism.toInt(),

View File

@ -46,7 +46,7 @@ class Blake2BTest {
"1234567890" + "1234567890" +
"1234567890" "1234567890"
val result = Blake2b.digest(test) val result = Blake2bPure.digest(test)
//Generated with b2sum 8.31 //Generated with b2sum 8.31
val expectedResult = ubyteArrayOf( val expectedResult = ubyteArrayOf(
//@formatter:off //@formatter:off
@ -77,7 +77,7 @@ class Blake2BTest {
"1234567890" "1234567890"
val result = Blake2b.digest(test) val result = Blake2bPure.digest(test)
val expectedResultString = "800bb78cd4da18995c8074713bb674" + val expectedResultString = "800bb78cd4da18995c8074713bb674" +
"3cd94b2b6490a693fe4000ed00833b88b7b474d94af9cfed246b1b" + "3cd94b2b6490a693fe4000ed00833b88b7b474d94af9cfed246b1b" +
"4ce1935a76154d7ea7c410493557741d18ec3a08da75" "4ce1935a76154d7ea7c410493557741d18ec3a08da75"
@ -93,7 +93,7 @@ class Blake2BTest {
fun testDigest() { fun testDigest() {
val test = "111111111122222222223333333333333" val test = "111111111122222222223333333333333"
val result = Blake2b.digest(test) val result = Blake2bPure.digest(test)
//Generated with b2sum 8.31 //Generated with b2sum 8.31
val expectedResult = ubyteArrayOf( val expectedResult = ubyteArrayOf(
//@formatter:off //@formatter:off
@ -115,7 +115,7 @@ class Blake2BTest {
val test = "abc" val test = "abc"
val key = "key" val key = "key"
val result = Blake2b.digest(test, key) val result = Blake2bPure.digest(test, key)
assertTrue { assertTrue {
result.isNotEmpty() result.isNotEmpty()
@ -134,7 +134,7 @@ class Blake2BTest {
fun testDigestFromRfc() { fun testDigestFromRfc() {
val test = "abc" val test = "abc"
val result = Blake2b.digest(test) val result = Blake2bPure.digest(test)
//@formatter:off //@formatter:off
val expectedResult = ubyteArrayOf( val expectedResult = ubyteArrayOf(
@ -272,7 +272,7 @@ class Blake2BTest {
for (i in 0 until mixChain.size - 1) { for (i in 0 until mixChain.size - 1) {
val inputRound = mixChain[i] val inputRound = mixChain[i]
val round = i val round = i
val result = Blake2b.mixRound(inputRound, message, round) val result = Blake2bPure.mixRound(inputRound, message, round)
val expectedResult = mixChain[i + 1] val expectedResult = mixChain[i + 1]
assertTrue { assertTrue {
result.contentEquals(expectedResult) result.contentEquals(expectedResult)
@ -286,7 +286,7 @@ class Blake2BTest {
fun testInvalidHashLength() { fun testInvalidHashLength() {
val test = "1234567890" val test = "1234567890"
assertFailsWith(RuntimeException::class) { assertFailsWith(RuntimeException::class) {
val result = Blake2b.digest(inputString = test, hashLength = 65) val result = Blake2bPure.digest(inputString = test, hashLength = 65)
} }
} }

View File

@ -42,7 +42,7 @@ class Blake2bInstanceTest {
//@formatter:on //@formatter:on
) )
val blake2b = Blake2b() val blake2b = Blake2bPure()
for (i in 0 until updates) { for (i in 0 until updates) {
blake2b.update(input) blake2b.update(input)
} }
@ -60,7 +60,7 @@ class Blake2bInstanceTest {
val expectedResult = "2F49AEB613E34E924E175A6AF2FAAD7BC78235F9C5E461C68FD5B47E".toLowerCase() + val expectedResult = "2F49AEB613E34E924E175A6AF2FAAD7BC78235F9C5E461C68FD5B47E".toLowerCase() +
"E8E2FD2FB4C07D7E4A72404612D92899AF8A328F3B614ED77244B481151D40B11E32A4".toLowerCase() "E8E2FD2FB4C07D7E4A72404612D92899AF8A328F3B614ED77244B481151D40B11E32A4".toLowerCase()
val blake2b = Blake2b() val blake2b = Blake2bPure()
for (i in 0 until updates) { for (i in 0 until updates) {
blake2b.update(input) blake2b.update(input)
} }
@ -74,7 +74,7 @@ class Blake2bInstanceTest {
fun testDigestWithKey() { fun testDigestWithKey() {
val test = "abc" val test = "abc"
val key = "key" val key = "key"
val blake2b = Blake2b(key) val blake2b = Blake2bPure(key)
blake2b.update(test) blake2b.update(test)
val result = blake2b.digest() val result = blake2b.digest()

View File

@ -37,7 +37,7 @@ class Blake2bKnowAnswerTests {
fun knownAnswerTest() { fun knownAnswerTest() {
kat.forEach { kat.forEach {
val parsedInput = it.input.chunked(2).map { it.toUByte(16) }.toUByteArray() val parsedInput = it.input.chunked(2).map { it.toUByte(16) }.toUByteArray()
val result = Blake2b.digest( val result = Blake2bPure.digest(
inputMessage = parsedInput, inputMessage = parsedInput,
key = it.key.chunked(2).map { it.toUByte(16) }.toUByteArray() key = it.key.chunked(2).map { it.toUByte(16) }.toUByteArray()
) )
@ -53,7 +53,7 @@ class Blake2bKnowAnswerTests {
kat.forEach { kat -> kat.forEach { kat ->
val parsedInput = kat.input.chunked(2).map { it.toUByte(16) }.toUByteArray() val parsedInput = kat.input.chunked(2).map { it.toUByte(16) }.toUByteArray()
val chunkedInput = parsedInput.toList().chunked(128).map { it.toUByteArray() } val chunkedInput = parsedInput.toList().chunked(128).map { it.toUByteArray() }
val blake2b = Blake2b(key = kat.key.chunked(2).map { it.toUByte(16) }.toUByteArray()) val blake2b = Blake2bPure(key = kat.key.chunked(2).map { it.toUByte(16) }.toUByteArray())
chunkedInput.forEach { blake2b.update(it) } chunkedInput.forEach { blake2b.update(it) }
val result = blake2b.digest() val result = blake2b.digest()
assertTrue("KAT ${kat.input} \nkey: ${kat.key} \nexpected: {${kat.hash}") { assertTrue("KAT ${kat.input} \nkey: ${kat.key} \nexpected: {${kat.hash}") {

View File

@ -31,7 +31,7 @@ class Sha256Test {
@Test @Test
fun testWellKnownValue() { fun testWellKnownValue() {
val result = Sha256.digest(inputString = "abc") val result = Sha256Pure.digest(inputString = "abc")
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue { assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray()) result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
@ -44,7 +44,7 @@ class Sha256Test {
@Test @Test
fun testWellKnownDoubleBlock() { fun testWellKnownDoubleBlock() {
val resultDoubleBlock = Sha256.digest(inputString = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") val resultDoubleBlock = Sha256Pure.digest(inputString = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
assertTrue { assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray()) resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
@ -56,7 +56,7 @@ class Sha256Test {
fun testWellKnown3() { //It's good that I'm consistent with names. fun testWellKnown3() { //It's good that I'm consistent with names.
val resultDoubleBlock = Sha256.digest(inputString = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") val resultDoubleBlock = Sha256Pure.digest(inputString = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = "")) println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1" val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
assertTrue { assertTrue {
@ -71,7 +71,7 @@ class Sha256Test {
for (i in 0 until 1000000) { for (i in 0 until 1000000) {
inputBuilder.append("a") inputBuilder.append("a")
} }
val resultDoubleBlock = Sha256.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray()) val resultDoubleBlock = Sha256Pure.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
val expectedResultForDoubleBlock = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0" val expectedResultForDoubleBlock = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
assertTrue { assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray()) resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())

View File

@ -31,7 +31,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnownValue() { fun testWellKnownValue() {
val sha256 = Sha256() val sha256 = Sha256Pure()
sha256.update("abc") sha256.update("abc")
val result = sha256.digest() val result = sha256.digest()
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
@ -43,7 +43,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnownDoubleBlock() { fun testWellKnownDoubleBlock() {
val sha256 = Sha256() val sha256 = Sha256Pure()
sha256.update(data = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") sha256.update(data = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val resultDoubleBlock = sha256.digest() val resultDoubleBlock = sha256.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = "")) println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
@ -56,7 +56,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnown3() { //It's good that I'm consistent with names. fun testWellKnown3() { //It's good that I'm consistent with names.
val sha256 = Sha256() val sha256 = Sha256Pure()
sha256.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") sha256.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha256.digest() val resultDoubleBlock = sha256.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = "")) println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
@ -69,7 +69,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnownLong() { fun testWellKnownLong() {
val sha256 = Sha256() val sha256 = Sha256Pure()
for (i in 0 until 10000) { for (i in 0 until 10000) {
sha256.update("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") sha256.update("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
} }
@ -84,7 +84,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnownLonger() { fun testWellKnownLonger() {
val sha256 = Sha256() val sha256 = Sha256Pure()
for (i in 0 until 16_777_216) { for (i in 0 until 16_777_216) {
if (i % 10000 == 0) { if (i % 10000 == 0) {
println("$i/16777216") println("$i/16777216")

View File

@ -30,7 +30,7 @@ class Sha512Test {
@Test @Test
fun testWellKnownValue() { fun testWellKnownValue() {
val result = Sha512.digest(inputMessage = "abc".encodeToByteArray().map { it.toUByte() }.toUByteArray()) val result = Sha512Pure.digest(inputMessage = "abc".encodeToByteArray().map { it.toUByte() }.toUByteArray())
println(result.map {it.toString(16)}) println(result.map {it.toString(16)})
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
@ -45,7 +45,7 @@ class Sha512Test {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnown3() { fun testWellKnown3() {
val sha512 = Sha512() val sha512 = Sha512Pure()
sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha512.digest() val resultDoubleBlock = sha512.digest()
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" + val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
@ -62,7 +62,7 @@ class Sha512Test {
for (i in 0 until 1000000) { for (i in 0 until 1000000) {
inputBuilder.append("a") inputBuilder.append("a")
} }
val resultDoubleBlock = Sha512.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray()) val resultDoubleBlock = Sha512Pure.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
val expectedResultForDoubleBlock = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b" val expectedResultForDoubleBlock = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
assertTrue { assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray()) resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())

View File

@ -29,7 +29,7 @@ class Sha512UpdatableTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnownValue() { fun testWellKnownValue() {
val sha512 = Sha512() val sha512 = Sha512Pure()
sha512.update("abc") sha512.update("abc")
val result = sha512.digest() val result = sha512.digest()
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
@ -44,7 +44,7 @@ class Sha512UpdatableTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnownDoubleBlock() { fun testWellKnownDoubleBlock() {
val sha512 = Sha512() val sha512 = Sha512Pure()
sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha512.digest() val resultDoubleBlock = sha512.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = "")) println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
@ -58,7 +58,7 @@ class Sha512UpdatableTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnownLong() { fun testWellKnownLong() {
val sha512 = Sha512() val sha512 = Sha512Pure()
for (i in 0 until 10000) { for (i in 0 until 10000) {
sha512.update("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") sha512.update("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
} }
@ -73,7 +73,7 @@ class Sha512UpdatableTest {
@ExperimentalStdlibApi @ExperimentalStdlibApi
@Test @Test
fun testWellKnownLonger() { fun testWellKnownLonger() {
val sha512 = Sha512() val sha512 = Sha512Pure()
for (i in 0 until 16_777_216) { for (i in 0 until 16_777_216) {
if (i % 10000 == 0) { if (i % 10000 == 0) {
println("$i/16777216") println("$i/16777216")

View File

@ -16,7 +16,6 @@
package com.ionspin.kotlin.crypto.symmetric package com.ionspin.kotlin.crypto.symmetric
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
import com.ionspin.kotlin.crypto.util.toHexString import com.ionspin.kotlin.crypto.util.toHexString
import kotlin.test.Test import kotlin.test.Test
@ -38,7 +37,7 @@ class AesCbcTest {
val plaintext = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5" val plaintext = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val expectedCipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7" val expectedCipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val aesCbc = val aesCbc =
AesCbc(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initializationVector = iv.hexStringToUByteArray()) AesCbcPure(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initializationVector = iv.hexStringToUByteArray())
aesCbc.addData(plaintext.hexStringToUByteArray()) aesCbc.addData(plaintext.hexStringToUByteArray())
val encrypted = aesCbc.encrypt() val encrypted = aesCbc.encrypt()
println("Encrypted: ${encrypted.encryptedData.toHexString()}") println("Encrypted: ${encrypted.encryptedData.toHexString()}")
@ -59,8 +58,8 @@ class AesCbcTest {
val plainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5" val plainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val encryptedDataAndInitializationVector = AesCbc.encrypt(key, plainText.hexStringToUByteArray()) val encryptedDataAndInitializationVector = AesCbcPure.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCbc.decrypt( val decrypted = AesCbcPure.decrypt(
key, key,
encryptedDataAndInitializationVector.encryptedData, encryptedDataAndInitializationVector.encryptedData,
encryptedDataAndInitializationVector.initilizationVector encryptedDataAndInitializationVector.initilizationVector
@ -77,7 +76,7 @@ class AesCbcTest {
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7" val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5" val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val aesCbc = val aesCbc =
AesCbc(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initializationVector = iv.hexStringToUByteArray()) AesCbcPure(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initializationVector = iv.hexStringToUByteArray())
aesCbc.addData(cipherText.hexStringToUByteArray()) aesCbc.addData(cipherText.hexStringToUByteArray())
val decrypted = aesCbc.decrypt() val decrypted = aesCbc.decrypt()
println("Decrypted: ${decrypted.toHexString()}") println("Decrypted: ${decrypted.toHexString()}")
@ -96,7 +95,7 @@ class AesCbcTest {
val iv = "57f02a5c5339daeb0a2908a06ac6393f" val iv = "57f02a5c5339daeb0a2908a06ac6393f"
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7" val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5" val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val decrypted = AesCbc.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), iv.hexStringToUByteArray()) val decrypted = AesCbcPure.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), iv.hexStringToUByteArray())
println("Decrypted: ${decrypted.toHexString()}") println("Decrypted: ${decrypted.toHexString()}")
expectedPlainText == decrypted.toHexString() expectedPlainText == decrypted.toHexString()

View File

@ -38,7 +38,7 @@ class AesCtrTest {
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710" "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val expectedCipherText = val expectedCipherText =
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee" "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val aesCtr = AesCtr(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initialCounter = ic.hexStringToUByteArray()) val aesCtr = AesCtrPure(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initialCounter = ic.hexStringToUByteArray())
aesCtr.addData( aesCtr.addData(
plaintext.hexStringToUByteArray() plaintext.hexStringToUByteArray()
) )
@ -57,8 +57,8 @@ class AesCtrTest {
val key = AesKey.Aes128Key(keyString) val key = AesKey.Aes128Key(keyString)
val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710" val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val encryptedDataAndInitializationVector = AesCtr.encrypt(key, plainText.hexStringToUByteArray()) val encryptedDataAndInitializationVector = AesCtrPure.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCtr.decrypt( val decrypted = AesCtrPure.decrypt(
key, key,
encryptedDataAndInitializationVector.encryptedData, encryptedDataAndInitializationVector.encryptedData,
encryptedDataAndInitializationVector.initialCounter encryptedDataAndInitializationVector.initialCounter
@ -77,7 +77,7 @@ class AesCtrTest {
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee" "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val expectedPlainText = val expectedPlainText =
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710" "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val aesCtr = AesCtr(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initialCounter = ic.hexStringToUByteArray()) val aesCtr = AesCtrPure(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initialCounter = ic.hexStringToUByteArray())
aesCtr.addData(cipherText.hexStringToUByteArray()) aesCtr.addData(cipherText.hexStringToUByteArray())
val decrypted = aesCtr.decrypt() val decrypted = aesCtr.decrypt()
println("Decrypted: ${decrypted.toHexString()}") println("Decrypted: ${decrypted.toHexString()}")
@ -97,7 +97,7 @@ class AesCtrTest {
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee" "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val expectedPlainText = val expectedPlainText =
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710" "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val decrypted = AesCtr.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), ic.hexStringToUByteArray()) val decrypted = AesCtrPure.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), ic.hexStringToUByteArray())
println("Decrypted: ${decrypted.toHexString()}") println("Decrypted: ${decrypted.toHexString()}")
expectedPlainText == decrypted.toHexString() expectedPlainText == decrypted.toHexString()
} }

View File

@ -20,7 +20,7 @@ class AesTest {
ubyteArrayOf(0U, 0U, 0U, 0U), ubyteArrayOf(0U, 0U, 0U, 0U),
ubyteArrayOf(0U, 0U, 0U, 0U) ubyteArrayOf(0U, 0U, 0U, 0U)
) )
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput) val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state) fakeState.copyInto(aes.state)
aes.subBytes() aes.subBytes()
assertTrue { assertTrue {
@ -42,7 +42,7 @@ class AesTest {
ubyteArrayOf(2U, 3U, 0U, 1U), ubyteArrayOf(2U, 3U, 0U, 1U),
ubyteArrayOf(3U, 0U, 1U, 2U) ubyteArrayOf(3U, 0U, 1U, 2U)
) )
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput) val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state) fakeState.copyInto(aes.state)
aes.shiftRows() aes.shiftRows()
assertTrue { assertTrue {
@ -56,7 +56,7 @@ class AesTest {
assertTrue { assertTrue {
val a = 0x57U val a = 0x57U
val b = 0x83U val b = 0x83U
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput) val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val c = aes.galoisFieldMultiply(a.toUByte(), b.toUByte()) val c = aes.galoisFieldMultiply(a.toUByte(), b.toUByte())
c == 0xC1U.toUByte() c == 0xC1U.toUByte()
} }
@ -64,7 +64,7 @@ class AesTest {
assertTrue { assertTrue {
val a = 0x57U val a = 0x57U
val b = 0x13U val b = 0x13U
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput) val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val c = aes.galoisFieldMultiply(a.toUByte(), b.toUByte()) val c = aes.galoisFieldMultiply(a.toUByte(), b.toUByte())
c == 0xFEU.toUByte() c == 0xFEU.toUByte()
} }
@ -89,7 +89,7 @@ class AesTest {
ubyteArrayOf(0xbcU, 0x9dU, 0x01U, 0xc6U) ubyteArrayOf(0xbcU, 0x9dU, 0x01U, 0xc6U)
) )
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput) val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state) fakeState.copyInto(aes.state)
aes.mixColumns() aes.mixColumns()
assertTrue { assertTrue {
@ -116,7 +116,7 @@ class AesTest {
).toTypedArray() ).toTypedArray()
val aes = Aes(AesKey.Aes128Key(key), irrelevantInput) val aes = AesPure(AesKey.Aes128Key(key), irrelevantInput)
val result = aes.expandedKey.map { val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte -> it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8)) acc + (uByte.toUInt() shl (24 - index * 8))
@ -140,7 +140,7 @@ class AesTest {
).toTypedArray() ).toTypedArray()
val aes = Aes(AesKey.Aes192Key(key), irrelevantInput) val aes = AesPure(AesKey.Aes192Key(key), irrelevantInput)
val result = aes.expandedKey.map { val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte -> it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8)) acc + (uByte.toUInt() shl (24 - index * 8))
@ -166,7 +166,7 @@ class AesTest {
).toTypedArray() ).toTypedArray()
val aes = Aes(AesKey.Aes256Key(key), irrelevantInput) val aes = AesPure(AesKey.Aes256Key(key), irrelevantInput)
val result = aes.expandedKey.map { val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte -> it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8)) acc + (uByte.toUInt() shl (24 - index * 8))
@ -183,7 +183,7 @@ class AesTest {
val key = "2b7e151628aed2a6abf7158809cf4f3c" val key = "2b7e151628aed2a6abf7158809cf4f3c"
val expectedResult = "3925841d02dc09fbdc118597196a0b32" val expectedResult = "3925841d02dc09fbdc118597196a0b32"
val aes = Aes(AesKey.Aes128Key(key), input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()) val aes = AesPure(AesKey.Aes128Key(key), input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
val result = aes.encrypt() val result = aes.encrypt()
assertTrue { assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()) result.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
@ -197,12 +197,12 @@ class AesTest {
val key = "2b7e151628aed2a6abf7158809cf4f3c" val key = "2b7e151628aed2a6abf7158809cf4f3c"
val expectedResult = "3925841d02dc09fbdc118597196a0b32" val expectedResult = "3925841d02dc09fbdc118597196a0b32"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray() val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val aes = Aes(AesKey.Aes128Key(key), original) val aes = AesPure(AesKey.Aes128Key(key), original)
val encrypted = aes.encrypt() val encrypted = aes.encrypt()
assertTrue { assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()) encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
} }
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted) val decrypted = AesPure.decrypt(AesKey.Aes128Key(key), encrypted)
decrypted.contentEquals(original) decrypted.contentEquals(original)
} }
@ -211,12 +211,12 @@ class AesTest {
val key = "000102030405060708090a0b0c0d0e0f" val key = "000102030405060708090a0b0c0d0e0f"
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a" val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray() val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val aes = Aes(AesKey.Aes128Key(key), original) val aes = AesPure(AesKey.Aes128Key(key), original)
val encrypted = aes.encrypt() val encrypted = aes.encrypt()
assertTrue { assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()) encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
} }
val aesDec = Aes(AesKey.Aes128Key(key), encrypted) val aesDec = AesPure(AesKey.Aes128Key(key), encrypted)
val decrypted = aesDec.decrypt() val decrypted = aesDec.decrypt()
assertTrue { assertTrue {
aesDec.expandedKey.contentDeepEquals(aes.expandedKey) aesDec.expandedKey.contentDeepEquals(aes.expandedKey)
@ -229,11 +229,11 @@ class AesTest {
val key = "000102030405060708090a0b0c0d0e0f" val key = "000102030405060708090a0b0c0d0e0f"
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a" val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray() val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val encrypted = Aes.encrypt(AesKey.Aes128Key(key), original) val encrypted = AesPure.encrypt(AesKey.Aes128Key(key), original)
assertTrue { assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()) encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
} }
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted) val decrypted = AesPure.decrypt(AesKey.Aes128Key(key), encrypted)
decrypted.contentEquals(original) decrypted.contentEquals(original)
} }
@ -242,11 +242,11 @@ class AesTest {
val key = "000102030405060708090a0b0c0d0e0f1011121314151617" val key = "000102030405060708090a0b0c0d0e0f1011121314151617"
val expectedResult = "dda97ca4864cdfe06eaf70a0ec0d7191" val expectedResult = "dda97ca4864cdfe06eaf70a0ec0d7191"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray() val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val encrypted = Aes.encrypt(AesKey.Aes192Key(key), original) val encrypted = AesPure.encrypt(AesKey.Aes192Key(key), original)
assertTrue { assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()) encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
} }
val decrypted = Aes.decrypt(AesKey.Aes192Key(key), encrypted) val decrypted = AesPure.decrypt(AesKey.Aes192Key(key), encrypted)
decrypted.contentEquals(original) decrypted.contentEquals(original)
} }
@ -255,11 +255,11 @@ class AesTest {
val key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" val key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
val expectedResult = "8ea2b7ca516745bfeafc49904b496089" val expectedResult = "8ea2b7ca516745bfeafc49904b496089"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray() val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val encrypted = Aes.encrypt(AesKey.Aes256Key(key), original) val encrypted = AesPure.encrypt(AesKey.Aes256Key(key), original)
assertTrue { assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()) encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
} }
val decrypted = Aes.decrypt(AesKey.Aes256Key(key), encrypted) val decrypted = AesPure.decrypt(AesKey.Aes256Key(key), encrypted)
decrypted.contentEquals(original) decrypted.contentEquals(original)
} }
} }

View File

@ -1,4 +1,4 @@
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2 import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Pure
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
import kotlin.time.measureTime import kotlin.time.measureTime
@ -7,7 +7,7 @@ import kotlin.time.measureTime
@ExperimentalStdlibApi @ExperimentalStdlibApi
fun main() { fun main() {
println("Test") println("Test")
val argon2Instance = Argon2( val argon2Instance = Argon2Pure(
password = "Password", password = "Password",
salt = "RandomSalt", salt = "RandomSalt",
parallelism = 1, parallelism = 1,

View File

@ -35,5 +35,6 @@ pluginManagement {
enableFeaturePreview("GRADLE_METADATA") enableFeaturePreview("GRADLE_METADATA")
rootProject.name = "KotlinMultiplatformCrypto" rootProject.name = "KotlinMultiplatformCrypto"
include("multiplatform-crypto") include("multiplatform-crypto")
include("multiplatform-crypto-api")
include("sample") include("sample")