Change all occurences of additionalData to associatedData

This commit is contained in:
Ugljesa Jovanovic 2020-08-30 11:56:18 +02:00 committed by Ugljesa Jovanovic
parent 54489ef6cb
commit 3de04749ba
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
21 changed files with 142 additions and 142 deletions

View File

@ -54,16 +54,16 @@ interface HashApi {
} }
interface EncryptionApi { interface EncryptionApi {
fun encrypt(key: SymmetricKey, data : Encryptable<*>, additionalData : UByteArray) : EncryptedData fun encrypt(key: SymmetricKey, data : Encryptable<*>, associatedData : UByteArray) : EncryptedData
fun <T: Encryptable<T>> decrypt(key: SymmetricKey, encryptedData : EncryptedData, additionalData: UByteArray, byteArrayDeserializer : (UByteArray) -> T) : T fun <T: Encryptable<T>> decrypt(key: SymmetricKey, encryptedData : EncryptedData, associatedData: UByteArray, byteArrayDeserializer : (UByteArray) -> T) : T
fun createMultipartEncryptor(key: SymmetricKey) : MultipartAuthenticatedEncryption fun createMultipartEncryptor(key: SymmetricKey) : MultipartAuthenticatedEncryption
fun createMultipartDecryptor(key: SymmetricKey, header: MultipartEncryptionHeader) : MultipartAuthenticatedDecryption fun createMultipartDecryptor(key: SymmetricKey, header: MultipartEncryptionHeader) : MultipartAuthenticatedDecryption
} }
interface AuthenticatedEncryption { interface AuthenticatedEncryption {
fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, additionalData: UByteArray = ubyteArrayOf()) : UByteArray fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, associatedData: UByteArray = ubyteArrayOf()) : UByteArray
fun decrypt(key: UByteArray, nonce: UByteArray, cipherText: UByteArray, additionalData: UByteArray = ubyteArrayOf()) : UByteArray fun decrypt(key: UByteArray, nonce: UByteArray, cipherText: UByteArray, associatedData: UByteArray = ubyteArrayOf()) : UByteArray
} }
@ -75,12 +75,12 @@ 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 MultipartAuthenticatedDecryption { interface MultipartAuthenticatedDecryption {
fun decryptPartialData(data: EncryptedDataPart, additionalData: UByteArray = ubyteArrayOf()) : DecryptedDataPart fun decryptPartialData(data: EncryptedDataPart, associatedData: UByteArray = ubyteArrayOf()) : DecryptedDataPart
fun cleanup() fun cleanup()
} }
interface MultipartAuthenticatedEncryption { interface MultipartAuthenticatedEncryption {
fun encryptPartialData(data: UByteArray, additionalData: UByteArray = ubyteArrayOf()) : EncryptedDataPart fun encryptPartialData(data: UByteArray, associatedData: UByteArray = ubyteArrayOf()) : EncryptedDataPart
fun startEncryption() : MultipartEncryptionHeader fun startEncryption() : MultipartEncryptionHeader
fun cleanup() fun cleanup()

View File

@ -145,17 +145,17 @@ object Crypto {
} }
object Encryption : EncryptionApi { object Encryption : EncryptionApi {
override fun encrypt(key: SymmetricKey, data : Encryptable<*>, additionalData : UByteArray) : EncryptedData { override fun encrypt(key: SymmetricKey, data : Encryptable<*>, associatedData : UByteArray) : EncryptedData {
if (key.value.size != 32) { if (key.value.size != 32) {
throw RuntimeException("Invalid key size! Required 32, supplied ${key.value.size}") throw RuntimeException("Invalid key size! Required 32, supplied ${key.value.size}")
} }
val nonce = SRNG.getRandomBytes(24) val nonce = SRNG.getRandomBytes(24)
return EncryptedData(XChaCha20Poly1305Delegated.encrypt(key.value, nonce, data.toEncryptableForm(), additionalData), nonce) return EncryptedData(XChaCha20Poly1305Delegated.encrypt(key.value, nonce, data.toEncryptableForm(), associatedData), nonce)
} }
override fun <T: Encryptable<T>> decrypt(key: SymmetricKey, encryptedData : EncryptedData, additionalData: UByteArray, byteArrayDeserializer : (UByteArray) -> T) : T { override fun <T: Encryptable<T>> decrypt(key: SymmetricKey, encryptedData : EncryptedData, associatedData: UByteArray, byteArrayDeserializer : (UByteArray) -> T) : T {
return byteArrayDeserializer(XChaCha20Poly1305Delegated.decrypt(key.value, encryptedData.nonce, encryptedData.ciphertext, additionalData)) return byteArrayDeserializer(XChaCha20Poly1305Delegated.decrypt(key.value, encryptedData.nonce, encryptedData.ciphertext, associatedData))
} }
@ -185,8 +185,8 @@ class MultipartAuthenticatedEncryptor internal constructor(val key : SymmetricKe
return header return header
} }
override fun encryptPartialData(data: UByteArray, additionalData: UByteArray): EncryptedDataPart { override fun encryptPartialData(data: UByteArray, associatedData: UByteArray): EncryptedDataPart {
return EncryptedDataPart(primitive.encrypt(data, additionalData)) return EncryptedDataPart(primitive.encrypt(data, associatedData))
} }
override fun cleanup() { override fun cleanup() {
@ -196,8 +196,8 @@ class MultipartAuthenticatedEncryptor internal constructor(val key : SymmetricKe
class MultipartAuthenticatedDecryptor internal constructor(val decryptor: XChaCha20Poly1305Delegated) : MultipartAuthenticatedDecryption { class MultipartAuthenticatedDecryptor internal constructor(val decryptor: XChaCha20Poly1305Delegated) : MultipartAuthenticatedDecryption {
override fun decryptPartialData(data: EncryptedDataPart, additionalData: UByteArray): DecryptedDataPart { override fun decryptPartialData(data: EncryptedDataPart, associatedData: UByteArray): DecryptedDataPart {
return DecryptedDataPart(decryptor.decrypt(data.data, additionalData)) return DecryptedDataPart(decryptor.decrypt(data.data, associatedData))
} }
override fun cleanup() { override fun cleanup() {

View File

@ -9,13 +9,13 @@ package com.ionspin.kotlin.crypto.authenticated
expect class XChaCha20Poly1305Delegated internal constructor() { expect class XChaCha20Poly1305Delegated internal constructor() {
internal constructor(key: UByteArray, testState : UByteArray, testHeader: UByteArray, isDecryptor: Boolean) internal constructor(key: UByteArray, testState : UByteArray, testHeader: UByteArray, isDecryptor: Boolean)
companion object { companion object {
fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, additionalData: UByteArray) : UByteArray fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, associatedData: UByteArray) : UByteArray
fun decrypt(key: UByteArray, nonce: UByteArray, ciphertext: UByteArray, additionalData: UByteArray) : UByteArray fun decrypt(key: UByteArray, nonce: UByteArray, ciphertext: UByteArray, associatedData: UByteArray) : UByteArray
} }
fun initializeForEncryption(key: UByteArray) : UByteArray fun initializeForEncryption(key: UByteArray) : UByteArray
fun initializeForDecryption(key: UByteArray, header: UByteArray) fun initializeForDecryption(key: UByteArray, header: UByteArray)
fun encrypt(data: UByteArray, additionalData: UByteArray = ubyteArrayOf()) : UByteArray fun encrypt(data: UByteArray, associatedData: UByteArray = ubyteArrayOf()) : UByteArray
fun decrypt(data: UByteArray, additionalData: UByteArray = ubyteArrayOf()) : UByteArray fun decrypt(data: UByteArray, associatedData: UByteArray = ubyteArrayOf()) : UByteArray
fun cleanup() fun cleanup()

View File

@ -26,7 +26,7 @@ class XChaCha20Poly1305Test {
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
"only one tip for the future, sunscreen would be it.").encodeToUByteArray() "only one tip for the future, sunscreen would be it.").encodeToUByteArray()
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U 0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(
@ -61,9 +61,9 @@ class XChaCha20Poly1305Test {
0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU, 0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU,
0xcfU, 0x49U 0xcfU, 0x49U
) )
val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, additionalData) val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, associatedData)
encrypted.hexColumsPrint() encrypted.hexColumsPrint()
val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData) val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, associatedData)
println("Decrypted") println("Decrypted")
decrypted.hexColumsPrint() decrypted.hexColumsPrint()
println("----------") println("----------")
@ -74,7 +74,7 @@ class XChaCha20Poly1305Test {
val message = ubyteArrayOf( val message = ubyteArrayOf(
0x00U 0x00U
) )
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x00U 0x00U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(
@ -93,8 +93,8 @@ class XChaCha20Poly1305Test {
0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U, 0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U,
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU 0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
) )
val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, additionalData) val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, associatedData)
val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData) val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, associatedData)
encrypted.contentEquals(expected) && decrypted.contentEquals(message) encrypted.contentEquals(expected) && decrypted.contentEquals(message)
} }
@ -109,7 +109,7 @@ class XChaCha20Poly1305Test {
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
"only one tip for the future, sunscreen would be it.").encodeToUByteArray() "only one tip for the future, sunscreen would be it.").encodeToUByteArray()
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U 0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(
@ -144,7 +144,7 @@ class XChaCha20Poly1305Test {
0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU, 0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU,
0xcfU, 0x49U 0xcfU, 0x49U
) )
// val xChaChaPoly = XChaCha20Poly1305Delegated(key, additionalData) // val xChaChaPoly = XChaCha20Poly1305Delegated(key, associatedData)
// val firstChunk = xChaChaPoly.encrypt(message) // val firstChunk = xChaChaPoly.encrypt(message)
// val finalChunk = xChaChaPoly.finishEncryption().first // val finalChunk = xChaChaPoly.finishEncryption().first
// val result = firstChunk + finalChunk // val result = firstChunk + finalChunk
@ -157,7 +157,7 @@ class XChaCha20Poly1305Test {
val message = ubyteArrayOf( val message = ubyteArrayOf(
0x00U 0x00U
) )
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x00U 0x00U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(
@ -176,7 +176,7 @@ class XChaCha20Poly1305Test {
0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U, 0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U,
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, associatedData)
// val firstChunk = xChaChaPoly.encrypt(message) // val firstChunk = xChaChaPoly.encrypt(message)
// val finalChunk = xChaChaPoly.finishEncryption().first // val finalChunk = xChaChaPoly.finishEncryption().first
// val result = firstChunk + finalChunk // val result = firstChunk + finalChunk

View File

@ -22,17 +22,17 @@ class EncryptionTest {
val plaintext = ("pUoR4JVXJUeMKNkt6ZGGzEdTo33ajNGXwXpivBKA0XKs8toGRYI9Eul4bELRDkaQDNhd4vZseEFU" + val plaintext = ("pUoR4JVXJUeMKNkt6ZGGzEdTo33ajNGXwXpivBKA0XKs8toGRYI9Eul4bELRDkaQDNhd4vZseEFU" +
"ojsAn3c9zIifIrMnydSivHVZ2pBtpAQwYoJhYmEsfE0tROGnOwFWyB9K6LRSv1gB3YqKR9VyM8mpRoUM3UCRRjyiX7bnKdCE1" + "ojsAn3c9zIifIrMnydSivHVZ2pBtpAQwYoJhYmEsfE0tROGnOwFWyB9K6LRSv1gB3YqKR9VyM8mpRoUM3UCRRjyiX7bnKdCE1" +
"EiX0myiwcY1nUKTgB3keERWtMU07hX7bCtao5nRvDofSj3o3IInHRQh6opltr5asQwn4m1qn029QF").encodeToUByteArray() "EiX0myiwcY1nUKTgB3keERWtMU07hX7bCtao5nRvDofSj3o3IInHRQh6opltr5asQwn4m1qn029QF").encodeToUByteArray()
val additionalData = "Additional data 1".encodeToUByteArray() val associatedData = "Additional data 1".encodeToUByteArray()
val keyValue = UByteArray(32) { it.toUByte() } val keyValue = UByteArray(32) { it.toUByte() }
val key = SymmetricKey(keyValue) val key = SymmetricKey(keyValue)
val encryptor = Crypto.Encryption.createMultipartEncryptor(key) val encryptor = Crypto.Encryption.createMultipartEncryptor(key)
val header = encryptor.startEncryption() val header = encryptor.startEncryption()
val ciphertext1 = encryptor.encryptPartialData(plaintext.sliceArray(0 until 100), additionalData) val ciphertext1 = encryptor.encryptPartialData(plaintext.sliceArray(0 until 100), associatedData)
val ciphertext2 = encryptor.encryptPartialData(plaintext.sliceArray(100 until 200)) val ciphertext2 = encryptor.encryptPartialData(plaintext.sliceArray(100 until 200))
val ciphertext3 = encryptor.encryptPartialData(plaintext.sliceArray(200 until 250)) val ciphertext3 = encryptor.encryptPartialData(plaintext.sliceArray(200 until 250))
//decrypt //decrypt
val decryptor = Crypto.Encryption.createMultipartDecryptor(key, header) val decryptor = Crypto.Encryption.createMultipartDecryptor(key, header)
val plaintext1 = decryptor.decryptPartialData(ciphertext1, additionalData) val plaintext1 = decryptor.decryptPartialData(ciphertext1, associatedData)
val plaintext2 = decryptor.decryptPartialData(ciphertext2) val plaintext2 = decryptor.decryptPartialData(ciphertext2)
val plaintext3 = decryptor.decryptPartialData(ciphertext3) val plaintext3 = decryptor.decryptPartialData(ciphertext3)

View File

@ -40,17 +40,17 @@ interface JsSodiumInterface {
fun crypto_hash_sha512_final(state: dynamic): Uint8Array fun crypto_hash_sha512_final(state: dynamic): Uint8Array
//XChaCha20Poly1305 //XChaCha20Poly1305
fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, additionalData: Uint8Array, secretNonce: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, associatedData: Uint8Array, secretNonce: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
fun crypto_aead_xchacha20poly1305_ietf_decrypt(secretNonce: Uint8Array, ciphertext: Uint8Array, additionalData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array fun crypto_aead_xchacha20poly1305_ietf_decrypt(secretNonce: Uint8Array, ciphertext: Uint8Array, associatedData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
//XChaCha20Poly1305 //XChaCha20Poly1305
//encrypt //encrypt
fun crypto_secretstream_xchacha20poly1305_init_push(header: Uint8Array) : dynamic fun crypto_secretstream_xchacha20poly1305_init_push(header: Uint8Array) : dynamic
fun crypto_secretstream_xchacha20poly1305_push(state: dynamic, message: Uint8Array, additionalData: Uint8Array, tag: UByte) : Uint8Array fun crypto_secretstream_xchacha20poly1305_push(state: dynamic, message: Uint8Array, associatedData: Uint8Array, tag: UByte) : Uint8Array
//decrypt //decrypt
fun crypto_secretstream_xchacha20poly1305_init_pull(header: Uint8Array, key: Uint8Array) : dynamic fun crypto_secretstream_xchacha20poly1305_init_pull(header: Uint8Array, key: Uint8Array) : dynamic
fun crypto_secretstream_xchacha20poly1305_pull(state: dynamic, ciphertext: Uint8Array, additionalData: Uint8Array) : dynamic fun crypto_secretstream_xchacha20poly1305_pull(state: dynamic, ciphertext: Uint8Array, associatedData: Uint8Array) : dynamic
//util //util
fun memzero(array: Uint8Array) fun memzero(array: Uint8Array)

View File

@ -24,11 +24,11 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
key: UByteArray, key: UByteArray,
nonce: UByteArray, nonce: UByteArray,
message: UByteArray, message: UByteArray,
additionalData: UByteArray associatedData: UByteArray
): UByteArray { ): UByteArray {
val encrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_encrypt( val encrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_encrypt(
message.toUInt8Array(), message.toUInt8Array(),
additionalData.toUInt8Array(), associatedData.toUInt8Array(),
Uint8Array(0), Uint8Array(0),
nonce.toUInt8Array(), nonce.toUInt8Array(),
key.toUInt8Array() key.toUInt8Array()
@ -40,12 +40,12 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
key: UByteArray, key: UByteArray,
nonce: UByteArray, nonce: UByteArray,
ciphertext: UByteArray, ciphertext: UByteArray,
additionalData: UByteArray associatedData: UByteArray
): UByteArray { ): UByteArray {
val decrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_decrypt( val decrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_decrypt(
Uint8Array(0), Uint8Array(0),
ciphertext.toUInt8Array(), ciphertext.toUInt8Array(),
additionalData.toUInt8Array(), associatedData.toUInt8Array(),
nonce.toUInt8Array(), nonce.toUInt8Array(),
key.toUInt8Array() key.toUInt8Array()
) )
@ -92,25 +92,25 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
isEncryptor = !isDecryptor isEncryptor = !isDecryptor
} }
actual fun encrypt(data: UByteArray, additionalData: UByteArray): UByteArray { actual fun encrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
if (!isInitialized) { if (!isInitialized) {
throw RuntimeException("Not initalized!") throw RuntimeException("Not initalized!")
} }
if (!isEncryptor) { if (!isEncryptor) {
throw RuntimeException("Initialized as decryptor, attempted to use as encryptor") throw RuntimeException("Initialized as decryptor, attempted to use as encryptor")
} }
val encrypted = getSodium().crypto_secretstream_xchacha20poly1305_push(state, data.toUInt8Array(), additionalData.toUInt8Array(), 0U) val encrypted = getSodium().crypto_secretstream_xchacha20poly1305_push(state, data.toUInt8Array(), associatedData.toUInt8Array(), 0U)
return encrypted.toUByteArray() return encrypted.toUByteArray()
} }
actual fun decrypt(data: UByteArray, additionalData: UByteArray): UByteArray { actual fun decrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
if (!isInitialized) { if (!isInitialized) {
throw RuntimeException("Not initalized!") throw RuntimeException("Not initalized!")
} }
if (isEncryptor) { if (isEncryptor) {
throw RuntimeException("Initialized as encryptor, attempted to use as decryptor") throw RuntimeException("Initialized as encryptor, attempted to use as decryptor")
} }
val decryptedWithTag = getSodium().crypto_secretstream_xchacha20poly1305_pull(state, data.toUInt8Array(), additionalData.toUInt8Array()) val decryptedWithTag = getSodium().crypto_secretstream_xchacha20poly1305_pull(state, data.toUInt8Array(), associatedData.toUInt8Array())
val decrypted = decryptedWithTag.message as Uint8Array val decrypted = decryptedWithTag.message as Uint8Array
val validTag = decryptedWithTag.tag val validTag = decryptedWithTag.tag

View File

@ -16,7 +16,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
key: UByteArray, key: UByteArray,
nonce: UByteArray, nonce: UByteArray,
message: UByteArray, message: UByteArray,
additionalData: UByteArray associatedData: UByteArray
): UByteArray { ): UByteArray {
val ciphertext = ByteArray(message.size + 16) val ciphertext = ByteArray(message.size + 16)
SodiumJava().crypto_aead_xchacha20poly1305_ietf_encrypt( SodiumJava().crypto_aead_xchacha20poly1305_ietf_encrypt(
@ -24,8 +24,8 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
longArrayOf(ciphertext.size.toLong()), longArrayOf(ciphertext.size.toLong()),
message.toByteArray(), message.toByteArray(),
message.size.toLong(), message.size.toLong(),
additionalData.toByteArray(), associatedData.toByteArray(),
additionalData.size.toLong(), associatedData.size.toLong(),
null, null,
nonce.toByteArray(), nonce.toByteArray(),
key.toByteArray() key.toByteArray()
@ -38,7 +38,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
key: UByteArray, key: UByteArray,
nonce: UByteArray, nonce: UByteArray,
ciphertext: UByteArray, ciphertext: UByteArray,
additionalData: UByteArray associatedData: UByteArray
): UByteArray { ): UByteArray {
val message = ByteArray(ciphertext.size - 16) val message = ByteArray(ciphertext.size - 16)
SodiumJava().crypto_aead_xchacha20poly1305_ietf_decrypt( SodiumJava().crypto_aead_xchacha20poly1305_ietf_decrypt(
@ -47,8 +47,8 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
null, null,
ciphertext.toByteArray(), ciphertext.toByteArray(),
ciphertext.size.toLong(), ciphertext.size.toLong(),
additionalData.toByteArray(), associatedData.toByteArray(),
additionalData.size.toLong(), associatedData.size.toLong(),
nonce.toByteArray(), nonce.toByteArray(),
key.toByteArray() key.toByteArray()
@ -89,7 +89,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
isEncryptor = false isEncryptor = false
} }
actual fun encrypt(data: UByteArray, additionalData: UByteArray): UByteArray { actual fun encrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
if (!isInitialized) { if (!isInitialized) {
throw RuntimeException("Not initalized!") throw RuntimeException("Not initalized!")
} }
@ -100,13 +100,13 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
sodium.crypto_secretstream_xchacha20poly1305_push( sodium.crypto_secretstream_xchacha20poly1305_push(
state, ciphertext, null, state, ciphertext, null,
data.asByteArray(), data.size.toLong(), data.asByteArray(), data.size.toLong(),
additionalData.asByteArray(), additionalData.size.toLong(), associatedData.asByteArray(), associatedData.size.toLong(),
0 0
) )
return ciphertext.asUByteArray() return ciphertext.asUByteArray()
} }
actual fun decrypt(data: UByteArray, additionalData: UByteArray): UByteArray { actual fun decrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
if (!isInitialized) { if (!isInitialized) {
throw RuntimeException("Not initalized!") throw RuntimeException("Not initalized!")
} }
@ -120,8 +120,8 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
null, null,
data.asByteArray(), data.asByteArray(),
(data.size).toLong(), (data.size).toLong(),
additionalData.asByteArray(), associatedData.asByteArray(),
additionalData.size.toLong() associatedData.size.toLong()
) )
if (validTag != 0) { if (validTag != 0) {
println("Tag validation failed") println("Tag validation failed")

View File

@ -17,7 +17,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
key: UByteArray, key: UByteArray,
nonce: UByteArray, nonce: UByteArray,
message: UByteArray, message: UByteArray,
additionalData: UByteArray associatedData: UByteArray
): UByteArray { ): UByteArray {
val ciphertextLength = message.size + crypto_aead_xchacha20poly1305_IETF_ABYTES.toInt() val ciphertextLength = message.size + crypto_aead_xchacha20poly1305_IETF_ABYTES.toInt()
val ciphertext = UByteArray(ciphertextLength) val ciphertext = UByteArray(ciphertextLength)
@ -27,8 +27,8 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
ulongArrayOf(ciphertextLength.convert()).toCValues(), ulongArrayOf(ciphertextLength.convert()).toCValues(),
message.toCValues(), message.toCValues(),
message.size.convert(), message.size.convert(),
additionalData.toCValues(), associatedData.toCValues(),
additionalData.size.convert(), associatedData.size.convert(),
null, null,
nonce.toCValues(), nonce.toCValues(),
key.toCValues() key.toCValues()
@ -41,7 +41,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
key: UByteArray, key: UByteArray,
nonce: UByteArray, nonce: UByteArray,
ciphertext: UByteArray, ciphertext: UByteArray,
additionalData: UByteArray associatedData: UByteArray
): UByteArray { ): UByteArray {
val messageLength = ciphertext.size - crypto_aead_xchacha20poly1305_IETF_ABYTES.toInt() val messageLength = ciphertext.size - crypto_aead_xchacha20poly1305_IETF_ABYTES.toInt()
val message = UByteArray(messageLength) val message = UByteArray(messageLength)
@ -52,8 +52,8 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
null, null,
ciphertext.toCValues(), ciphertext.toCValues(),
ciphertext.size.convert(), ciphertext.size.convert(),
additionalData.toCValues(), associatedData.toCValues(),
additionalData.size.convert(), associatedData.size.convert(),
nonce.toCValues(), nonce.toCValues(),
key.toCValues() key.toCValues()
) )
@ -112,7 +112,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
} }
actual fun encrypt(data: UByteArray, additionalData: UByteArray): UByteArray { actual fun encrypt(data: UByteArray, associatedData: 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(
@ -121,8 +121,8 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
null, null,
data.toCValues(), data.toCValues(),
data.size.convert(), data.size.convert(),
additionalData.toCValues(), associatedData.toCValues(),
additionalData.size.convert(), associatedData.size.convert(),
0U, 0U,
) )
println("Encrypt partial") println("Encrypt partial")
@ -132,7 +132,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
return ciphertextWithTag return ciphertextWithTag
} }
actual fun decrypt(data: UByteArray, additionalData: UByteArray): UByteArray { actual fun decrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
val plaintext = UByteArray(data.size - crypto_secretstream_xchacha20poly1305_ABYTES.toInt()) val plaintext = UByteArray(data.size - crypto_secretstream_xchacha20poly1305_ABYTES.toInt())
val plaintextPinned = plaintext.pin() val plaintextPinned = plaintext.pin()
val validTag = crypto_secretstream_xchacha20poly1305_pull( val validTag = crypto_secretstream_xchacha20poly1305_pull(
@ -142,8 +142,8 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
null, null,
data.toCValues(), data.toCValues(),
data.size.convert(), data.size.convert(),
additionalData.toCValues(), associatedData.toCValues(),
additionalData.size.convert() associatedData.size.convert()
) )
plaintextPinned.unpin() plaintextPinned.unpin()
println("tag: $validTag") println("tag: $validTag")

View File

@ -27,9 +27,9 @@ class SecretStreamCorrupedOrTamperedDataException() : RuntimeException("MAC vali
expect object SecretStream { expect object SecretStream {
fun xChaCha20Poly1305InitPush(key: UByteArray) : SecretStreamStateAndHeader fun xChaCha20Poly1305InitPush(key: UByteArray) : SecretStreamStateAndHeader
fun xChaCha20Poly1305Push(state : SecretStreamState, message: UByteArray, additionalData : UByteArray = ubyteArrayOf(), tag: UByte) : UByteArray fun xChaCha20Poly1305Push(state : SecretStreamState, message: UByteArray, associatedData : UByteArray = ubyteArrayOf(), tag: UByte) : UByteArray
fun xChaCha20Poly1305InitPull(key: UByteArray, header: UByteArray) : SecretStreamStateAndHeader fun xChaCha20Poly1305InitPull(key: UByteArray, header: UByteArray) : SecretStreamStateAndHeader
fun xChaCha20Poly1305Pull(state : SecretStreamState, ciphertext: UByteArray, additionalData : UByteArray = ubyteArrayOf()) : DecryptedDataAndTag fun xChaCha20Poly1305Pull(state : SecretStreamState, ciphertext: UByteArray, associatedData : UByteArray = ubyteArrayOf()) : DecryptedDataAndTag
fun xChaCha20Poly1305Keygen() : UByteArray fun xChaCha20Poly1305Keygen() : UByteArray
fun xChaCha20Poly1305Rekey(state: SecretStreamState) fun xChaCha20Poly1305Rekey(state: SecretStreamState)

View File

@ -22,7 +22,7 @@ class SecretStreamTest {
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
"only one tip for the future, sunscreen would be it.").encodeToUByteArray() "only one tip for the future, sunscreen would be it.").encodeToUByteArray()
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U 0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(

View File

@ -45,17 +45,17 @@ interface JsSodiumInterface {
fun crypto_hash_sha512_final(state: dynamic): Uint8Array fun crypto_hash_sha512_final(state: dynamic): Uint8Array
//XChaCha20Poly1305 //XChaCha20Poly1305
fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, additionalData: Uint8Array, secretNonce: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, associatedData: Uint8Array, secretNonce: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
fun crypto_aead_xchacha20poly1305_ietf_decrypt(secretNonce: Uint8Array, ciphertext: Uint8Array, additionalData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array fun crypto_aead_xchacha20poly1305_ietf_decrypt(secretNonce: Uint8Array, ciphertext: Uint8Array, associatedData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
//XChaCha20Poly1305 //XChaCha20Poly1305
//encrypt //encrypt
fun crypto_secretstream_xchacha20poly1305_init_push(key: Uint8Array) : dynamic fun crypto_secretstream_xchacha20poly1305_init_push(key: Uint8Array) : dynamic
fun crypto_secretstream_xchacha20poly1305_push(state: dynamic, message: Uint8Array, additionalData: Uint8Array, tag: UByte) : Uint8Array fun crypto_secretstream_xchacha20poly1305_push(state: dynamic, message: Uint8Array, associatedData: Uint8Array, tag: UByte) : Uint8Array
//decrypt //decrypt
fun crypto_secretstream_xchacha20poly1305_init_pull(header: Uint8Array, key: Uint8Array) : dynamic fun crypto_secretstream_xchacha20poly1305_init_pull(header: Uint8Array, key: Uint8Array) : dynamic
fun crypto_secretstream_xchacha20poly1305_pull(state: dynamic, ciphertext: Uint8Array, additionalData: Uint8Array) : dynamic fun crypto_secretstream_xchacha20poly1305_pull(state: dynamic, ciphertext: Uint8Array, associatedData: Uint8Array) : dynamic
//keygen and rekey //keygen and rekey
fun crypto_secretstream_xchacha20poly1305_keygen() : Uint8Array fun crypto_secretstream_xchacha20poly1305_keygen() : Uint8Array

View File

@ -16,11 +16,11 @@ actual object SecretStream {
actual fun xChaCha20Poly1305Push( actual fun xChaCha20Poly1305Push(
state: SecretStreamState, state: SecretStreamState,
message: UByteArray, message: UByteArray,
additionalData: UByteArray, associatedData: UByteArray,
tag: UByte tag: UByte
): UByteArray { ): UByteArray {
return getSodium().crypto_secretstream_xchacha20poly1305_push( return getSodium().crypto_secretstream_xchacha20poly1305_push(
state, message.toUInt8Array(), additionalData.toUInt8Array(), tag state, message.toUInt8Array(), associatedData.toUInt8Array(), tag
).toUByteArray() ).toUByteArray()
} }
@ -35,10 +35,10 @@ actual object SecretStream {
actual fun xChaCha20Poly1305Pull( actual fun xChaCha20Poly1305Pull(
state: SecretStreamState, state: SecretStreamState,
ciphertext: UByteArray, ciphertext: UByteArray,
additionalData: UByteArray associatedData: UByteArray
): DecryptedDataAndTag { ): DecryptedDataAndTag {
val dataAndTag = getSodium().crypto_secretstream_xchacha20poly1305_pull( val dataAndTag = getSodium().crypto_secretstream_xchacha20poly1305_pull(
state, ciphertext.toUInt8Array(), additionalData.toUInt8Array() state, ciphertext.toUInt8Array(), associatedData.toUInt8Array()
) )
if (dataAndTag == false) { if (dataAndTag == false) {
throw SecretStreamCorrupedOrTamperedDataException() throw SecretStreamCorrupedOrTamperedDataException()

View File

@ -16,7 +16,7 @@ actual object SecretStream {
actual fun xChaCha20Poly1305Push( actual fun xChaCha20Poly1305Push(
state: SecretStreamState, state: SecretStreamState,
message: UByteArray, message: UByteArray,
additionalData: UByteArray, associatedData: UByteArray,
tag: UByte tag: UByte
): UByteArray { ): UByteArray {
val ciphertext = UByteArray(message.size + crypto_secretstream_xchacha20poly1305_ABYTES) val ciphertext = UByteArray(message.size + crypto_secretstream_xchacha20poly1305_ABYTES)
@ -26,8 +26,8 @@ actual object SecretStream {
null, null,
message.asByteArray(), message.asByteArray(),
message.size.toLong(), message.size.toLong(),
additionalData.asByteArray(), associatedData.asByteArray(),
additionalData.size.toLong(), associatedData.size.toLong(),
tag.toByte() tag.toByte()
) )
return ciphertext return ciphertext
@ -45,7 +45,7 @@ actual object SecretStream {
actual fun xChaCha20Poly1305Pull( actual fun xChaCha20Poly1305Pull(
state: SecretStreamState, state: SecretStreamState,
ciphertext: UByteArray, ciphertext: UByteArray,
additionalData: UByteArray associatedData: UByteArray
): DecryptedDataAndTag { ): DecryptedDataAndTag {
val result = UByteArray(ciphertext.size - crypto_secretstream_xchacha20poly1305_ABYTES) val result = UByteArray(ciphertext.size - crypto_secretstream_xchacha20poly1305_ABYTES)
val tagArray = UByteArray(1) { 0U } val tagArray = UByteArray(1) { 0U }
@ -56,8 +56,8 @@ actual object SecretStream {
tagArray.asByteArray(), tagArray.asByteArray(),
ciphertext.asByteArray(), ciphertext.asByteArray(),
ciphertext.size.toLong(), ciphertext.size.toLong(),
additionalData.asByteArray(), associatedData.asByteArray(),
additionalData.size.toLong() associatedData.size.toLong()
) )
if (validationResult != 0) { if (validationResult != 0) {
throw SecretStreamCorrupedOrTamperedDataException() throw SecretStreamCorrupedOrTamperedDataException()

View File

@ -40,14 +40,14 @@ actual object SecretStream {
actual fun xChaCha20Poly1305Push( actual fun xChaCha20Poly1305Push(
state: SecretStreamState, state: SecretStreamState,
message: UByteArray, message: UByteArray,
additionalData: UByteArray, associatedData: UByteArray,
tag: UByte tag: UByte
): UByteArray { ): UByteArray {
val ciphertext = UByteArray(message.size + crypto_secretstream_xchacha20poly1305_ABYTES.toInt()) { 0U } val ciphertext = UByteArray(message.size + crypto_secretstream_xchacha20poly1305_ABYTES.toInt()) { 0U }
val ciphertextPinned = ciphertext.pin() val ciphertextPinned = ciphertext.pin()
val messagePinned = message.pin() val messagePinned = message.pin()
val additionalDataPinned = if (additionalData.isNotEmpty()) { val associatedDataPinned = if (associatedData.isNotEmpty()) {
additionalData.pin() associatedData.pin()
} else { } else {
null null
} }
@ -57,14 +57,14 @@ actual object SecretStream {
null, null,
messagePinned.toPtr(), messagePinned.toPtr(),
message.size.convert(), message.size.convert(),
additionalDataPinned?.toPtr(), associatedDataPinned?.toPtr(),
additionalData.size.convert(), associatedData.size.convert(),
tag tag
) )
ciphertextPinned.unpin() ciphertextPinned.unpin()
messagePinned.unpin() messagePinned.unpin()
additionalDataPinned?.unpin() associatedDataPinned?.unpin()
return ciphertext return ciphertext
} }
@ -89,13 +89,13 @@ actual object SecretStream {
actual fun xChaCha20Poly1305Pull( actual fun xChaCha20Poly1305Pull(
state: SecretStreamState, state: SecretStreamState,
ciphertext: UByteArray, ciphertext: UByteArray,
additionalData: UByteArray associatedData: UByteArray
): DecryptedDataAndTag { ): DecryptedDataAndTag {
val message = UByteArray(ciphertext.size - crypto_secretstream_xchacha20poly1305_ABYTES.toInt()) val message = UByteArray(ciphertext.size - crypto_secretstream_xchacha20poly1305_ABYTES.toInt())
val messagePinned = message.pin() val messagePinned = message.pin()
val ciphertextPinned = ciphertext.pin() val ciphertextPinned = ciphertext.pin()
val additionalDataPinned = if (additionalData.isNotEmpty()) { val associatedDataPinned = if (associatedData.isNotEmpty()) {
additionalData.pin() associatedData.pin()
} else { } else {
null null
} }
@ -108,12 +108,12 @@ actual object SecretStream {
tagPinned.toPtr(), tagPinned.toPtr(),
ciphertextPinned.toPtr(), ciphertextPinned.toPtr(),
ciphertext.size.convert(), ciphertext.size.convert(),
additionalDataPinned?.toPtr(), associatedDataPinned?.toPtr(),
additionalData.size.convert() associatedData.size.convert()
) )
ciphertextPinned.unpin() ciphertextPinned.unpin()
messagePinned.unpin() messagePinned.unpin()
additionalDataPinned?.unpin() associatedDataPinned?.unpin()
tagPinned.unpin() tagPinned.unpin()
if (validationResult != 0) { if (validationResult != 0) {
throw SecretStreamCorrupedOrTamperedDataException() throw SecretStreamCorrupedOrTamperedDataException()

View File

@ -102,17 +102,17 @@ object Crypto {
} }
object Encryption : EncryptionApi { object Encryption : EncryptionApi {
override fun encrypt(key: SymmetricKey, data : Encryptable<*>, additionalData : UByteArray) : EncryptedData { override fun encrypt(key: SymmetricKey, data : Encryptable<*>, associatedData : UByteArray) : EncryptedData {
if (key.value.size != 32) { if (key.value.size != 32) {
throw RuntimeException("Invalid key size! Required 32, supplied ${key.value.size}") throw RuntimeException("Invalid key size! Required 32, supplied ${key.value.size}")
} }
val nonce = SRNG.getRandomBytes(24) val nonce = SRNG.getRandomBytes(24)
return EncryptedData(XChaCha20Poly1305Pure.encrypt(key.value, nonce, data.toEncryptableForm(), additionalData), nonce) return EncryptedData(XChaCha20Poly1305Pure.encrypt(key.value, nonce, data.toEncryptableForm(), associatedData), nonce)
} }
override fun <T: Encryptable<T>> decrypt(key: SymmetricKey, encryptedData : EncryptedData, additionalData: UByteArray, byteArrayDeserializer : (UByteArray) -> T) : T { override fun <T: Encryptable<T>> decrypt(key: SymmetricKey, encryptedData : EncryptedData, associatedData: UByteArray, byteArrayDeserializer : (UByteArray) -> T) : T {
return byteArrayDeserializer(XChaCha20Poly1305Pure.decrypt(key.value, encryptedData.nonce, encryptedData.ciphertext, additionalData)) return byteArrayDeserializer(XChaCha20Poly1305Pure.decrypt(key.value, encryptedData.nonce, encryptedData.ciphertext, associatedData))
} }
@ -130,8 +130,8 @@ object Crypto {
class MultipartAuthenticatedEncryptor internal constructor(val key : SymmetricKey) : MultipartAuthenticatedEncryption { class MultipartAuthenticatedEncryptor internal constructor(val key : SymmetricKey) : MultipartAuthenticatedEncryption {
val header = MultipartEncryptionHeader(SRNG.getRandomBytes(24)) val header = MultipartEncryptionHeader(SRNG.getRandomBytes(24))
val primitive = XChaCha20Poly1305Pure(key.value, header.nonce) val primitive = XChaCha20Poly1305Pure(key.value, header.nonce)
override fun encryptPartialData(data: UByteArray, additionalData: UByteArray): EncryptedDataPart { override fun encryptPartialData(data: UByteArray, associatedData: UByteArray): EncryptedDataPart {
return EncryptedDataPart(primitive.streamEncrypt(data, additionalData, 0U)) return EncryptedDataPart(primitive.streamEncrypt(data, associatedData, 0U))
} }
override fun startEncryption(): MultipartEncryptionHeader { override fun startEncryption(): MultipartEncryptionHeader {
@ -144,8 +144,8 @@ class MultipartAuthenticatedEncryptor internal constructor(val key : SymmetricKe
} }
class MultipartAuthenticatedDecryptor internal constructor(val decryptor: XChaCha20Poly1305Pure) : MultipartAuthenticatedDecryption { class MultipartAuthenticatedDecryptor internal constructor(val decryptor: XChaCha20Poly1305Pure) : MultipartAuthenticatedDecryption {
override fun decryptPartialData(data: EncryptedDataPart, additionalData: UByteArray): DecryptedDataPart { override fun decryptPartialData(data: EncryptedDataPart, associatedData: UByteArray): DecryptedDataPart {
return DecryptedDataPart(decryptor.streamDecrypt(data.data, additionalData, 0U)) return DecryptedDataPart(decryptor.streamDecrypt(data.data, associatedData, 0U))
} }
override fun cleanup() { override fun cleanup() {

View File

@ -13,7 +13,7 @@ import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray
internal class ChaCha20Poly1305Pure { internal class ChaCha20Poly1305Pure {
companion object { companion object {
fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, additionalData: UByteArray) : UByteArray { fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, associatedData: UByteArray) : UByteArray {
val state = UIntArray(16) { val state = UIntArray(16) {
when (it) { when (it) {
0 -> ChaCha20Pure.sigma0_32 0 -> ChaCha20Pure.sigma0_32
@ -37,11 +37,11 @@ internal class ChaCha20Poly1305Pure {
} }
val oneTimeKey = ChaCha20Pure.hash(state).sliceArray(0 until 32) val oneTimeKey = ChaCha20Pure.hash(state).sliceArray(0 until 32)
val cipherText = ChaCha20Pure.xorWithKeystream(key, nonce, message, 1U) val cipherText = ChaCha20Pure.xorWithKeystream(key, nonce, message, 1U)
val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U } val associatedDataPad = UByteArray(16 - associatedData.size % 16) { 0U }
val cipherTextPad = UByteArray(16 - cipherText.size % 16) { 0U } val cipherTextPad = UByteArray(16 - cipherText.size % 16) { 0U }
val macData = additionalData + additionalDataPad + val macData = associatedData + associatedDataPad +
cipherText + cipherTextPad + cipherText + cipherTextPad +
additionalData.size.toULong().toLittleEndianUByteArray() + associatedData.size.toULong().toLittleEndianUByteArray() +
cipherText.size.toULong().toLittleEndianUByteArray() cipherText.size.toULong().toLittleEndianUByteArray()
val tag = Poly1305.poly1305Authenticate(oneTimeKey, macData) val tag = Poly1305.poly1305Authenticate(oneTimeKey, macData)
return cipherText + tag return cipherText + tag

View File

@ -15,7 +15,7 @@ import com.ionspin.kotlin.crypto.util.*
class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) { class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) {
companion object : AuthenticatedEncryption { companion object : AuthenticatedEncryption {
override fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, additionalData: UByteArray) : UByteArray { override fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, associatedData: UByteArray) : UByteArray {
val subKey = XChaCha20Pure.hChacha(key, nonce) val subKey = XChaCha20Pure.hChacha(key, nonce)
val authKey = val authKey =
ChaCha20Pure.xorWithKeystream( ChaCha20Pure.xorWithKeystream(
@ -28,17 +28,17 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) {
// at org.jetbrains.kotlin.ir.backend.js.lower.ConstTransformer.lowerConst(ConstLowering.kt:38) // at org.jetbrains.kotlin.ir.backend.js.lower.ConstTransformer.lowerConst(ConstLowering.kt:38)
) )
val cipherText = XChaCha20Pure.xorWithKeystream(key, nonce, message, 1U) val cipherText = XChaCha20Pure.xorWithKeystream(key, nonce, message, 1U)
val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U } val associatedDataPad = UByteArray(16 - associatedData.size % 16) { 0U }
val cipherTextPad = UByteArray(16 - cipherText.size % 16) { 0U } val cipherTextPad = UByteArray(16 - cipherText.size % 16) { 0U }
val macData = additionalData + additionalDataPad + val macData = associatedData + associatedDataPad +
cipherText + cipherTextPad + cipherText + cipherTextPad +
additionalData.size.toULong().toLittleEndianUByteArray() + associatedData.size.toULong().toLittleEndianUByteArray() +
cipherText.size.toULong().toLittleEndianUByteArray() cipherText.size.toULong().toLittleEndianUByteArray()
val tag = Poly1305.poly1305Authenticate(authKey, macData) val tag = Poly1305.poly1305Authenticate(authKey, macData)
return cipherText + tag return cipherText + tag
} }
override fun decrypt(key: UByteArray, nonce: UByteArray, cipherText: UByteArray, additionalData: UByteArray) : UByteArray { override fun decrypt(key: UByteArray, nonce: UByteArray, cipherText: UByteArray, associatedData: UByteArray) : UByteArray {
val subKey = XChaCha20Pure.hChacha(key, nonce) val subKey = XChaCha20Pure.hChacha(key, nonce)
val authKey = val authKey =
ChaCha20Pure.xorWithKeystream( ChaCha20Pure.xorWithKeystream(
@ -51,11 +51,11 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) {
val tag = cipherText.sliceArray(cipherText.size - 16 until cipherText.size) val tag = cipherText.sliceArray(cipherText.size - 16 until cipherText.size)
//3. Verify tag is valid //3. Verify tag is valid
val cipherTextWithoutTag = cipherText.sliceArray(0 until cipherText.size - 16) val cipherTextWithoutTag = cipherText.sliceArray(0 until cipherText.size - 16)
val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U } val associatedDataPad = UByteArray(16 - associatedData.size % 16) { 0U }
val cipherTextPad = UByteArray(16 - cipherTextWithoutTag.size % 16) { 0U } val cipherTextPad = UByteArray(16 - cipherTextWithoutTag.size % 16) { 0U }
val macData = additionalData + additionalDataPad + val macData = associatedData + associatedDataPad +
cipherTextWithoutTag + cipherTextPad + cipherTextWithoutTag + cipherTextPad +
additionalData.size.toULong().toLittleEndianUByteArray() + associatedData.size.toULong().toLittleEndianUByteArray() +
cipherTextWithoutTag.size.toULong().toLittleEndianUByteArray() cipherTextWithoutTag.size.toULong().toLittleEndianUByteArray()
val calculatedTag = Poly1305.poly1305Authenticate(authKey, macData) val calculatedTag = Poly1305.poly1305Authenticate(authKey, macData)
if (!calculatedTag.contentEquals(tag)) { if (!calculatedTag.contentEquals(tag)) {
@ -86,15 +86,15 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) {
calcNonce[3] = 0U calcNonce[3] = 0U
} }
fun streamEncrypt(data: UByteArray, additionalData: UByteArray, tag : UByte) : UByteArray { fun streamEncrypt(data: UByteArray, associatedData: UByteArray, tag : UByte) : UByteArray {
//get encryption state //get encryption state
val block = UByteArray(64) { 0U } val block = UByteArray(64) { 0U }
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
val poly1305 = Poly1305(block) val poly1305 = Poly1305(block)
block.overwriteWithZeroes() block.overwriteWithZeroes()
if (additionalData.isNotEmpty()) { if (associatedData.isNotEmpty()) {
val additionalDataPadded = additionalData + UByteArray(16 - additionalData.size % 16) { 0U } val associatedDataPadded = associatedData + UByteArray(16 - associatedData.size % 16) { 0U }
processPolyBytes(poly1305, additionalDataPadded) processPolyBytes(poly1305, associatedDataPadded)
} }
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
@ -109,21 +109,21 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) {
// From security standpoint there are no obvious drawbacks, as padding was initially added to decrease implementation complexity. // From security standpoint there are no obvious drawbacks, as padding was initially added to decrease implementation complexity.
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
// Last 16byte block containing actual additional data nad ciphertext sizes // Last 16byte block containing actual additional data nad ciphertext sizes
val finalMac = additionalData.size.toULong().toLittleEndianUByteArray() + (ciphertext.size + 64).toULong().toLittleEndianUByteArray() val finalMac = associatedData.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))
calcNonce.xorWithPositionsAndInsertIntoArray(0, 12, mac, 0, calcNonce, 0) calcNonce.xorWithPositionsAndInsertIntoArray(0, 12, mac, 0, calcNonce, 0)
return ubyteArrayOf(encryptedTag) + ciphertext + mac return ubyteArrayOf(encryptedTag) + ciphertext + mac
} }
fun streamDecrypt(data: UByteArray, additionalData: UByteArray, tag: UByte) : UByteArray { fun streamDecrypt(data: UByteArray, associatedData: UByteArray, tag: UByte) : UByteArray {
val block = UByteArray(64) { 0U } val block = UByteArray(64) { 0U }
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
val poly1305 = Poly1305(block) val poly1305 = Poly1305(block)
block.overwriteWithZeroes() block.overwriteWithZeroes()
if (additionalData.isNotEmpty()) { if (associatedData.isNotEmpty()) {
val additionalDataPadded = additionalData + UByteArray(16 - additionalData.size % 16) { 0U } val associatedDataPadded = associatedData + UByteArray(16 - associatedData.size % 16) { 0U }
processPolyBytes(poly1305, additionalDataPadded) processPolyBytes(poly1305, associatedDataPadded)
} }
block[0] = data[0] block[0] = data[0]
ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, block, 1U).copyInto(block)// get the keystream xored with zeroes, but also decrypteg tag marker ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, block, 1U).copyInto(block)// get the keystream xored with zeroes, but also decrypteg tag marker
@ -137,7 +137,7 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) {
val ciphertext = data.sliceArray(1 until data.size - 16) val ciphertext = data.sliceArray(1 until data.size - 16)
processPolyBytes(poly1305, ciphertext + UByteArray(((16U + ciphertext.size.toUInt() - block.size.toUInt()) % 16U).toInt()) { 0U } ) processPolyBytes(poly1305, ciphertext + UByteArray(((16U + ciphertext.size.toUInt() - block.size.toUInt()) % 16U).toInt()) { 0U } )
val plaintext = ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, ciphertext, 2U) val plaintext = ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, ciphertext, 2U)
val finalMac = additionalData.size.toULong().toLittleEndianUByteArray() + (ciphertext.size + 64).toULong().toLittleEndianUByteArray() val finalMac = associatedData.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))
val expectedMac = data.sliceArray(data.size - 16 until data.size) val expectedMac = data.sliceArray(data.size - 16 until data.size)

View File

@ -19,7 +19,7 @@ class ChaCha20Poly1305Test {
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
"only one tip for the future, sunscreen would be it.").encodeToUByteArray() "only one tip for the future, sunscreen would be it.").encodeToUByteArray()
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U 0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(
@ -44,7 +44,7 @@ class ChaCha20Poly1305Test {
0x61U, 0x16U, 0x1aU, 0xe1U, 0x0bU, 0x59U, 0x4fU, 0x09U, 0xe2U, 0x6aU, 0x7eU, 0x90U, 0x2eU, 0xcbU, 0xd0U, 0x60U, 0x61U, 0x16U, 0x1aU, 0xe1U, 0x0bU, 0x59U, 0x4fU, 0x09U, 0xe2U, 0x6aU, 0x7eU, 0x90U, 0x2eU, 0xcbU, 0xd0U, 0x60U,
0x06U, 0x91U 0x06U, 0x91U
) )
val result = ChaCha20Poly1305Pure.encrypt(key, nonce, message, additionalData) val result = ChaCha20Poly1305Pure.encrypt(key, nonce, message, associatedData)
result.hexColumsPrint() result.hexColumsPrint()
assertTrue { assertTrue {
result.contentEquals(expected) result.contentEquals(expected)
@ -53,4 +53,4 @@ class ChaCha20Poly1305Test {
} }
} }

View File

@ -20,7 +20,7 @@ class XChaCha20Poly1305Test {
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
"only one tip for the future, sunscreen would be it.").encodeToUByteArray() "only one tip for the future, sunscreen would be it.").encodeToUByteArray()
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U 0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(
@ -55,8 +55,8 @@ class XChaCha20Poly1305Test {
0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU, 0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU,
0xcfU, 0x49U 0xcfU, 0x49U
) )
val encrypted = XChaCha20Poly1305Pure.encrypt(key, nonce, message, additionalData) val encrypted = XChaCha20Poly1305Pure.encrypt(key, nonce, message, associatedData)
val decrypted = XChaCha20Poly1305Pure.decrypt(key, nonce, encrypted, additionalData) val decrypted = XChaCha20Poly1305Pure.decrypt(key, nonce, encrypted, associatedData)
encrypted.contentEquals(expected) && decrypted.contentEquals(message) encrypted.contentEquals(expected) && decrypted.contentEquals(message)
} }
@ -65,7 +65,7 @@ class XChaCha20Poly1305Test {
val message = ubyteArrayOf( val message = ubyteArrayOf(
0x00U 0x00U
) )
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x00U 0x00U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(
@ -84,8 +84,8 @@ class XChaCha20Poly1305Test {
0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U, 0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U,
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU 0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
) )
val encrypted = XChaCha20Poly1305Pure.encrypt(key, nonce, message, additionalData) val encrypted = XChaCha20Poly1305Pure.encrypt(key, nonce, message, associatedData)
val decrypted = XChaCha20Poly1305Pure.decrypt(key, nonce, encrypted, additionalData) val decrypted = XChaCha20Poly1305Pure.decrypt(key, nonce, encrypted, associatedData)
encrypted.contentEquals(expected) && decrypted.contentEquals(message) encrypted.contentEquals(expected) && decrypted.contentEquals(message)
} }
@ -99,7 +99,7 @@ class XChaCha20Poly1305Test {
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
"only one tip for the future, sunscreen would be it.").encodeToUByteArray() "only one tip for the future, sunscreen would be it.").encodeToUByteArray()
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U 0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(
@ -134,7 +134,7 @@ class XChaCha20Poly1305Test {
0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU, 0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU,
0xcfU, 0x49U 0xcfU, 0x49U
) )
// val xChaChaPoly = XChaCha20Poly1305Pure(key, additionalData) val firstChunk = // val xChaChaPoly = XChaCha20Poly1305Pure(key, associatedData) val firstChunk =
// xChaChaPoly.encryptPartialData(message) val finalChunk = xChaChaPoly.finishEncryption().first val result = // xChaChaPoly.encryptPartialData(message) val finalChunk = xChaChaPoly.finishEncryption().first val result =
// firstChunk + finalChunk result.contentEquals(expected) // firstChunk + finalChunk result.contentEquals(expected)
1 == 1 1 == 1
@ -144,7 +144,7 @@ class XChaCha20Poly1305Test {
val message = ubyteArrayOf( val message = ubyteArrayOf(
0x00U 0x00U
) )
val additionalData = ubyteArrayOf( val associatedData = ubyteArrayOf(
0x00U 0x00U
) )
val key = ubyteArrayOf( val key = ubyteArrayOf(
@ -163,7 +163,7 @@ class XChaCha20Poly1305Test {
0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U, 0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U,
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU 0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
) )
// val xChaChaPoly = XChaCha20Poly1305Pure(key, additionalData) // val xChaChaPoly = XChaCha20Poly1305Pure(key, associatedData)
// val firstChunk = xChaChaPoly.encryptPartialData(message) // val firstChunk = xChaChaPoly.encryptPartialData(message)
// val finalChunk = xChaChaPoly.finishEncryption().first // val finalChunk = xChaChaPoly.finishEncryption().first
// val result = firstChunk + finalChunk // val result = firstChunk + finalChunk

View File

@ -20,18 +20,18 @@ class EncryptionTest {
"ojsAn3c9zIifIrMnydSivHVZ2pBtpAQwYoJhYmEsfE0tROGnOwFWyB9K6LRSv1gB3YqKR9VyM8mpRoUM3UCRRjyiX7bnKdCE1" + "ojsAn3c9zIifIrMnydSivHVZ2pBtpAQwYoJhYmEsfE0tROGnOwFWyB9K6LRSv1gB3YqKR9VyM8mpRoUM3UCRRjyiX7bnKdCE1" +
"EiX0myiwcY1nUKTgB3keERWtMU07hX7bCtao5nRvDofSj3o3IInHRQh6opltr5asQwn4m1qn029QF").encodeToUByteArray() "EiX0myiwcY1nUKTgB3keERWtMU07hX7bCtao5nRvDofSj3o3IInHRQh6opltr5asQwn4m1qn029QF").encodeToUByteArray()
plaintext.hexColumsPrint() plaintext.hexColumsPrint()
val additionalData = "Additional data 1".encodeToUByteArray() val associatedData = "Additional data 1".encodeToUByteArray()
// val additionalData = ubyteArrayOf() // val associatedData = ubyteArrayOf()
val keyValue = UByteArray(32) { it.toUByte() } val keyValue = UByteArray(32) { it.toUByte() }
val key = SymmetricKey(keyValue) val key = SymmetricKey(keyValue)
val encryptor = Crypto.Encryption.createMultipartEncryptor(key) val encryptor = Crypto.Encryption.createMultipartEncryptor(key)
val header = encryptor.startEncryption() val header = encryptor.startEncryption()
val ciphertext1 = encryptor.encryptPartialData(plaintext.sliceArray(0 until 100), additionalData) val ciphertext1 = encryptor.encryptPartialData(plaintext.sliceArray(0 until 100), associatedData)
val ciphertext2 = encryptor.encryptPartialData(plaintext.sliceArray(100 until 200)) val ciphertext2 = encryptor.encryptPartialData(plaintext.sliceArray(100 until 200))
val ciphertext3 = encryptor.encryptPartialData(plaintext.sliceArray(200 until 250)) val ciphertext3 = encryptor.encryptPartialData(plaintext.sliceArray(200 until 250))
//decrypt //decrypt
val decryptor = Crypto.Encryption.createMultipartDecryptor(key, header) val decryptor = Crypto.Encryption.createMultipartDecryptor(key, header)
val plaintext1 = decryptor.decryptPartialData(ciphertext1, additionalData) val plaintext1 = decryptor.decryptPartialData(ciphertext1, associatedData)
val plaintext2 = decryptor.decryptPartialData(ciphertext2) val plaintext2 = decryptor.decryptPartialData(ciphertext2)
val plaintext3 = decryptor.decryptPartialData(ciphertext3) val plaintext3 = decryptor.decryptPartialData(ciphertext3)