First steps
This commit is contained in:
parent
aecad37e64
commit
9858eaa5fb
418
multiplatform-crypto-api/build.gradle.kts
Normal file
418
multiplatform-crypto-api/build.gradle.kts
Normal 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
201
multiplatform-crypto-api/package-lock.json
generated
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
15
multiplatform-crypto-api/package.json
Normal file
15
multiplatform-crypto-api/package.json
Normal 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"
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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")
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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) }
|
||||
}
|
||||
}
|
@ -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) }
|
||||
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -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)
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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}") {
|
||||
|
@ -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())
|
||||
|
@ -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")
|
||||
|
@ -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())
|
||||
|
@ -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")
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -35,5 +35,6 @@ pluginManagement {
|
||||
enableFeaturePreview("GRADLE_METADATA")
|
||||
rootProject.name = "KotlinMultiplatformCrypto"
|
||||
include("multiplatform-crypto")
|
||||
include("multiplatform-crypto-api")
|
||||
include("sample")
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user