Slow progress.

This commit is contained in:
Ugljesa Jovanovic 2020-08-21 18:55:17 +02:00 committed by Ugljesa Jovanovic
parent cd90f964ab
commit be4468785d
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
9 changed files with 122 additions and 54 deletions

View File

@ -28,6 +28,27 @@ fun ClassDefinition.defineSecretStreamFunctions() {
)
)
+dataClassDef(
"DecryptedDataAndTag",
"""
This data class wraps the decrypted data and tag returned when decrypting
""".trimIndent(),
listOf(
ParameterDefinition(
parameterName = "decrypted",
parameterType = TypeDefinition.ARRAY_OF_UBYTES
),
ParameterDefinition(
parameterName = "tag",
parameterType = TypeDefinition.UBYTE
)
)
)
val jsSecretStreamInit = CodeBlockDefinition(
"""
val stateAndHeader = getSodium().crypto_secretstream_xchacha20poly1305_init_push(key.toUInt8Array())
@ -148,7 +169,7 @@ fun ClassDefinition.defineSecretStreamFunctions() {
codeDocumentation = """
Decrypt next block of data using the previously initialized state. Returns decrypted block.
""".trimIndent(),
returnType = TypeDefinition.ARRAY_OF_UBYTES
returnType = CustomTypeDefinition(withPackageName("DecryptedDataAndTag"))
) {
+ParameterDefinition(
"state",
@ -167,7 +188,9 @@ fun ClassDefinition.defineSecretStreamFunctions() {
)
+ParameterDefinition(
"tag_p",
TypeDefinition.NULL
TypeDefinition.UBYTE,
dropParameterFromDefinition = true,
isActuallyAnOutputParam = true
)
+ParameterDefinition(
"c",

View File

@ -53,7 +53,7 @@ object CommonLibsodiumGenerator {
fun createCommonMethodSpec(methodDefinition: FunctionDefinition): FunSpec.Builder {
val methodBuilder = FunSpec.builder(methodDefinition.name)
var actualReturnType : TypeName = Any::class.asTypeName()
val actualReturnTypes = mutableListOf<TypeName>()
var actualReturnTypeFound : Boolean = false
for (paramDefinition in methodDefinition.parameterList) {
if ((paramDefinition.isStateType.not() || methodDefinition.isStateCreationFunction.not()) && paramDefinition.dropParameterFromDefinition.not()) {
@ -65,11 +65,11 @@ object CommonLibsodiumGenerator {
}
if (paramDefinition.isActuallyAnOutputParam) {
actualReturnTypeFound = true
actualReturnType = paramDefinition.parameterType.typeName
actualReturnTypes += paramDefinition.parameterType.typeName
}
}
if (actualReturnTypeFound) {
methodBuilder.returns(actualReturnType)
if (actualReturnTypeFound && actualReturnTypes.size == 1) {
methodBuilder.returns(actualReturnTypes[0])
} else {
methodBuilder.returns(methodDefinition.returnType.typeName)
}

View File

@ -8,6 +8,7 @@ import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeAliasSpec
import com.squareup.kotlinpoet.TypeName
/**
* Created by Ugljesa Jovanovic
@ -56,7 +57,7 @@ object JvmLibsodiumGenerator {
methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList
var returnModifierFound = false
var returnModifierValue = ""
lateinit var actualReturnParameterDefinition: ParameterDefinition
val actualReturnTypes = mutableListOf<ParameterDefinition>()
var actualReturnTypeFound: Boolean = false
for (paramDefinition in methodDefinition.parameterList) {
if (paramDefinition.isStateType && methodDefinition.isStateCreationFunction) {
@ -89,14 +90,14 @@ object JvmLibsodiumGenerator {
}
}
if (paramDefinition.isActuallyAnOutputParam) {
actualReturnParameterDefinition = paramDefinition
actualReturnTypes += paramDefinition
actualReturnTypeFound = true
}
}
if (actualReturnTypeFound) {
if (returnModifierFound) {
createOutputParam(
actualReturnParameterDefinition,
actualReturnTypes,
returnModifierValue,
methodBuilder
)
@ -105,7 +106,7 @@ object JvmLibsodiumGenerator {
throw RuntimeException("Function definition lacks a way to define output array length, function ${methodDefinition.name}")
}
createOutputParam(
actualReturnParameterDefinition,
actualReturnTypes,
methodDefinition.outputLengthWhenArray.toString(),
methodBuilder
)
@ -125,10 +126,18 @@ object JvmLibsodiumGenerator {
methodBuilder.addStatement(constructJvmCall.toString())
methodBuilder.addStatement("return state")
} else if (actualReturnTypeFound) {
if (actualReturnTypes.size == 1) {
constructJvmCall.append("sodium.${methodDefinition.nativeName}")
constructJvmCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructJvmCall.toString())
methodBuilder.addStatement("return ${actualReturnParameterDefinition.parameterName}")
methodBuilder.addStatement("return ${actualReturnTypes[0].parameterName}")
} else {
constructJvmCall.append("sodium.${methodDefinition.nativeName}")
constructJvmCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructJvmCall.toString())
methodBuilder.addStatement(
"return ${methodDefinition.returnType.typeName}(${createTupleOutputParams(actualReturnTypes)})")
}
} else {
when (methodDefinition.returnType) {
TypeDefinition.ARRAY_OF_UBYTES -> {
@ -161,23 +170,30 @@ object JvmLibsodiumGenerator {
return methodBuilder
}
fun createOutputParam(outputParam: ParameterDefinition, length: String?, methodBuilder: FunSpec.Builder) {
fun createOutputParam(outputParams: List<ParameterDefinition>, length: String?, methodBuilder: FunSpec.Builder) {
/*
val hashed = ByteArray(Sha256Properties.MAX_HASH_BYTES)
sodium.crypto_hash_sha256_final(state, hashed)
return hashed.asUByteArray()
*/
for (outputParam in outputParams) {
when (outputParam.parameterType) {
TypeDefinition.ARRAY_OF_UBYTES, TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> {
methodBuilder.addStatement("val ${outputParam.parameterName} = UByteArray($length)")
}
TypeDefinition.UBYTE -> {
methodBuilder.addStatement("var ${outputParam.parameterName} : UByte = 0U")
}
else -> {
throw RuntimeException("Unhandled native output param type: ${outputParam.parameterType.typeName}")
}
}
}
}
fun createTupleOutputParams(outputParams: List<ParameterDefinition>) : String {
return outputParams.map { it.parameterName }.joinToString (separator = ", ")
}
fun createStateParam(stateParameterDefinition: ParameterDefinition, methodBuilder: FunSpec.Builder) {
/*

View File

@ -71,7 +71,7 @@ object NativeLibsodiumGenerator {
methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList
var returnModifierFound = false
var returnModifierValue = ""
lateinit var actualReturnParameterDefinition: ParameterDefinition
val actualReturnTypes = mutableListOf<ParameterDefinition>()
var actualReturnTypeFound: Boolean = false
for (paramDefinition in methodDefinition.parameterList) {
if (paramDefinition.isStateType && methodDefinition.isStateCreationFunction) {
@ -104,18 +104,18 @@ object NativeLibsodiumGenerator {
}
if (paramDefinition.isActuallyAnOutputParam) {
actualReturnParameterDefinition = paramDefinition
actualReturnTypes += paramDefinition
actualReturnTypeFound = true
}
}
if (actualReturnTypeFound) {
if (returnModifierFound) {
createOutputParam(actualReturnParameterDefinition, returnModifierValue, methodBuilder)
createOutputParam(actualReturnTypes, returnModifierValue, methodBuilder)
} else {
if (methodDefinition.outputLengthWhenArray == -1) {
throw RuntimeException("Function definition lacks a way to define output array length, function ${methodDefinition.name}")
}
createOutputParam(actualReturnParameterDefinition, methodDefinition.outputLengthWhenArray.toString(), methodBuilder)
createOutputParam(actualReturnTypes, methodDefinition.outputLengthWhenArray.toString(), methodBuilder)
}
}
methodBuilder.addStatement("println(\"Debug ${methodDefinition.name}\")")
@ -134,11 +134,24 @@ object NativeLibsodiumGenerator {
unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement("return state")
} else if (actualReturnTypeFound) {
if (actualReturnTypes.size == 1) {
constructNativeCall.append("libsodium.${methodDefinition.nativeName}")
constructNativeCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructNativeCall.toString())
unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement("return ${actualReturnParameterDefinition.parameterName}")
methodBuilder.addStatement("return ${actualReturnTypes[0].parameterName}")
} else {
constructNativeCall.append("libsodium.${methodDefinition.nativeName}")
constructNativeCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructNativeCall.toString())
unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement(
"return ${methodDefinition.returnType.typeName}(${
JvmLibsodiumGenerator.createTupleOutputParams(
actualReturnTypes
)
})")
}
} else {
when (methodDefinition.returnType) {
TypeDefinition.ARRAY_OF_UBYTES -> {
@ -188,7 +201,7 @@ object NativeLibsodiumGenerator {
methodBuilder.addStatement("val state = allocated.reinterpret<${stateParameterDefinition.parameterType.typeName}>().pointed")
}
fun createOutputParam(outputParam: ParameterDefinition, length: String?, methodBuilder: FunSpec.Builder) {
fun createOutputParam(outputParams: List<ParameterDefinition>, length: String?, methodBuilder: FunSpec.Builder) {
/*
val hashResult = UByteArray(Sha256Properties.MAX_HASH_BYTES)
val hashResultPinned = hashResult.pin()
@ -196,17 +209,24 @@ object NativeLibsodiumGenerator {
sodium_free(state.ptr)
return hashResult
*/
for (outputParam in outputParams) {
when (outputParam.parameterType) {
TypeDefinition.ARRAY_OF_UBYTES, TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> {
methodBuilder.addStatement("val ${outputParam.parameterName} = UByteArray($length)")
}
TypeDefinition.UBYTE -> {
methodBuilder.addStatement("var ${outputParam.parameterName} : UByte = 0U")
}
else -> {
throw RuntimeException("Unhandled native output param type: ${outputParam.parameterType.typeName}")
}
}
}
}
fun createTupleOutputParams(outputParams: List<ParameterDefinition>) : String {
return outputParams.map { it.parameterName }.joinToString (separator = ", ")
}
fun pinParams(methodDefinition: FunctionDefinition, methodBuilder: FunSpec.Builder) {
methodDefinition.parameterList.forEachIndexed { index, paramDefinition ->

View File

@ -20,6 +20,13 @@ data class SecretStreamStateAndHeader(
val header: UByteArray
)
data class DecryptedDataAndTag(
@JsName("decrypted")
val decrypted: UByteArray,
@JsName("tag")
val tag: UByte
)
expect class Crypto internal constructor() {
/**
* Initialize the SHA256 hash
@ -68,5 +75,5 @@ expect class Crypto internal constructor() {
state: SecretStreamState,
c: UByteArray,
ad: UByteArray
): UByteArray
): DecryptedDataAndTag
}

View File

@ -65,7 +65,7 @@ class SecretStreamTest {
encrypted.hexColumsPrint()
val decryptState = crypto.crypto_secretstream_xchacha20poly1305_init_pull(stateAndHeader.header, key)
val decrypted =
crypto.crypto_secretstream_xchacha20poly1305_pull(decryptState, encrypted, ubyteArrayOf()) //TODO JS pull returns a tag and a message!!!
crypto.crypto_secretstream_xchacha20poly1305_pull(decryptState, encrypted, ubyteArrayOf())
decrypted.hexColumsPrint()
decrypted.contentEquals(message)

View File

@ -77,10 +77,10 @@ actual class Crypto internal actual constructor() {
* Initialize state from header and key. The state can then be used for decryption.
*/
actual fun crypto_secretstream_xchacha20poly1305_init_pull(header: UByteArray, key: UByteArray):
SecretStreamState {
dynamic {
println("Debug crypto_secretstream_xchacha20poly1305_init_pull")
return getSodium().crypto_secretstream_xchacha20poly1305_init_pull(header.toUInt8Array(),
key.toUInt8Array()) as SecretStreamState
key.toUInt8Array())
}
/**
@ -104,9 +104,9 @@ actual class Crypto internal actual constructor() {
state: SecretStreamState,
c: UByteArray,
ad: UByteArray
): UByteArray {
): UByte {
println("Debug crypto_secretstream_xchacha20poly1305_pull")
return getSodium().crypto_secretstream_xchacha20poly1305_pull(state, c.toUInt8Array(),
ad.toUInt8Array()).toUByteArray()
ad.toUInt8Array())
}
}

View File

@ -117,11 +117,12 @@ actual class Crypto internal actual constructor() {
state: SecretStreamState,
c: UByteArray,
ad: UByteArray
): UByteArray {
): DecryptedDataAndTag {
val m = UByteArray(c.size - 17)
var tag_p : UByte = 0U
println("Debug crypto_secretstream_xchacha20poly1305_pull")
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m.asByteArray(), null, null,
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m.asByteArray(), null, tag_p.toByte(),
c.asByteArray(), c.size.toLong(), ad.asByteArray(), ad.size.toLong())
return m
return debug.test.DecryptedDataAndTag(m, tag_p)
}
}

View File

@ -162,17 +162,18 @@ actual class Crypto internal actual constructor() {
state: SecretStreamState,
c: UByteArray,
ad: UByteArray
): UByteArray {
): DecryptedDataAndTag {
val m = UByteArray(c.size - 17)
var tag_p : UByte = 0U
println("Debug crypto_secretstream_xchacha20poly1305_pull")
val pinnedM = m.pin()
val pinnedC = c.pin()
val pinnedAd = ad.pin()
libsodium.crypto_secretstream_xchacha20poly1305_pull(state.ptr, pinnedM.addressOf(0), null,
null, pinnedC.addressOf(0), c.size.convert(), pinnedAd.addressOf(0), ad.size.convert())
tag_p, pinnedC.addressOf(0), c.size.convert(), pinnedAd.addressOf(0), ad.size.convert())
pinnedM.unpin()
pinnedC.unpin()
pinnedAd.unpin()
return m
return debug.test.DecryptedDataAndTag(m, tag_p)
}
}