Completed xsalsa20, adding chacha20
This commit is contained in:
parent
0143fe0080
commit
c7445376ca
@ -0,0 +1,38 @@
|
||||
package com.ionspin.kotlin.crypto.symmetric
|
||||
|
||||
import com.ionspin.kotlin.crypto.util.rotateLeft
|
||||
|
||||
/**
|
||||
* Created by Ugljesa Jovanovic
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 16-Jun-2020
|
||||
*/
|
||||
class ChaCha20Pure {
|
||||
companion object {
|
||||
fun quarterRound(input: UIntArray, aPosition: Int, bPosition: Int, cPosition: Int, dPosition: Int) {
|
||||
input[aPosition] += input[bPosition]; input[dPosition] = input[dPosition] xor input[aPosition]; input[dPosition] = input[dPosition] rotateLeft 16
|
||||
input[cPosition] += input[dPosition]; input[bPosition] = input[bPosition] xor input[cPosition]; input[bPosition] = input[bPosition] rotateLeft 12
|
||||
input[aPosition] += input[bPosition]; input[dPosition] = input[dPosition] xor input[aPosition]; input[dPosition] = input[dPosition] rotateLeft 8
|
||||
input[cPosition] += input[dPosition]; input[bPosition] = input[bPosition] xor input[cPosition]; input[bPosition] = input[bPosition] rotateLeft 7
|
||||
}
|
||||
|
||||
fun rowRound(input: UIntArray) {
|
||||
Salsa20Pure.quarterRound(input, 0, 1, 2, 3)
|
||||
Salsa20Pure.quarterRound(input, 5, 6, 7, 4)
|
||||
Salsa20Pure.quarterRound(input, 10, 11, 8, 9)
|
||||
Salsa20Pure.quarterRound(input, 15, 12, 13, 14)
|
||||
}
|
||||
|
||||
fun columnRound(input: UIntArray) {
|
||||
Salsa20Pure.quarterRound(input, 0, 4, 8, 12)
|
||||
Salsa20Pure.quarterRound(input, 5, 9, 13, 1)
|
||||
Salsa20Pure.quarterRound(input, 10, 14, 2, 6)
|
||||
Salsa20Pure.quarterRound(input, 15, 3, 7, 11)
|
||||
}
|
||||
|
||||
fun doubleRound(input: UIntArray) {
|
||||
columnRound(input)
|
||||
rowRound(input)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.ionspin.kotlin.crypto.symmetric
|
||||
|
||||
/**
|
||||
* Created by Ugljesa Jovanovic
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 16-Jun-2020
|
||||
*/
|
||||
fun littleEndian(
|
||||
input: UByteArray,
|
||||
byte0Position: Int,
|
||||
byte1Position: Int,
|
||||
byte2Position: Int,
|
||||
byte3Position: Int
|
||||
): UInt {
|
||||
var uint = 0U
|
||||
uint = input[byte0Position].toUInt()
|
||||
uint = uint or (input[byte1Position].toUInt() shl 8)
|
||||
uint = uint or (input[byte2Position].toUInt() shl 16)
|
||||
uint = uint or (input[byte3Position].toUInt() shl 24)
|
||||
|
||||
return uint
|
||||
}
|
||||
|
||||
fun littleEndianInverted(
|
||||
input: UIntArray,
|
||||
startingPosition: Int,
|
||||
output: UByteArray,
|
||||
outputPosition: Int
|
||||
) {
|
||||
output[outputPosition] = (input[startingPosition] and 0xFFU).toUByte()
|
||||
output[outputPosition + 1] = ((input[startingPosition] shr 8) and 0xFFU).toUByte()
|
||||
output[outputPosition + 2] = ((input[startingPosition] shr 16) and 0xFFU).toUByte()
|
||||
output[outputPosition + 3] = ((input[startingPosition] shr 24) and 0xFFU).toUByte()
|
||||
}
|
||||
|
||||
fun littleEndianInverted(
|
||||
input: UInt,
|
||||
output: UByteArray,
|
||||
outputPosition: Int
|
||||
) {
|
||||
output[outputPosition] = (input and 0xFFU).toUByte()
|
||||
output[outputPosition + 1] = ((input shr 8) and 0xFFU).toUByte()
|
||||
output[outputPosition + 2] = ((input shr 16) and 0xFFU).toUByte()
|
||||
output[outputPosition + 3] = ((input shr 24) and 0xFFU).toUByte()
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package com.ionspin.kotlin.crypto.symmetric
|
||||
|
||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.xorWithBlock
|
||||
import com.ionspin.kotlin.crypto.util.*
|
||||
|
||||
/**
|
||||
@ -8,7 +7,7 @@ import com.ionspin.kotlin.crypto.util.*
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 14-Jun-2020
|
||||
*/
|
||||
class Salsa20 {
|
||||
class Salsa20Pure {
|
||||
companion object {
|
||||
fun quarterRound(input: UIntArray, y0position: Int, y1position: Int, y2position: Int, y3position: Int) {
|
||||
input[y1position] = input[y1position] xor ((input[y0position] + input[y3position]) rotateLeft 7)
|
||||
@ -36,44 +35,7 @@ class Salsa20 {
|
||||
rowRound(input)
|
||||
}
|
||||
|
||||
fun littleEndian(
|
||||
input: UByteArray,
|
||||
byte0Position: Int,
|
||||
byte1Position: Int,
|
||||
byte2Position: Int,
|
||||
byte3Position: Int
|
||||
): UInt {
|
||||
var uint = 0U
|
||||
uint = input[byte0Position].toUInt()
|
||||
uint = uint or (input[byte1Position].toUInt() shl 8)
|
||||
uint = uint or (input[byte2Position].toUInt() shl 16)
|
||||
uint = uint or (input[byte3Position].toUInt() shl 24)
|
||||
|
||||
return uint
|
||||
}
|
||||
|
||||
fun littleEndianInverted(
|
||||
input: UIntArray,
|
||||
startingPosition: Int,
|
||||
output: UByteArray,
|
||||
outputPosition: Int
|
||||
) {
|
||||
output[outputPosition] = (input[startingPosition] and 0xFFU).toUByte()
|
||||
output[outputPosition + 1] = ((input[startingPosition] shr 8) and 0xFFU).toUByte()
|
||||
output[outputPosition + 2] = ((input[startingPosition] shr 16) and 0xFFU).toUByte()
|
||||
output[outputPosition + 3] = ((input[startingPosition] shr 24) and 0xFFU).toUByte()
|
||||
}
|
||||
|
||||
fun littleEndianInverted(
|
||||
input: UInt,
|
||||
output: UByteArray,
|
||||
outputPosition: Int
|
||||
) {
|
||||
output[outputPosition] = (input and 0xFFU).toUByte()
|
||||
output[outputPosition + 1] = ((input shr 8) and 0xFFU).toUByte()
|
||||
output[outputPosition + 2] = ((input shr 16) and 0xFFU).toUByte()
|
||||
output[outputPosition + 3] = ((input shr 24) and 0xFFU).toUByte()
|
||||
}
|
||||
|
||||
fun hash(initialState: UIntArray): UByteArray {
|
||||
val state = initialState.copyOf()
|
||||
@ -128,23 +90,31 @@ class Salsa20 {
|
||||
else -> 0U
|
||||
}
|
||||
}
|
||||
val blocks = message.size / 64
|
||||
val remainder = message.size % 64
|
||||
for (i in 0 until message.size - 64 step 64) {
|
||||
hash(state).xorWithPositionsAndInsertIntoArray(0, 64, message, i, ciphertext, i)
|
||||
for (i in 0 until blocks) {
|
||||
hash(state).xorWithPositionsAndInsertIntoArray(0, 64, message, i * 64, ciphertext, i * 64)
|
||||
state[8] += 1U
|
||||
if (state[8] == 0U) {
|
||||
state[9] += 1U
|
||||
}
|
||||
}
|
||||
for ( i in message.size - (64 - remainder) until message.size step 64) {
|
||||
hash(state).xorWithPositionsAndInsertIntoArray(0, (64 - remainder), message, i, ciphertext, i)
|
||||
|
||||
hash(state).xorWithPositionsAndInsertIntoArray(
|
||||
0, remainder,
|
||||
message, (blocks - 1) * 64,
|
||||
ciphertext, (blocks - 1) * 64)
|
||||
state[8] += 1U
|
||||
if (state[8] == 0U) {
|
||||
state[9] += 1U
|
||||
}
|
||||
}
|
||||
|
||||
return ciphertext
|
||||
}
|
||||
|
||||
fun decrypt(key : UByteArray, nonce: UByteArray, ciphertext: UByteArray) : UByteArray {
|
||||
return encrypt(key, nonce, ciphertext)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package com.ionspin.kotlin.crypto.symmetric
|
||||
|
||||
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToUInt
|
||||
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToUIntWithPosition
|
||||
import com.ionspin.kotlin.crypto.util.xorWithPositionsAndInsertIntoArray
|
||||
|
||||
/**
|
||||
* Created by Ugljesa Jovanovic
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 16-Jun-2020
|
||||
*/
|
||||
class XSalsa20Pure {
|
||||
companion object {
|
||||
fun hSalsa(key: UByteArray, nonce: UByteArray): UIntArray {
|
||||
val state = UIntArray(16) {
|
||||
when (it) {
|
||||
0 -> Salsa20Pure.sigma0_32.fromLittleEndianArrayToUInt()
|
||||
1 -> key.fromLittleEndianArrayToUIntWithPosition(0)
|
||||
2 -> key.fromLittleEndianArrayToUIntWithPosition(4)
|
||||
3 -> key.fromLittleEndianArrayToUIntWithPosition(8)
|
||||
4 -> key.fromLittleEndianArrayToUIntWithPosition(12)
|
||||
5 -> Salsa20Pure.sigma1_32.fromLittleEndianArrayToUInt()
|
||||
6 -> nonce.fromLittleEndianArrayToUIntWithPosition(0)
|
||||
7 -> nonce.fromLittleEndianArrayToUIntWithPosition(4)
|
||||
8 -> nonce.fromLittleEndianArrayToUIntWithPosition(8)
|
||||
9 -> nonce.fromLittleEndianArrayToUIntWithPosition(12)
|
||||
10 -> Salsa20Pure.sigma2_32.fromLittleEndianArrayToUInt()
|
||||
11 -> key.fromLittleEndianArrayToUIntWithPosition(16)
|
||||
12 -> key.fromLittleEndianArrayToUIntWithPosition(20)
|
||||
13 -> key.fromLittleEndianArrayToUIntWithPosition(24)
|
||||
14 -> key.fromLittleEndianArrayToUIntWithPosition(28)
|
||||
15 -> Salsa20Pure.sigma3_32.fromLittleEndianArrayToUInt()
|
||||
else -> throw RuntimeException("Invalid index $it")
|
||||
}
|
||||
}
|
||||
for (i in 0 until 10) {
|
||||
Salsa20Pure.doubleRound(state)
|
||||
}
|
||||
val result = UIntArray(8) {
|
||||
when (it) {
|
||||
0 -> state[0]
|
||||
1 -> state[5]
|
||||
2 -> state[10]
|
||||
3 -> state[15]
|
||||
4 -> state[6]
|
||||
5 -> state[7]
|
||||
6 -> state[8]
|
||||
7 -> state[9]
|
||||
else -> throw RuntimeException("Invalid index $it")
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray): UByteArray {
|
||||
if (nonce.size != 24) {
|
||||
throw RuntimeException("Invalid nonce size. required 192 bits, got ${nonce.size * 8}")
|
||||
}
|
||||
val ciphertext = UByteArray(message.size)
|
||||
val hSalsaKey = hSalsa(key, nonce)
|
||||
val state = UIntArray(16) {
|
||||
when (it) {
|
||||
0 -> Salsa20Pure.sigma0_32.fromLittleEndianArrayToUInt()
|
||||
1 -> hSalsaKey[0]
|
||||
2 -> hSalsaKey[1]
|
||||
3 -> hSalsaKey[2]
|
||||
4 -> hSalsaKey[3]
|
||||
5 -> Salsa20Pure.sigma1_32.fromLittleEndianArrayToUInt()
|
||||
6 -> nonce.fromLittleEndianArrayToUIntWithPosition(16) //Last 63 bit of 192 bit nonce
|
||||
7 -> nonce.fromLittleEndianArrayToUIntWithPosition(20)
|
||||
8 -> 0U
|
||||
9 -> 0U
|
||||
10 -> Salsa20Pure.sigma2_32.fromLittleEndianArrayToUInt()
|
||||
11 -> hSalsaKey[4]
|
||||
12 -> hSalsaKey[5]
|
||||
13 -> hSalsaKey[6]
|
||||
14 -> hSalsaKey[7]
|
||||
15 -> Salsa20Pure.sigma3_32.fromLittleEndianArrayToUInt()
|
||||
else -> 0U
|
||||
}
|
||||
}
|
||||
val blocks = message.size / 64
|
||||
val remainder = message.size % 64
|
||||
for (i in 0 until blocks) {
|
||||
Salsa20Pure.hash(state).xorWithPositionsAndInsertIntoArray(0, 64, message, i * 64, ciphertext, i * 64)
|
||||
state[8] += 1U
|
||||
if (state[8] == 0U) {
|
||||
state[9] += 1U
|
||||
}
|
||||
}
|
||||
|
||||
Salsa20Pure.hash(state).xorWithPositionsAndInsertIntoArray(
|
||||
0, remainder,
|
||||
message, (blocks - 1).coerceAtLeast(0) * 64,
|
||||
ciphertext, (blocks - 1).coerceAtLeast(0) * 64)
|
||||
state[8] += 1U
|
||||
if (state[8] == 0U) {
|
||||
state[9] += 1U
|
||||
}
|
||||
return ciphertext
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -108,9 +108,6 @@ fun UByteArray.xorWithPositionsAndInsertIntoArray(
|
||||
other : UByteArray, otherStart: Int,
|
||||
targetArray: UByteArray, targetStart : Int) {
|
||||
for (i in start until end) {
|
||||
if (targetStart + i == 131071) {
|
||||
println("stop")
|
||||
}
|
||||
targetArray[targetStart + i] = this[start + i] xor other[otherStart + i]
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class Salsa20Test {
|
||||
assertTrue {
|
||||
val input = uintArrayOf(0U, 0U, 0U, 0U)
|
||||
val expected = uintArrayOf(0U, 0U, 0U, 0U)
|
||||
Salsa20.quarterRound(input, 0, 1, 2, 3)
|
||||
Salsa20Pure.quarterRound(input, 0, 1, 2, 3)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
|
||||
expected.contentEquals(input)
|
||||
@ -37,7 +37,7 @@ class Salsa20Test {
|
||||
assertTrue {
|
||||
val input = uintArrayOf(1U, 0U, 0U, 0U)
|
||||
val expected = uintArrayOf(0x08008145U, 0x00000080U, 0x00010200U, 0x20500000U)
|
||||
Salsa20.quarterRound(input, 0, 1, 2, 3)
|
||||
Salsa20Pure.quarterRound(input, 0, 1, 2, 3)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
|
||||
expected.contentEquals(input)
|
||||
@ -46,7 +46,7 @@ class Salsa20Test {
|
||||
assertTrue {
|
||||
val input = uintArrayOf(0U, 1U, 0U, 0U)
|
||||
val expected = uintArrayOf(0x88000100U, 0x00000001U, 0x00000200U, 0x00402000U)
|
||||
Salsa20.quarterRound(input, 0, 1, 2, 3)
|
||||
Salsa20Pure.quarterRound(input, 0, 1, 2, 3)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
|
||||
expected.contentEquals(input)
|
||||
@ -56,14 +56,14 @@ class Salsa20Test {
|
||||
val input = uintArrayOf(0U, 0U, 1U, 0U)
|
||||
val expected = uintArrayOf(0x80040000U, 0x00000000U, 0x00000001U, 0x00002000U)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
Salsa20.quarterRound(input, 0, 1, 2, 3)
|
||||
Salsa20Pure.quarterRound(input, 0, 1, 2, 3)
|
||||
expected.contentEquals(input)
|
||||
}
|
||||
|
||||
assertTrue {
|
||||
val input = uintArrayOf(0U, 0U, 0U, 1U)
|
||||
val expected = uintArrayOf(0x00048044U, 0x00000080U, 0x00010000U, 0x20100001U)
|
||||
Salsa20.quarterRound(input, 0, 1, 2, 3)
|
||||
Salsa20Pure.quarterRound(input, 0, 1, 2, 3)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
|
||||
expected.contentEquals(input)
|
||||
@ -73,7 +73,7 @@ class Salsa20Test {
|
||||
assertTrue {
|
||||
val input = uintArrayOf(0xd3917c5bU, 0x55f1c407U, 0x52a58a7aU, 0x8f887a3bU)
|
||||
val expected = uintArrayOf(0x3e2f308cU, 0xd90a8f36U, 0x6ab2a923U, 0x2883524cU)
|
||||
Salsa20.quarterRound(input, 0, 1, 2, 3)
|
||||
Salsa20Pure.quarterRound(input, 0, 1, 2, 3)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
expected.contentEquals(input)
|
||||
}
|
||||
@ -95,7 +95,7 @@ class Salsa20Test {
|
||||
0x00000001U, 0x00000200U, 0x00402000U, 0x88000100U
|
||||
)
|
||||
|
||||
Salsa20.rowRound(input)
|
||||
Salsa20Pure.rowRound(input)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
expected.contentEquals(input)
|
||||
}
|
||||
@ -113,7 +113,7 @@ class Salsa20Test {
|
||||
0x3402e183U, 0x3c3af432U, 0x50669f96U, 0xd89ef0a8U,
|
||||
0x0040ede5U, 0xb545fbceU, 0xd257ed4fU, 0x1818882dU
|
||||
)
|
||||
Salsa20.rowRound(input)
|
||||
Salsa20Pure.rowRound(input)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
expected.contentEquals(input)
|
||||
}
|
||||
@ -135,7 +135,7 @@ class Salsa20Test {
|
||||
0x40a04001U, 0x00000000U, 0x00000000U, 0x00000000U
|
||||
)
|
||||
|
||||
Salsa20.columnRound(input)
|
||||
Salsa20Pure.columnRound(input)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
expected.contentEquals(input)
|
||||
}
|
||||
@ -153,7 +153,7 @@ class Salsa20Test {
|
||||
0x789b010cU, 0xd195a681U, 0xeb7d5504U, 0xa774135cU,
|
||||
0x481c2027U, 0x53a8e4b5U, 0x4c1f89c5U, 0x3f78c9c8U
|
||||
)
|
||||
Salsa20.columnRound(input)
|
||||
Salsa20Pure.columnRound(input)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
expected.contentEquals(input)
|
||||
}
|
||||
@ -175,7 +175,7 @@ class Salsa20Test {
|
||||
0x20500000U, 0xa0000040U, 0x0008180aU, 0x612a8020U
|
||||
)
|
||||
|
||||
Salsa20.doubleRound(input)
|
||||
Salsa20Pure.doubleRound(input)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
expected.contentEquals(input)
|
||||
}
|
||||
@ -193,7 +193,7 @@ class Salsa20Test {
|
||||
0xca531c29U, 0x8e7943dbU, 0xac1680cdU, 0xd503ca00U,
|
||||
0xa74b2ad6U, 0xbc331c5cU, 0x1dda24c7U, 0xee928277U
|
||||
)
|
||||
Salsa20.doubleRound(input)
|
||||
Salsa20Pure.doubleRound(input)
|
||||
println("Result ${input.joinToString { it.toString(16).padStart(2, '0') }}")
|
||||
expected.contentEquals(input)
|
||||
}
|
||||
@ -204,14 +204,14 @@ class Salsa20Test {
|
||||
assertTrue {
|
||||
val input = ubyteArrayOf(86U, 75U, 30U, 9U)
|
||||
val expected = 0x091e4b56U
|
||||
val result = Salsa20.littleEndian(input, 0, 1, 2, 3)
|
||||
val result = littleEndian(input, 0, 1, 2, 3)
|
||||
result == expected
|
||||
}
|
||||
|
||||
assertTrue {
|
||||
val input = ubyteArrayOf(255U, 255U, 255U, 250U)
|
||||
val expected = 0xFAFFFFFFU
|
||||
val result = Salsa20.littleEndian(input, 0, 1, 2, 3)
|
||||
val result = littleEndian(input, 0, 1, 2, 3)
|
||||
result == expected
|
||||
}
|
||||
}
|
||||
@ -222,7 +222,7 @@ class Salsa20Test {
|
||||
val expected = ubyteArrayOf(86U, 75U, 30U, 9U)
|
||||
val input = uintArrayOf(0x091e4b56U)
|
||||
val result = UByteArray(4)
|
||||
Salsa20.littleEndianInverted(input, 0, result, 0)
|
||||
littleEndianInverted(input, 0, result, 0)
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
|
||||
@ -230,7 +230,7 @@ class Salsa20Test {
|
||||
val expected = ubyteArrayOf(255U, 255U, 255U, 250U)
|
||||
val input = uintArrayOf(0xFAFFFFFFU)
|
||||
val result = UByteArray(4)
|
||||
Salsa20.littleEndianInverted(input, 0, result, 0)
|
||||
littleEndianInverted(input, 0, result, 0)
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
}
|
||||
@ -241,7 +241,7 @@ class Salsa20Test {
|
||||
val expected = ubyteArrayOf(86U, 75U, 30U, 9U)
|
||||
val input = 0x091e4b56U
|
||||
val result = UByteArray(4)
|
||||
Salsa20.littleEndianInverted(input, result, 0)
|
||||
littleEndianInverted(input, result, 0)
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
|
||||
@ -249,7 +249,7 @@ class Salsa20Test {
|
||||
val expected = ubyteArrayOf(255U, 255U, 255U, 250U)
|
||||
val input = 0xFAFFFFFFU
|
||||
val result = UByteArray(4)
|
||||
Salsa20.littleEndianInverted(input, result, 0)
|
||||
littleEndianInverted(input, result, 0)
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
}
|
||||
@ -269,7 +269,7 @@ class Salsa20Test {
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U
|
||||
)
|
||||
val result = Salsa20.hash(input.fromLittleEndianToUInt())
|
||||
val result = Salsa20Pure.hash(input.fromLittleEndianToUInt())
|
||||
input.contentEquals(expected)
|
||||
}
|
||||
|
||||
@ -286,7 +286,7 @@ class Salsa20Test {
|
||||
118U, 40U, 152U, 157U, 180U, 57U, 27U, 94U, 107U, 42U, 236U, 35U, 27U, 111U, 114U, 114U,
|
||||
219U, 236U, 232U, 135U, 111U, 155U, 110U, 18U, 24U, 232U, 95U, 158U, 179U, 19U, 48U, 202U
|
||||
)
|
||||
val result = Salsa20.hash(input.fromLittleEndianToUInt())
|
||||
val result = Salsa20Pure.hash(input.fromLittleEndianToUInt())
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
|
||||
@ -304,7 +304,7 @@ class Salsa20Test {
|
||||
122U, 127U, 195U, 185U, 185U, 204U, 188U, 90U, 245U, 9U, 183U, 248U, 226U, 85U, 245U, 104U
|
||||
)
|
||||
val result = (0 until 1_000_000).fold(input) { acc, _ ->
|
||||
Salsa20.hash(acc.fromLittleEndianToUInt())
|
||||
Salsa20Pure.hash(acc.fromLittleEndianToUInt())
|
||||
}
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
@ -326,7 +326,7 @@ class Salsa20Test {
|
||||
104U, 197U, 7U, 225U, 197U, 153U, 31U, 2U, 102U, 78U, 76U, 176U, 84U, 245U, 246U, 184U,
|
||||
177U, 160U, 133U, 130U, 6U, 72U, 149U, 119U, 192U, 195U, 132U, 236U, 234U, 103U, 246U, 74U
|
||||
)
|
||||
val result = Salsa20.expansion32(k0 + k1, n)
|
||||
val result = Salsa20Pure.expansion32(k0 + k1, n)
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
|
||||
@ -337,7 +337,7 @@ class Salsa20Test {
|
||||
134U, 85U, 110U, 246U, 161U, 163U, 43U, 235U, 231U, 94U, 171U, 51U, 145U, 214U, 112U, 29U,
|
||||
14U, 232U, 5U, 16U, 151U, 140U, 183U, 141U, 171U, 9U, 122U, 181U, 104U, 182U, 177U, 193U
|
||||
)
|
||||
val result = Salsa20.expansion16(k0, n)
|
||||
val result = Salsa20Pure.expansion16(k0, n)
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
}
|
||||
@ -359,7 +359,7 @@ class Salsa20Test {
|
||||
"CC32B15B93784A36E56A76CC64BC8477"
|
||||
).toLowerCase()
|
||||
|
||||
val ciphertext = Salsa20.encrypt(key, nonce, UByteArray(512) { 0U })
|
||||
val ciphertext = Salsa20Pure.encrypt(key, nonce, UByteArray(512) { 0U })
|
||||
ciphertext.toHexString().toLowerCase().startsWith(expectedStartsWith) &&
|
||||
ciphertext.toHexString().toLowerCase().endsWith(endsWith)
|
||||
}
|
||||
@ -379,7 +379,7 @@ class Salsa20Test {
|
||||
"529C4158B7FF41EE854B1235373988C8"
|
||||
).toLowerCase()
|
||||
|
||||
val ciphertext = Salsa20.encrypt(key, nonce, UByteArray(131072) { 0U })
|
||||
val ciphertext = Salsa20Pure.encrypt(key, nonce, UByteArray(131072) { 0U })
|
||||
println(ciphertext.slice(0 until 64).toTypedArray().toHexString())
|
||||
println(ciphertext.slice(131008 until 131072).toTypedArray().toHexString())
|
||||
ciphertext.slice(0 until 64).toTypedArray().toHexString().toLowerCase().startsWith(expectedStartsWith) &&
|
||||
|
@ -0,0 +1,44 @@
|
||||
package com.ionspin.kotlin.crypto.symmetric
|
||||
|
||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Created by Ugljesa Jovanovic
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 16-Jun-2020
|
||||
*/
|
||||
class XSalsa20Test {
|
||||
@Test
|
||||
fun testXSalsa20() {
|
||||
// values from https://go.googlesource.com/crypto/+/master/salsa20/salsa20_test.go xSalsa20TestData
|
||||
assertTrue {
|
||||
val message = "Hello world!".encodeToUByteArray()
|
||||
val nonce = "24-byte nonce for xsalsa".encodeToUByteArray()
|
||||
val key = "this is 32-byte key for xsalsa20".encodeToUByteArray()
|
||||
val expected = ubyteArrayOf(0x00U, 0x2dU, 0x45U, 0x13U, 0x84U, 0x3fU, 0xc2U, 0x40U, 0xc4U, 0x01U, 0xe5U, 0x41U)
|
||||
val result = XSalsa20Pure.encrypt(key, nonce, message)
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
|
||||
assertTrue {
|
||||
val message = UByteArray(64) { 0U }
|
||||
val nonce = "24-byte nonce for xsalsa".encodeToUByteArray()
|
||||
val key = "this is 32-byte key for xsalsa20".encodeToUByteArray()
|
||||
val expected = ubyteArrayOf(
|
||||
0x48U, 0x48U, 0x29U, 0x7fU, 0xebU, 0x1fU, 0xb5U, 0x2fU, 0xb6U,
|
||||
0x6dU, 0x81U, 0x60U, 0x9bU, 0xd5U, 0x47U, 0xfaU, 0xbcU, 0xbeU, 0x70U,
|
||||
0x26U, 0xedU, 0xc8U, 0xb5U, 0xe5U, 0xe4U, 0x49U, 0xd0U, 0x88U, 0xbfU,
|
||||
0xa6U, 0x9cU, 0x08U, 0x8fU, 0x5dU, 0x8dU, 0xa1U, 0xd7U, 0x91U, 0x26U,
|
||||
0x7cU, 0x2cU, 0x19U, 0x5aU, 0x7fU, 0x8cU, 0xaeU, 0x9cU, 0x4bU, 0x40U,
|
||||
0x50U, 0xd0U, 0x8cU, 0xe6U, 0xd3U, 0xa1U, 0x51U, 0xecU, 0x26U, 0x5fU,
|
||||
0x3aU, 0x58U, 0xe4U, 0x76U, 0x48U
|
||||
)
|
||||
val result = XSalsa20Pure.encrypt(key, nonce, message)
|
||||
result.contentEquals(expected)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user