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(Deps.Common.coroutines)
implementation(Deps.Common.kotlinBigNum)
implementation(project(":multiplatform-crypto-api"))
}
}
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.toBigInteger
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
/**
@ -31,9 +28,9 @@ import com.ionspin.kotlin.crypto.util.rotateRight
*/
@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
//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
@ -255,7 +252,7 @@ class Blake2b(val key: UByteArray? = null, val hashLength: Int = 64) : Updatable
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 counter = BigInteger.ZERO

View File

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

View File

@ -16,7 +16,6 @@
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.UpdatableHash
import com.ionspin.kotlin.crypto.util.rotateRight
@ -28,11 +27,11 @@ import com.ionspin.kotlin.crypto.util.rotateRight
*/
@ExperimentalUnsignedTypes
class Sha512 : UpdatableHash {
class Sha512Pure : Sha512 {
override val MAX_HASH_BYTES: Int = 32
companion object : StatelessHash {
companion object : StatelessSha512 {
const val BLOCK_SIZE = 1024
const val BLOCK_SIZE_IN_BYTES = 128
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
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.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
* on 24-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 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()
)
}
}
}
interface Argon2 : KeyDerivationFunction

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
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.util.arrayChunked
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToULong
import com.ionspin.kotlin.crypto.util.plus
import com.ionspin.kotlin.crypto.util.rotateRight
@ -101,17 +99,17 @@ object Argon2Utils {
internal fun argonBlake2bArbitraryLenghtHash(input: UByteArray, length: UInt): UByteArray {
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
val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent to ceil(length/32) - 2
val v = Array<UByteArray>(numberOf64ByteBlocks) { ubyteArrayOf() }
v[0] = Blake2b.digest(length + input)
v[0] = Blake2bPure.digest(length + input)
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 vLast = Blake2b.digest(v[numberOf64ByteBlocks - 1], hashLength = remainingPartOfInput)
val vLast = Blake2bPure.digest(v[numberOf64ByteBlocks - 1], hashLength = remainingPartOfInput)
val concat =
(v.map { it.copyOfRange(0, 32) })
.plus(listOf(vLast))

View File

@ -16,11 +16,7 @@
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.measureTime
/**
* Created by Ugljesa Jovanovic

View File

@ -17,13 +17,12 @@
package com.ionspin.kotlin.crypto.symmetric
import com.ionspin.kotlin.crypto.SRNG
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.util.xor
/**
* 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]
*
@ -32,7 +31,7 @@ import com.ionspin.kotlin.crypto.util.xor
* on 21-Sep-2019
*/
@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 {
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
* data call [encrypt]
*/
fun createEncryptor(aesKey: AesKey) : AesCbc {
return AesCbc(aesKey, Mode.ENCRYPT)
fun createEncryptor(aesKey: AesKey) : AesCbcPure {
return AesCbcPure(aesKey, Mode.ENCRYPT)
}
/**
* Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
* data call [decrypt]
*/
fun createDecryptor(aesKey : AesKey) : AesCbc {
return AesCbc(aesKey, Mode.DECRYPT)
fun createDecryptor(aesKey : AesKey) : AesCbcPure {
return AesCbcPure(aesKey, Mode.DECRYPT)
}
/**
* Bulk encryption, returns encrypted data and a random initialization vector
*/
fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitializationVector {
val aesCbc = AesCbc(aesKey, Mode.ENCRYPT)
val aesCbc = AesCbcPure(aesKey, Mode.ENCRYPT)
aesCbc.addData(data)
return aesCbc.encrypt()
}
@ -64,7 +63,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
* Bulk decryption, returns decrypted data
*/
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)
return aesCbc.decrypt()
}
@ -199,17 +198,17 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
Mode.ENCRYPT -> {
currentOutput = if (currentOutput.isEmpty()) {
println("IV: $initVector")
Aes.encrypt(aesKey, data xor initVector)
AesPure.encrypt(aesKey, data xor initVector)
} else {
Aes.encrypt(aesKey, data xor currentOutput)
AesPure.encrypt(aesKey, data xor currentOutput)
}
currentOutput
}
Mode.DECRYPT -> {
if (currentOutput.isEmpty()) {
currentOutput = Aes.decrypt(aesKey, data) xor initVector
currentOutput = AesPure.decrypt(aesKey, data) xor initVector
} else {
currentOutput = Aes.decrypt(aesKey, data) xor previousEncrypted
currentOutput = AesPure.decrypt(aesKey, data) xor previousEncrypted
}
previousEncrypted = data
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.modular.ModularBigInteger
import com.ionspin.kotlin.crypto.SRNG
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.symmetric.AesCtr.Companion.encrypt
import com.ionspin.kotlin.crypto.symmetric.AesCtrPure.Companion.encrypt
import com.ionspin.kotlin.crypto.util.xor
/**
*
* 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]
*
@ -37,7 +36,7 @@ import com.ionspin.kotlin.crypto.util.xor
* on 22-Sep-2019
*/
@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 {
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
* data call [encrypt]
*/
fun createEncryptor(aesKey: AesKey) : AesCtr {
return AesCtr(aesKey, Mode.ENCRYPT)
fun createEncryptor(aesKey: AesKey) : AesCtrPure {
return AesCtrPure(aesKey, Mode.ENCRYPT)
}
/**
* Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
* data call [decrypt]
*/
fun createDecryptor(aesKey : AesKey) : AesCtr {
return AesCtr(aesKey, Mode.DECRYPT)
fun createDecryptor(aesKey : AesKey) : AesCtrPure {
return AesCtrPure(aesKey, Mode.DECRYPT)
}
/**
* Bulk encryption, returns encrypted data and a random initial counter
*/
fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitialCounter {
val aesCtr = AesCtr(aesKey, Mode.ENCRYPT)
val aesCtr = AesCtrPure(aesKey, Mode.ENCRYPT)
aesCtr.addData(data)
return aesCtr.encrypt()
}
@ -69,7 +68,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
* Bulk decryption, returns decrypted data
*/
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)
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()
return when (mode) {
Mode.ENCRYPT -> {
Aes.encrypt(aesKey, blockCountAsByteArray) xor data
AesPure.encrypt(aesKey, blockCountAsByteArray) xor data
}
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
*/
@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 {
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)
fun encrypt(aesKey: AesKey, input: UByteArray): UByteArray {
return Aes(aesKey, input).encrypt()
return AesPure(aesKey, input).encrypt()
}
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
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.hash.blake2b.Blake2bPure
import com.ionspin.kotlin.crypto.hash.sha.Sha256Pure
import com.ionspin.kotlin.crypto.hash.sha.Sha512Pure
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Pure
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
import com.ionspin.kotlin.crypto.util.testBlocking
import kotlin.test.Test
@ -40,7 +40,7 @@ class ReadmeTest {
@Test
fun blake2bObjectExample() {
val input = "abc"
val result = Blake2b.digest(input)
val result = Blake2bPure.digest(input)
//@formatter:off
val expectedResult = ubyteArrayOf(
0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U,
@ -59,7 +59,7 @@ class ReadmeTest {
fun blake2bInstanceExample() {
val test = "abc"
val key = "key"
val blake2b = Blake2b(key)
val blake2b = Blake2bPure(key)
blake2b.update(test)
val result = blake2b.digest()
@ -79,7 +79,7 @@ class ReadmeTest {
@Test
fun sha256Example() {
val input = "abc"
val result = Sha256.digest(inputString = input)
val result = Sha256Pure.digest(inputString = input)
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
@ -92,7 +92,7 @@ class ReadmeTest {
@Test
fun sha512Example() {
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) })
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
@ -106,7 +106,7 @@ class ReadmeTest {
@ExperimentalStdlibApi
@Test
fun sha256UpdatableExample() {
val sha256 = Sha256()
val sha256 = Sha256Pure()
sha256.update("abc")
val result = sha256.digest()
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
@ -118,7 +118,7 @@ class ReadmeTest {
@ExperimentalStdlibApi
@Test
fun sha512UpdatableExample() {
val sha512 = Sha512()
val sha512 = Sha512Pure()
sha512.update("abc")
val result = sha512.digest()
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
@ -133,13 +133,13 @@ class ReadmeTest {
@ExperimentalTime
@Test
fun argon2StringExample() = testBlocking {
val argon2Instance = Argon2(
val argon2Instance = Argon2Pure(
password = "Password",
salt = "RandomSalt",
parallelism = 1,
tagLength = 64U,
requestedMemorySize = 4096U,
numberOfIterations = 100,
numberOfIterations = 2,
key = "",
associatedData = "",
argonType = ArgonType.Argon2id
@ -147,7 +147,7 @@ class ReadmeTest {
val time = measureTime {
val tag = argon2Instance.derive()
val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
val expectedTagString = "27c61b6538ef9f4a1250f8712cac09fc4329969295f9440249437d38c1617a005c2702d76a8a59e4cda2dfba48e1132261dacdfd31296945906992ea32f1d06e"
val expectedTagString = "c19db7e22d1480702b943872c863baf8c43b53d0c3e2c782cd07bfc613eda159233bd821a945c239c5085c70257f7c93d8a809f81c4af367f4ad8f0443a8fc47"
println("Tag: ${tagString}")
assertEquals(tagString, expectedTagString)
}

View File

@ -18,7 +18,7 @@
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.util.hexColumsPrint
import kotlin.test.Test
@ -57,7 +57,7 @@ class Argon2KATTest {
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(
val digest = Argon2Pure(
password,
salt,
parallelism.toInt(),
@ -98,7 +98,7 @@ class Argon2KATTest {
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(
val digest = Argon2Pure(
password,
salt,
parallelism.toInt(),
@ -139,7 +139,7 @@ class Argon2KATTest {
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(
val digest = Argon2Pure(
password,
salt,
parallelism.toInt(),

View File

@ -46,7 +46,7 @@ class Blake2BTest {
"1234567890" +
"1234567890"
val result = Blake2b.digest(test)
val result = Blake2bPure.digest(test)
//Generated with b2sum 8.31
val expectedResult = ubyteArrayOf(
//@formatter:off
@ -77,7 +77,7 @@ class Blake2BTest {
"1234567890"
val result = Blake2b.digest(test)
val result = Blake2bPure.digest(test)
val expectedResultString = "800bb78cd4da18995c8074713bb674" +
"3cd94b2b6490a693fe4000ed00833b88b7b474d94af9cfed246b1b" +
"4ce1935a76154d7ea7c410493557741d18ec3a08da75"
@ -93,7 +93,7 @@ class Blake2BTest {
fun testDigest() {
val test = "111111111122222222223333333333333"
val result = Blake2b.digest(test)
val result = Blake2bPure.digest(test)
//Generated with b2sum 8.31
val expectedResult = ubyteArrayOf(
//@formatter:off
@ -115,7 +115,7 @@ class Blake2BTest {
val test = "abc"
val key = "key"
val result = Blake2b.digest(test, key)
val result = Blake2bPure.digest(test, key)
assertTrue {
result.isNotEmpty()
@ -134,7 +134,7 @@ class Blake2BTest {
fun testDigestFromRfc() {
val test = "abc"
val result = Blake2b.digest(test)
val result = Blake2bPure.digest(test)
//@formatter:off
val expectedResult = ubyteArrayOf(
@ -272,7 +272,7 @@ class Blake2BTest {
for (i in 0 until mixChain.size - 1) {
val inputRound = mixChain[i]
val round = i
val result = Blake2b.mixRound(inputRound, message, round)
val result = Blake2bPure.mixRound(inputRound, message, round)
val expectedResult = mixChain[i + 1]
assertTrue {
result.contentEquals(expectedResult)
@ -286,7 +286,7 @@ class Blake2BTest {
fun testInvalidHashLength() {
val test = "1234567890"
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
)
val blake2b = Blake2b()
val blake2b = Blake2bPure()
for (i in 0 until updates) {
blake2b.update(input)
}
@ -60,7 +60,7 @@ class Blake2bInstanceTest {
val expectedResult = "2F49AEB613E34E924E175A6AF2FAAD7BC78235F9C5E461C68FD5B47E".toLowerCase() +
"E8E2FD2FB4C07D7E4A72404612D92899AF8A328F3B614ED77244B481151D40B11E32A4".toLowerCase()
val blake2b = Blake2b()
val blake2b = Blake2bPure()
for (i in 0 until updates) {
blake2b.update(input)
}
@ -74,7 +74,7 @@ class Blake2bInstanceTest {
fun testDigestWithKey() {
val test = "abc"
val key = "key"
val blake2b = Blake2b(key)
val blake2b = Blake2bPure(key)
blake2b.update(test)
val result = blake2b.digest()

View File

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

View File

@ -31,7 +31,7 @@ class Sha256Test {
@Test
fun testWellKnownValue() {
val result = Sha256.digest(inputString = "abc")
val result = Sha256Pure.digest(inputString = "abc")
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
@ -44,7 +44,7 @@ class Sha256Test {
@Test
fun testWellKnownDoubleBlock() {
val resultDoubleBlock = Sha256.digest(inputString = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val resultDoubleBlock = Sha256Pure.digest(inputString = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
assertTrue {
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.
val resultDoubleBlock = Sha256.digest(inputString = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = Sha256Pure.digest(inputString = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
assertTrue {
@ -71,7 +71,7 @@ class Sha256Test {
for (i in 0 until 1000000) {
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"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())

View File

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

View File

@ -30,7 +30,7 @@ class Sha512Test {
@Test
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)})
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
@ -45,7 +45,7 @@ class Sha512Test {
@ExperimentalStdlibApi
@Test
fun testWellKnown3() {
val sha512 = Sha512()
val sha512 = Sha512Pure()
sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha512.digest()
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
@ -62,7 +62,7 @@ class Sha512Test {
for (i in 0 until 1000000) {
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"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())

View File

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

View File

@ -16,7 +16,6 @@
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
@ -38,7 +37,7 @@ class AesCbcTest {
val plaintext = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val expectedCipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
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())
val encrypted = aesCbc.encrypt()
println("Encrypted: ${encrypted.encryptedData.toHexString()}")
@ -59,8 +58,8 @@ class AesCbcTest {
val plainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val encryptedDataAndInitializationVector = AesCbc.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCbc.decrypt(
val encryptedDataAndInitializationVector = AesCbcPure.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCbcPure.decrypt(
key,
encryptedDataAndInitializationVector.encryptedData,
encryptedDataAndInitializationVector.initilizationVector
@ -77,7 +76,7 @@ class AesCbcTest {
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
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())
val decrypted = aesCbc.decrypt()
println("Decrypted: ${decrypted.toHexString()}")
@ -96,7 +95,7 @@ class AesCbcTest {
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
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()}")
expectedPlainText == decrypted.toHexString()

View File

@ -38,7 +38,7 @@ class AesCtrTest {
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val expectedCipherText =
"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(
plaintext.hexStringToUByteArray()
)
@ -57,8 +57,8 @@ class AesCtrTest {
val key = AesKey.Aes128Key(keyString)
val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val encryptedDataAndInitializationVector = AesCtr.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCtr.decrypt(
val encryptedDataAndInitializationVector = AesCtrPure.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCtrPure.decrypt(
key,
encryptedDataAndInitializationVector.encryptedData,
encryptedDataAndInitializationVector.initialCounter
@ -77,7 +77,7 @@ class AesCtrTest {
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val expectedPlainText =
"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())
val decrypted = aesCtr.decrypt()
println("Decrypted: ${decrypted.toHexString()}")
@ -97,7 +97,7 @@ class AesCtrTest {
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val expectedPlainText =
"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()}")
expectedPlainText == decrypted.toHexString()
}

View File

@ -20,7 +20,7 @@ class AesTest {
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)
aes.subBytes()
assertTrue {
@ -42,7 +42,7 @@ class AesTest {
ubyteArrayOf(2U, 3U, 0U, 1U),
ubyteArrayOf(3U, 0U, 1U, 2U)
)
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state)
aes.shiftRows()
assertTrue {
@ -56,7 +56,7 @@ class AesTest {
assertTrue {
val a = 0x57U
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())
c == 0xC1U.toUByte()
}
@ -64,7 +64,7 @@ class AesTest {
assertTrue {
val a = 0x57U
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())
c == 0xFEU.toUByte()
}
@ -89,7 +89,7 @@ class AesTest {
ubyteArrayOf(0xbcU, 0x9dU, 0x01U, 0xc6U)
)
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state)
aes.mixColumns()
assertTrue {
@ -116,7 +116,7 @@ class AesTest {
).toTypedArray()
val aes = Aes(AesKey.Aes128Key(key), irrelevantInput)
val aes = AesPure(AesKey.Aes128Key(key), irrelevantInput)
val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8))
@ -140,7 +140,7 @@ class AesTest {
).toTypedArray()
val aes = Aes(AesKey.Aes192Key(key), irrelevantInput)
val aes = AesPure(AesKey.Aes192Key(key), irrelevantInput)
val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8))
@ -166,7 +166,7 @@ class AesTest {
).toTypedArray()
val aes = Aes(AesKey.Aes256Key(key), irrelevantInput)
val aes = AesPure(AesKey.Aes256Key(key), irrelevantInput)
val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8))
@ -183,7 +183,7 @@ class AesTest {
val key = "2b7e151628aed2a6abf7158809cf4f3c"
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()
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
@ -197,12 +197,12 @@ class AesTest {
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 aes = AesPure(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)
val decrypted = AesPure.decrypt(AesKey.Aes128Key(key), encrypted)
decrypted.contentEquals(original)
}
@ -211,12 +211,12 @@ class AesTest {
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 aes = AesPure(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 aesDec = AesPure(AesKey.Aes128Key(key), encrypted)
val decrypted = aesDec.decrypt()
assertTrue {
aesDec.expandedKey.contentDeepEquals(aes.expandedKey)
@ -229,11 +229,11 @@ class AesTest {
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)
val encrypted = AesPure.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)
val decrypted = AesPure.decrypt(AesKey.Aes128Key(key), encrypted)
decrypted.contentEquals(original)
}
@ -242,11 +242,11 @@ class AesTest {
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)
val encrypted = AesPure.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)
val decrypted = AesPure.decrypt(AesKey.Aes192Key(key), encrypted)
decrypted.contentEquals(original)
}
@ -255,11 +255,11 @@ class AesTest {
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)
val encrypted = AesPure.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)
val decrypted = AesPure.decrypt(AesKey.Aes256Key(key), encrypted)
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 kotlin.time.ExperimentalTime
import kotlin.time.measureTime
@ -7,7 +7,7 @@ import kotlin.time.measureTime
@ExperimentalStdlibApi
fun main() {
println("Test")
val argon2Instance = Argon2(
val argon2Instance = Argon2Pure(
password = "Password",
salt = "RandomSalt",
parallelism = 1,

View File

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