Cleanup 1
This commit is contained in:
parent
a1a56487ff
commit
2db5523893
@ -72,15 +72,10 @@ interface AuthenticatedEncryption {
|
|||||||
data class EncryptedDataPart(val data : UByteArray)
|
data class EncryptedDataPart(val data : UByteArray)
|
||||||
data class DecryptedDataPart(val data : UByteArray)
|
data class DecryptedDataPart(val data : UByteArray)
|
||||||
|
|
||||||
data class MultipartEncryptedDataDescriptor(val data: UByteArray, val nonce: UByteArray)
|
data class MultipartEncryptionHeader(val nonce: UByteArray)
|
||||||
|
|
||||||
class InvalidTagException : RuntimeException("Tag mismatch! Encrypted data is corrupted or tampered with.")
|
class InvalidTagException : RuntimeException("Tag mismatch! Encrypted data is corrupted or tampered with.")
|
||||||
|
|
||||||
interface MultipartAuthenticatedVerification {
|
|
||||||
fun verifyPartialData(data: EncryptedDataPart)
|
|
||||||
fun finalizeVerificationAndPrepareDecryptor() : MultipartAuthenticatedDecryption
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MultipartAuthenticatedDecryption {
|
interface MultipartAuthenticatedDecryption {
|
||||||
fun decryptPartialData(data: EncryptedDataPart) : DecryptedDataPart
|
fun decryptPartialData(data: EncryptedDataPart) : DecryptedDataPart
|
||||||
}
|
}
|
||||||
|
@ -171,32 +171,14 @@ object Crypto {
|
|||||||
|
|
||||||
class MultipartAuthenticatedEncryptor internal constructor(val key : SymmetricKey, additionalData: UByteArray) : MultipartAuthenticatedEncryption {
|
class MultipartAuthenticatedEncryptor internal constructor(val key : SymmetricKey, additionalData: UByteArray) : MultipartAuthenticatedEncryption {
|
||||||
val primitive = XChaCha20Poly1305Delegated(key.value, additionalData)
|
val primitive = XChaCha20Poly1305Delegated(key.value, additionalData)
|
||||||
|
|
||||||
|
|
||||||
override fun encryptPartialData(data: UByteArray): EncryptedDataPart {
|
override fun encryptPartialData(data: UByteArray): EncryptedDataPart {
|
||||||
return EncryptedDataPart(primitive.encryptPartialData(data))
|
return EncryptedDataPart(primitive.encrypt(data))
|
||||||
}
|
|
||||||
|
|
||||||
override fun finish(): MultipartEncryptedDataDescriptor {
|
|
||||||
val finished = primitive.finishEncryption()
|
|
||||||
return MultipartEncryptedDataDescriptor(finished.first, finished.second)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiplatformAuthenticatedVerificator internal constructor(key: SymmetricKey, multipartEncryptedDataDescriptor: MultipartEncryptedDataDescriptor, additionalData: UByteArray) : MultipartAuthenticatedVerification {
|
|
||||||
val primitive = XChaCha20Poly1305Delegated(key.value, additionalData)
|
|
||||||
val tag = multipartEncryptedDataDescriptor.data.sliceArray(
|
|
||||||
multipartEncryptedDataDescriptor.data.size - 16 until multipartEncryptedDataDescriptor.data.size
|
|
||||||
)
|
|
||||||
override fun verifyPartialData(data: EncryptedDataPart) {
|
|
||||||
primitive.verifyPartialData(data.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun finalizeVerificationAndPrepareDecryptor(): MultipartAuthenticatedDecryption {
|
|
||||||
primitive.checkTag(tag)
|
|
||||||
return MultipartAuthenticatedDecryptor(primitive)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class MultipartAuthenticatedDecryptor internal constructor(val encryptor: XChaCha20Poly1305Delegated) : MultipartAuthenticatedDecryption {
|
class MultipartAuthenticatedDecryptor internal constructor(val encryptor: XChaCha20Poly1305Delegated) : MultipartAuthenticatedDecryption {
|
||||||
override fun decryptPartialData(data: EncryptedDataPart): DecryptedDataPart {
|
override fun decryptPartialData(data: EncryptedDataPart): DecryptedDataPart {
|
||||||
|
@ -13,11 +13,9 @@ expect class XChaCha20Poly1305Delegated constructor(key: UByteArray, additionalD
|
|||||||
fun decrypt(key: UByteArray, nonce: UByteArray, ciphertext: UByteArray, additionalData: UByteArray) : UByteArray
|
fun decrypt(key: UByteArray, nonce: UByteArray, ciphertext: UByteArray, additionalData: UByteArray) : UByteArray
|
||||||
}
|
}
|
||||||
|
|
||||||
fun encryptPartialData(data: UByteArray) : UByteArray
|
fun encrypt(data: UByteArray) : UByteArray
|
||||||
fun verifyPartialData(data: UByteArray)
|
|
||||||
fun checkTag(expectedTag: UByteArray)
|
|
||||||
fun decrypt(data: UByteArray) : UByteArray
|
fun decrypt(data: UByteArray) : UByteArray
|
||||||
fun finishEncryption() : Pair<UByteArray, UByteArray>
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,6 @@ import com.ionspin.kotlin.crypto.CryptoInitializerDelegated
|
|||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
||||||
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
import com.ionspin.kotlin.crypto.util.testBlocking
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlin.test.Ignore
|
import kotlin.test.Ignore
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
@ -145,7 +143,7 @@ class XChaCha20Poly1305Test {
|
|||||||
0xcfU, 0x49U
|
0xcfU, 0x49U
|
||||||
)
|
)
|
||||||
val xChaChaPoly = XChaCha20Poly1305Delegated(key, additionalData)
|
val xChaChaPoly = XChaCha20Poly1305Delegated(key, additionalData)
|
||||||
val firstChunk = xChaChaPoly.encryptPartialData(message)
|
val firstChunk = xChaChaPoly.encrypt(message)
|
||||||
val finalChunk = xChaChaPoly.finishEncryption().first
|
val finalChunk = xChaChaPoly.finishEncryption().first
|
||||||
val result = firstChunk + finalChunk
|
val result = firstChunk + finalChunk
|
||||||
|
|
||||||
@ -176,7 +174,7 @@ class XChaCha20Poly1305Test {
|
|||||||
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
|
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
|
||||||
)
|
)
|
||||||
val xChaChaPoly = XChaCha20Poly1305Delegated(key, additionalData)
|
val xChaChaPoly = XChaCha20Poly1305Delegated(key, additionalData)
|
||||||
val firstChunk = xChaChaPoly.encryptPartialData(message)
|
val firstChunk = xChaChaPoly.encrypt(message)
|
||||||
val finalChunk = xChaChaPoly.finishEncryption().first
|
val finalChunk = xChaChaPoly.finishEncryption().first
|
||||||
val result = firstChunk + finalChunk
|
val result = firstChunk + finalChunk
|
||||||
result.contentEquals(expected)
|
result.contentEquals(expected)
|
||||||
|
@ -55,7 +55,7 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun encryptPartialData(data: UByteArray): UByteArray {
|
actual fun encrypt(data: UByteArray): UByteArray {
|
||||||
TODO("not implemented yet")
|
TODO("not implemented yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun encryptPartialData(data: UByteArray): UByteArray {
|
actual fun encrypt(data: UByteArray): UByteArray {
|
||||||
TODO("not implemented yet")
|
TODO("not implemented yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ actual class XChaCha20Poly1305Delegated actual constructor(val key: UByteArray,v
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun encryptPartialData(data: UByteArray): UByteArray {
|
actual fun encrypt(data: UByteArray): UByteArray {
|
||||||
val ciphertextWithTag = UByteArray(data.size + crypto_secretstream_xchacha20poly1305_ABYTES.toInt())
|
val ciphertextWithTag = UByteArray(data.size + crypto_secretstream_xchacha20poly1305_ABYTES.toInt())
|
||||||
val ciphertextWithTagPinned = ciphertextWithTag.pin()
|
val ciphertextWithTagPinned = ciphertextWithTag.pin()
|
||||||
crypto_secretstream_xchacha20poly1305_push(
|
crypto_secretstream_xchacha20poly1305_push(
|
||||||
|
@ -69,49 +69,12 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val updateableEncryptionPrimitive = XChaCha20Pure(key, nonce, initialCounter = 1U)
|
|
||||||
private val updateableMacPrimitive : Poly1305
|
|
||||||
|
|
||||||
private val polyBuffer = UByteArray(16)
|
private val polyBuffer = UByteArray(16)
|
||||||
private var polyBufferByteCounter = 0
|
private var polyBufferByteCounter = 0
|
||||||
|
|
||||||
private var processedBytes = 0
|
private var processedBytes = 0
|
||||||
|
|
||||||
init {
|
|
||||||
val subKey = XChaCha20Pure.hChacha(key, nonce)
|
|
||||||
val authKey =
|
|
||||||
ChaCha20Pure.xorWithKeystream(
|
|
||||||
subKey.toLittleEndianUByteArray(),
|
|
||||||
ubyteArrayOf(0U, 0U, 0U, 0U) + nonce.sliceArray(16 until 24),
|
|
||||||
UByteArray(64) { 0U },
|
|
||||||
0U // If this is moved as a default parameter in encrypt, and not here (in 1.4-M2)
|
|
||||||
// js compiler dies with: e: java.lang.NullPointerException
|
|
||||||
// at org.jetbrains.kotlin.ir.backend.js.lower.ConstTransformer$visitConst$1$3.invoke(ConstLowering.kt:28)
|
|
||||||
// at org.jetbrains.kotlin.ir.backend.js.lower.ConstTransformer.lowerConst(ConstLowering.kt:38)
|
|
||||||
)
|
|
||||||
updateableMacPrimitive = Poly1305(authKey)
|
|
||||||
// val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U }
|
|
||||||
// processPolyBytes(additionalData + additionalDataPad)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sketch libsodium stream cipher with chachapoly, because my two pass approach to multipart encryption is
|
|
||||||
// inneficient, to put it mildly.
|
|
||||||
|
|
||||||
// libsodium-like state
|
|
||||||
// key, 32 Bytes
|
|
||||||
// nonce, 12 Bytes
|
|
||||||
// pad, 8 bytes
|
|
||||||
|
|
||||||
//libsodium like header
|
|
||||||
//random header bytes 24 and put that into out
|
|
||||||
//then hchacha20 of key and random bytes (out) to generate state key
|
|
||||||
//the reset counter to 1
|
|
||||||
//then copy to state->NONCE, HCHACHAINPUTBYTES (16B) from out, length of INONCE_BYTES which is 8, which uses up all random from previous step
|
|
||||||
//Pad state with 8B of zeroes
|
|
||||||
|
|
||||||
//header is a 24byte nonce
|
|
||||||
|
|
||||||
internal val calcKey : UByteArray = UByteArray(32)
|
internal val calcKey : UByteArray = UByteArray(32)
|
||||||
internal val calcNonce : UByteArray = UByteArray(12)
|
internal val calcNonce : UByteArray = UByteArray(12)
|
||||||
|
|
||||||
@ -131,117 +94,39 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) {
|
|||||||
println("Calcnonce---------")
|
println("Calcnonce---------")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun encryptPartial(data: UByteArray, additionalData: UByteArray = ubyteArrayOf(), tag : UByte = 0U) : UByteArray {
|
fun streamEncrypt(data: UByteArray, additionalData: UByteArray = ubyteArrayOf(), tag : UByte = 0U) : UByteArray {
|
||||||
val result = UByteArray(1 + data.size + 16) //Tag marker, ciphertext, mac
|
val result = UByteArray(1 + data.size + 16) //Tag marker, ciphertext, mac
|
||||||
//get encryption state
|
//get encryption state
|
||||||
val block = UByteArray(64) { 0U }
|
val block = UByteArray(64) { 0U }
|
||||||
println("--block")
|
|
||||||
block.hexColumsPrint()
|
|
||||||
println("--block")
|
|
||||||
println("--key")
|
|
||||||
calcKey.hexColumsPrint()
|
|
||||||
println("--key")
|
|
||||||
println("--nonce")
|
|
||||||
calcNonce.hexColumsPrint()
|
|
||||||
println("--nonce")
|
|
||||||
ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, block, 0U).copyInto(block) // This is equivalent to the first 64 bytes of keystream
|
ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, block, 0U).copyInto(block) // This is equivalent to the first 64 bytes of keystream
|
||||||
/*
|
|
||||||
5C 9A C3 7B CA 8F 2B 12 9A D8 41 3B 0C E9 55 EF
|
|
||||||
25 27 9A 4B 5B 7F 87 75 0C 47 E9 C9 DE 82 44 BA
|
|
||||||
6C 51 48 F4 9C 0A 24 6B F2 7C 51 5E 62 1A 16 E1
|
|
||||||
28 23 C6 B5 12 2E AD 58 AD 51 AA 34 78 33 08 C9
|
|
||||||
*/
|
|
||||||
println("--block")
|
|
||||||
block.hexColumsPrint()
|
|
||||||
println("--block")
|
|
||||||
val poly1305 = Poly1305(block)
|
val poly1305 = Poly1305(block)
|
||||||
block.overwriteWithZeroes()
|
block.overwriteWithZeroes()
|
||||||
if (additionalData.isNotEmpty()) {
|
if (additionalData.isNotEmpty()) {
|
||||||
val additionalDataPadded = additionalData + UByteArray(16 - additionalData.size % 16) { 0U }
|
val additionalDataPadded = additionalData + UByteArray(16 - additionalData.size % 16) { 0U }
|
||||||
processPolyBytes(poly1305, additionalDataPadded)
|
processPolyBytes(poly1305, additionalDataPadded)
|
||||||
}
|
}
|
||||||
|
|
||||||
block[0] = tag
|
block[0] = tag
|
||||||
ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, block, 1U).copyInto(block) // This just xors block[0] with keystream
|
ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, block, 1U).copyInto(block) // This just xors block[0] with keystream
|
||||||
processPolyBytes(poly1305, block) // but updates the mac with the full block!
|
processPolyBytes(poly1305, block) // but updates the mac with the full block!
|
||||||
// println("--poly 1")
|
|
||||||
// 13 10 8E D1 3C B9 77 C1 9B 95 66 C8 1B 8A 5D D3
|
|
||||||
// poly1305.finalizeMac().hexColumsPrint()
|
|
||||||
// println("--poly 1")
|
|
||||||
// In libsodium c code, it now sets the first byte to be a tag, we'll just save it for now
|
// In libsodium c code, it now sets the first byte to be a tag, we'll just save it for now
|
||||||
val encryptedTag = block[0]
|
val encryptedTag = block[0]
|
||||||
//And then encrypt the rest of the message
|
//And then encrypt the rest of the message
|
||||||
val ciphertext = ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, data, 2U) // With appropriate counter
|
val ciphertext = ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, data, 2U) // With appropriate counter
|
||||||
println("ciphertext-----")
|
// Next we update the poly1305 with ciphertext and padding, BUT the padding in libsodium is not correctly calculated, so it doesn't
|
||||||
/*
|
// pad correctly. https://github.com/jedisct1/libsodium/issues/976
|
||||||
paddedCipherText--
|
// We want to use libsodium in delegated flavour, so we will use the same incorrect padding here.
|
||||||
D3 2D 59 B8 C4 66 2E 47 29 C6 F9 93 4B 09 27 24
|
// From security standpoint there are no obvious drawbacks, as padding was initially added to decrease implementation complexity.
|
||||||
DD F3 05 48 94 67 10 00 21 85 22 96 3C CE 8E B7
|
|
||||||
53 9D 46 F5 3C 5E 48 9B 8C 13 B7 28 6B B3 6C 3A
|
|
||||||
04 B7 25 B9 50 45 08 0B 89 A2 0F 70 CC 60 1B C3
|
|
||||||
17 35 9F AE 82 51 43 1B 9D 53 9E E2 AF 20 1F FD
|
|
||||||
03 59 11 51 9E AC 83 CD 78 D1 D0 E5 D7 0E 41 DE
|
|
||||||
FB 5C 7F 1C 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
paddedCipherText--
|
|
||||||
*/
|
|
||||||
(ciphertext + UByteArray(((16 - 64 + data.size) % 16)) { 0U }).hexColumsPrint()
|
|
||||||
println("pad: ${16 - ((data.size) % 16)}")
|
|
||||||
println("pad: ${((16U + data.size.toUInt() - block.size.toUInt()) % 16U).toInt()}")
|
|
||||||
println("ciphertext-----")
|
|
||||||
processPolyBytes(poly1305, ciphertext + UByteArray(((16U + data.size.toUInt() - block.size.toUInt()) % 16U).toInt()) { 0U } ) //TODO this is inefficient as it creates a new array and copies data
|
processPolyBytes(poly1305, ciphertext + UByteArray(((16U + data.size.toUInt() - block.size.toUInt()) % 16U).toInt()) { 0U } ) //TODO this is inefficient as it creates a new array and copies data
|
||||||
// println("--poly cipher")
|
// Last 16byte block containing actual additional data nad ciphertext sizes
|
||||||
// 93 D9 13 DC AB 1D 07 D7 51 03 17 85 8A 5C F0 84
|
|
||||||
// poly1305.finalizeMac().hexColumsPrint()
|
|
||||||
// println("--poly cipher")
|
|
||||||
val finalMac = additionalData.size.toULong().toLittleEndianUByteArray() + (ciphertext.size + 64).toULong().toLittleEndianUByteArray()
|
val finalMac = additionalData.size.toULong().toLittleEndianUByteArray() + (ciphertext.size + 64).toULong().toLittleEndianUByteArray()
|
||||||
processPolyBytes(poly1305, finalMac)
|
processPolyBytes(poly1305, finalMac)
|
||||||
val mac = poly1305.finalizeMac(polyBuffer.sliceArray(0 until polyBufferByteCounter))
|
val mac = poly1305.finalizeMac(polyBuffer.sliceArray(0 until polyBufferByteCounter))
|
||||||
//19 F3 39 CC DE 82 35 08 C1 82 DB 3D F1 EF 89 45
|
|
||||||
println("poly final --")
|
|
||||||
mac.hexColumsPrint()
|
|
||||||
println("poly final --")
|
|
||||||
return ubyteArrayOf(encryptedTag) + ciphertext + mac
|
return ubyteArrayOf(encryptedTag) + ciphertext + mac
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sketch end
|
fun streamDecrypt(data: UByteArray, additionalData: UByteArray = ubyteArrayOf(), tag: UBy)
|
||||||
|
|
||||||
fun encryptPartialData(data: UByteArray) : UByteArray {
|
|
||||||
processedBytes += data.size
|
|
||||||
val encrypted = updateableEncryptionPrimitive.xorWithKeystream(data)
|
|
||||||
// processPolyBytes(encrypted)
|
|
||||||
|
|
||||||
val cipherTextPad = UByteArray(16 - processedBytes % 16) { 0U }
|
|
||||||
val macData = cipherTextPad +
|
|
||||||
// additionalData.size.toULong().toLittleEndianUByteArray() +
|
|
||||||
processedBytes.toULong().toLittleEndianUByteArray()
|
|
||||||
// processPolyBytes(macData)
|
|
||||||
val tag = updateableMacPrimitive.finalizeMac()
|
|
||||||
|
|
||||||
return encrypted + tag
|
|
||||||
}
|
|
||||||
|
|
||||||
fun verifyPartialData(data: UByteArray) {
|
|
||||||
// processPolyBytes(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkTag(expectedTag: UByteArray) {
|
|
||||||
val cipherTextPad = UByteArray(16 - processedBytes % 16) { 0U }
|
|
||||||
val macData = cipherTextPad +
|
|
||||||
// additionalData.size.toULong().toLittleEndianUByteArray() +
|
|
||||||
processedBytes.toULong().toLittleEndianUByteArray()
|
|
||||||
// processPolyBytes(macData)
|
|
||||||
val tag = updateableMacPrimitive.finalizeMac()
|
|
||||||
if (!tag.contentEquals(expectedTag)) {
|
|
||||||
throw InvalidTagException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun decrypt(data: UByteArray) : UByteArray {
|
|
||||||
processedBytes += data.size
|
|
||||||
val decrypted = updateableEncryptionPrimitive.xorWithKeystream(data)
|
|
||||||
// processPolyBytes(decrypted)
|
|
||||||
return decrypted
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processPolyBytes(updateableMacPrimitive: Poly1305, data: UByteArray) {
|
private fun processPolyBytes(updateableMacPrimitive: Poly1305, data: UByteArray) {
|
||||||
if (polyBufferByteCounter == 0) {
|
if (polyBufferByteCounter == 0) {
|
||||||
@ -284,16 +169,5 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun finishEncryption() : Pair<UByteArray, UByteArray> {
|
|
||||||
|
|
||||||
val cipherTextPad = UByteArray(16 - processedBytes % 16) { 0U }
|
|
||||||
val macData = cipherTextPad +
|
|
||||||
// additionalData.size.toULong().toLittleEndianUByteArray() +
|
|
||||||
processedBytes.toULong().toLittleEndianUByteArray()
|
|
||||||
// processPolyBytes(macData)
|
|
||||||
val tag = updateableMacPrimitive.finalizeMac()
|
|
||||||
return Pair(tag, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -207,6 +207,6 @@ class XChaCha20Poly1305Test {
|
|||||||
xcha.calcNonce.contentEquals(state.sliceArray(32 until 44))
|
xcha.calcNonce.contentEquals(state.sliceArray(32 until 44))
|
||||||
}
|
}
|
||||||
val data = UByteArray(100) { 0U }
|
val data = UByteArray(100) { 0U }
|
||||||
xcha.encryptPartial(data).hexColumsPrint()
|
xcha.streamEncrypt(data).hexColumsPrint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user