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
|
* SHA512
|
||||||
* SHA256
|
* SHA256
|
||||||
|
|
||||||
## Symmetric cipher (Currently only available only in 0.0.3-SNAPSHOT)
|
## Symmetric cipher
|
||||||
* AES
|
* AES
|
||||||
* Modes: CBC, CTR
|
* Modes: CBC, CTR
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ It's not peer reviewed, not guaranteed to be bug free, and not guaranteed to be
|
|||||||
|
|
||||||
## AEAD
|
## AEAD
|
||||||
|
|
||||||
More to come.
|
TODO()
|
||||||
|
|
||||||
## Integration
|
## 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.compressionFunctionG
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
|
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
|
||||||
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToUInt
|
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToUInt
|
||||||
|
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
||||||
import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray
|
import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,6 +165,7 @@ class Argon2(
|
|||||||
addressBlock: Array<UByte>?
|
addressBlock: Array<UByte>?
|
||||||
): Pair<Int, Int> {
|
): Pair<Int, Int> {
|
||||||
val segmentIndex = (column % segmentLength)
|
val segmentIndex = (column % segmentLength)
|
||||||
|
val independentIndex = segmentIndex % 128 // 128 is the number of addresses in address block
|
||||||
val (j1, j2) = when (argonType) {
|
val (j1, j2) = when (argonType) {
|
||||||
ArgonType.Argon2d -> {
|
ArgonType.Argon2d -> {
|
||||||
val previousBlock = if (column == 0) {
|
val previousBlock = if (column == 0) {
|
||||||
@ -176,7 +178,7 @@ class Argon2(
|
|||||||
Pair(first32Bit, second32Bit)
|
Pair(first32Bit, second32Bit)
|
||||||
}
|
}
|
||||||
ArgonType.Argon2i -> {
|
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 first32Bit = selectedAddressBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
|
||||||
val second32Bit = selectedAddressBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
|
val second32Bit = selectedAddressBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
|
||||||
Pair(first32Bit, second32Bit)
|
Pair(first32Bit, second32Bit)
|
||||||
@ -184,7 +186,7 @@ class Argon2(
|
|||||||
ArgonType.Argon2id -> {
|
ArgonType.Argon2id -> {
|
||||||
if (iteration == 0 && (slice == 0 || slice == 1)) {
|
if (iteration == 0 && (slice == 0 || slice == 1)) {
|
||||||
val selectedAddressBlock =
|
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 first32Bit = selectedAddressBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
|
||||||
val second32Bit = selectedAddressBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
|
val second32Bit = selectedAddressBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
|
||||||
Pair(first32Bit, second32Bit)
|
Pair(first32Bit, second32Bit)
|
||||||
@ -338,12 +340,15 @@ class Argon2(
|
|||||||
slice * segmentLength
|
slice * segmentLength
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (column in startColumn until (slice + 1) * 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,
|
//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
|
//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)
|
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock!!, addressCounter)
|
||||||
addressCounter++
|
addressCounter++
|
||||||
|
addressBlock.hexColumsPrint(16)
|
||||||
}
|
}
|
||||||
val previousColumn = if (column == 0) {
|
val previousColumn = if (column == 0) {
|
||||||
columnCount - 1
|
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.blake2b.Blake2b
|
||||||
import com.ionspin.kotlin.crypto.hash.sha.Sha256
|
import com.ionspin.kotlin.crypto.hash.sha.Sha256
|
||||||
import com.ionspin.kotlin.crypto.hash.sha.Sha512
|
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.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.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()
|
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
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user