Added decryption

This commit is contained in:
Ugljesa Jovanovic 2020-06-21 21:52:17 +02:00 committed by Ugljesa Jovanovic
parent 3c49128c90
commit 2f0f174b33
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
6 changed files with 57 additions and 12 deletions

View File

@ -1,5 +1,6 @@
package com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.authenticated.XChaCha20Poly1305Pure
import com.ionspin.kotlin.crypto.hash.UpdatableHash
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bProperties
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bPure
@ -92,6 +93,14 @@ data class HashedData(val hash: UByteArray) {
}
}
data class SymmetricKey(val value : UByteArray) {
companion object {
fun randomKey() : SymmetricKey {
return SymmetricKey(SRNG.getRandomBytes(32))
}
}
}
data class EncryptedData(val encrypted: UByteArray)
object PublicApi {
@ -106,8 +115,12 @@ object PublicApi {
}
}
object Symmetric {
fun encrypt(data : Encryptable) : EncryptedData {
TODO()
fun encrypt(key: SymmetricKey, data : Encryptable, additionalData : UByteArray = ubyteArrayOf()) : EncryptedData {
if (key.value.size != 32) {
throw RuntimeException("Invalid key size! Required 32, supplied ${key.value.size}")
}
val nonce = SRNG.getRandomBytes(24)
return EncryptedData(XChaCha20Poly1305Pure.encrypt(key.value, nonce, data.encryptableData(), additionalData) + nonce)
}
fun <T: Encryptable> decrypt(encryptedData : EncryptedData) : T {

View File

@ -3,7 +3,6 @@ package com.ionspin.kotlin.crypto.authenticated
import com.ionspin.kotlin.crypto.mac.Poly1305
import com.ionspin.kotlin.crypto.symmetric.ChaCha20Pure
import com.ionspin.kotlin.crypto.symmetric.XChaCha20Pure
import com.ionspin.kotlin.crypto.util.hexColumsPrint
import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray
/**
@ -26,7 +25,7 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray, val addi
// 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)
)
val cipherText = XChaCha20Pure.encrypt(key, nonce, message, 1U)
val cipherText = XChaCha20Pure.xorWithKeystream(key, nonce, message, 1U)
val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U }
val cipherTextPad = UByteArray(16 - cipherText.size % 16) { 0U }
val macData = additionalData + additionalDataPad +
@ -36,6 +35,33 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray, val addi
val tag = Poly1305.poly1305Authenticate(authKey, macData)
return cipherText + tag
}
fun decrypt(key: UByteArray, nonce: UByteArray, cipherText: UByteArray, additionalData: UByteArray) : UByteArray {
val subKey = XChaCha20Pure.hChacha(key, nonce)
val authKey =
ChaCha20Pure.encrypt(
subKey.toLittleEndianUByteArray(),
ubyteArrayOf(0U, 0U, 0U, 0U) + nonce.sliceArray(16 until 24),
UByteArray(64) { 0U },
0U
)
//2. Get the tag
val tag = cipherText.sliceArray(cipherText.size - 16 until cipherText.size)
//3. Verify tag is valid
val cipherTextWithoutTag = cipherText.sliceArray(0 until cipherText.size - 16)
val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U }
val cipherTextPad = UByteArray(16 - cipherTextWithoutTag.size % 16) { 0U }
val macData = additionalData + additionalDataPad +
cipherTextWithoutTag + cipherTextPad +
additionalData.size.toULong().toLittleEndianUByteArray() +
cipherTextWithoutTag.size.toULong().toLittleEndianUByteArray()
val calculatedTag = Poly1305.poly1305Authenticate(authKey, macData)
if (!calculatedTag.contentEquals(tag)) {
RuntimeException("Bad tag!") //TODO replace with specific exception
}
//4. Decrypt data
return XChaCha20Pure.xorWithKeystream(key, nonce, cipherTextWithoutTag, 1U)
}
}
private val updateableEncryptionPrimitive = XChaCha20Pure(key, nonce, initialCounter = 1U)

View File

@ -37,6 +37,9 @@ class Poly1305(key: UByteArray) {
//Doesn't have to be every power, just divisible by 8
val twoToThe128 = BigInteger.ONE.shl(128)
/**
* Limit - stop poly calculating tag at desired index, ignored if 0
*/
fun poly1305Authenticate(key: UByteArray, message: UByteArray) : UByteArray {
val r = clampR(UByteArray(16) { key[it] })
val s= UByteArray(16) { key[it + 16]}

View File

@ -55,7 +55,7 @@ class XChaCha20Pure(key: UByteArray, nonce: UByteArray, initialCounter: UInt = 0
}
fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, initialCounter: UInt = 0U): UByteArray {
fun xorWithKeystream(key: UByteArray, nonce: UByteArray, message: UByteArray, initialCounter: UInt = 0U): UByteArray {
val ciphertext = UByteArray(message.size)
val hChaChaKey = hChacha(key, nonce)

View File

@ -53,8 +53,10 @@ class XChaCha20Poly1305Test {
0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU,
0xcfU, 0x49U
)
val result = XChaCha20Poly1305Pure.encrypt(key, nonce, message, additionalData)
result.contentEquals(expected)
val encrypted = XChaCha20Poly1305Pure.encrypt(key, nonce, message, additionalData)
val decrypted = XChaCha20Poly1305Pure.decrypt(key, nonce, encrypted, additionalData)
encrypted.contentEquals(expected) && decrypted.contentEquals(message)
}
assertTrue {
@ -80,8 +82,10 @@ class XChaCha20Poly1305Test {
0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U,
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
)
val result = XChaCha20Poly1305Pure.encrypt(key, nonce, message, additionalData)
result.contentEquals(expected)
val encrypted = XChaCha20Poly1305Pure.encrypt(key, nonce, message, additionalData)
val decrypted = XChaCha20Poly1305Pure.decrypt(key, nonce, encrypted, additionalData)
encrypted.contentEquals(expected) && decrypted.contentEquals(message)
}

View File

@ -1,7 +1,6 @@
package com.ionspin.kotlin.crypto.symmetric
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
import com.ionspin.kotlin.crypto.util.hexColumsPrint
import kotlin.test.Test
import kotlin.test.assertTrue
@ -133,7 +132,7 @@ class XChaCha20Test {
)
val result = XChaCha20Pure.encrypt(key, nonce, message, 1U)
val result = XChaCha20Pure.xorWithKeystream(key, nonce, message, 1U)
assertTrue {
result.contentEquals(expected)
}