Fix errors when calculating address blocks, add readme
This commit is contained in:
parent
c62727e3fb
commit
04955effe7
33
README.md
33
README.md
@ -40,7 +40,7 @@ It's not peer reviewed, not guaranteed to be bug free, and not guaranteed to be
|
||||
* SHA512
|
||||
* SHA256
|
||||
|
||||
## Symmetric cipher (Currently only available only in 0.0.3-SNAPSHOT)
|
||||
## Symmetric cipher
|
||||
* AES
|
||||
* Modes: CBC, CTR
|
||||
|
||||
@ -50,7 +50,7 @@ It's not peer reviewed, not guaranteed to be bug free, and not guaranteed to be
|
||||
|
||||
## AEAD
|
||||
|
||||
More to come.
|
||||
TODO()
|
||||
|
||||
## Integration
|
||||
|
||||
@ -187,6 +187,35 @@ plainText == decrypted.toHexString()
|
||||
|
||||
```
|
||||
|
||||
### Key derivation
|
||||
|
||||
#### Argon2
|
||||
|
||||
NOTE: This implementation is tested against KAT generated by reference Argon2 implementation, which does not follow
|
||||
specification completely. See this issue https://github.com/P-H-C/phc-winner-argon2/issues/183
|
||||
|
||||
```kotlin
|
||||
val argon2Instance = Argon2(
|
||||
password = "Password",
|
||||
salt = "RandomSalt",
|
||||
parallelism = 8,
|
||||
tagLength = 64U,
|
||||
requestedMemorySize = 256U, //4GB
|
||||
numberOfIterations = 4U,
|
||||
key = "",
|
||||
associatedData = "",
|
||||
argonType = ArgonType.Argon2id
|
||||
)
|
||||
val tag = argon2Instance.derive()
|
||||
val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
|
||||
val expectedTagString = "c255e3e94305817d5e09a7c771e574e3a81cc78fef5da4a9644b6df0" +
|
||||
"0ba1c9b424e3dd0ce7e600b1269b14c84430708186a8a60403e1bfbda935991592b9ff37"
|
||||
println("Tag: ${tagString}")
|
||||
assertEquals(tagString, expectedTagString)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@ import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.argonBlake2bAr
|
||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.compressionFunctionG
|
||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
|
||||
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToUInt
|
||||
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
||||
import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray
|
||||
|
||||
/**
|
||||
@ -164,6 +165,7 @@ class Argon2(
|
||||
addressBlock: Array<UByte>?
|
||||
): 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 previousBlock = if (column == 0) {
|
||||
@ -176,7 +178,7 @@ class Argon2(
|
||||
Pair(first32Bit, second32Bit)
|
||||
}
|
||||
ArgonType.Argon2i -> {
|
||||
val selectedAddressBlock = addressBlock!!.sliceArray((segmentIndex * 8) until (segmentIndex * 8) + 8)
|
||||
val selectedAddressBlock = addressBlock!!.sliceArray((independentIndex * 8) until (independentIndex * 8) + 8)
|
||||
val first32Bit = selectedAddressBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
|
||||
val second32Bit = selectedAddressBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
|
||||
Pair(first32Bit, second32Bit)
|
||||
@ -184,7 +186,7 @@ class Argon2(
|
||||
ArgonType.Argon2id -> {
|
||||
if (iteration == 0 && (slice == 0 || slice == 1)) {
|
||||
val selectedAddressBlock =
|
||||
addressBlock!!.sliceArray((segmentIndex * 8) until (segmentIndex * 8) + 8)
|
||||
addressBlock!!.sliceArray((independentIndex * 8) until (independentIndex * 8) + 8)
|
||||
val first32Bit = selectedAddressBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
|
||||
val second32Bit = selectedAddressBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
|
||||
Pair(first32Bit, second32Bit)
|
||||
@ -338,12 +340,15 @@ class Argon2(
|
||||
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 && column != 0 && column % 128 == 0) {
|
||||
if (useIndependentAddressing && segmentIndex != 0 && segmentIndex % 128 == 0) {
|
||||
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock!!, addressCounter)
|
||||
addressCounter++
|
||||
addressBlock.hexColumsPrint(16)
|
||||
}
|
||||
val previousColumn = if (column == 0) {
|
||||
columnCount - 1
|
||||
|
@ -19,8 +19,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.keyderivation.argon2.ArgonType
|
||||
import kotlin.test.Test
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
@ -73,7 +75,7 @@ class ReadmeTest {
|
||||
@ExperimentalStdlibApi
|
||||
@Test
|
||||
fun sha256Example() {
|
||||
val input ="abc"
|
||||
val input = "abc"
|
||||
val result = Sha256.digest(inputString = input)
|
||||
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
|
||||
assertTrue {
|
||||
@ -86,9 +88,9 @@ class ReadmeTest {
|
||||
@ExperimentalStdlibApi
|
||||
@Test
|
||||
fun sha512Example() {
|
||||
val input ="abc"
|
||||
val input = "abc"
|
||||
val result = Sha512.digest(inputMessage = input.encodeToByteArray().map { it.toUByte() }.toTypedArray())
|
||||
println(result.map {it.toString(16)})
|
||||
println(result.map { it.toString(16) })
|
||||
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
||||
assertTrue {
|
||||
@ -124,4 +126,26 @@ class ReadmeTest {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun argon2StringExample() {
|
||||
val argon2Instance = Argon2(
|
||||
password = "Password",
|
||||
salt = "RandomSalt",
|
||||
parallelism = 8,
|
||||
tagLength = 64U,
|
||||
requestedMemorySize = 256U, //4GB
|
||||
numberOfIterations = 4U,
|
||||
key = "",
|
||||
associatedData = "",
|
||||
argonType = ArgonType.Argon2id
|
||||
)
|
||||
val tag = argon2Instance.derive()
|
||||
val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
|
||||
val expectedTagString = "c255e3e94305817d5e09a7c771e574e3a81cc78fef5da4a9644b6df0" +
|
||||
"0ba1c9b424e3dd0ce7e600b1269b14c84430708186a8a60403e1bfbda935991592b9ff37"
|
||||
println("Tag: ${tagString}")
|
||||
assertEquals(tagString, expectedTagString)
|
||||
|
||||
}
|
||||
}
|
@ -72,6 +72,15 @@ class UtilTest {
|
||||
converted[3] == 0xAAU.toUByte()
|
||||
|
||||
}
|
||||
assertTrue {
|
||||
val original = 123456U
|
||||
val converted = original.toLittleEndianUByteArray()
|
||||
converted[0] == 0x40U.toUByte() &&
|
||||
converted[1] == 0xE2U.toUByte() &&
|
||||
converted[2] == 0x01U.toUByte() &&
|
||||
converted[3] == 0x00U.toUByte()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user