Fixed some of the errors spotted in various aes implementation while doing cryptopals challenge, anyways they were unused. Added multipart generic hash (blake2b) native implementation
This commit is contained in:
		
							parent
							
								
									231a84af67
								
							
						
					
					
						commit
						6f38a01195
					
				| @ -50,7 +50,7 @@ interface JsSodiumInterface { | ||||
| 
 | ||||
|     //decrypt | ||||
|     fun crypto_secretstream_xchacha20poly1305_init_pull(header: Uint8Array, key: Uint8Array) : dynamic | ||||
|     fun crypto_secretstream_xchacha20poly1305_pull(state: dynamic, ciphertext: Uint8Array, additionalData: Uint8Array) : Uint8Array | ||||
|     fun crypto_secretstream_xchacha20poly1305_pull(state: dynamic, ciphertext: Uint8Array, additionalData: Uint8Array) : dynamic | ||||
| 
 | ||||
|     //util | ||||
|     fun memzero(array: Uint8Array) | ||||
|  | ||||
| @ -5,6 +5,22 @@ package com.ionspin.kotlin.crypto.generichash | ||||
|  * ugljesa.jovanovic@ionspin.com | ||||
|  * on 21-Aug-2020 | ||||
|  */ | ||||
| 
 | ||||
| data class GenericHashState(val hashLength: Int, val state: GenericHashStateInternal) | ||||
| 
 | ||||
| expect class GenericHashStateInternal | ||||
| 
 | ||||
| expect object GenericHashing { | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     fun genericHash(message : UByteArray, requestedHashLength: Int, key : UByteArray? = null) : UByteArray | ||||
| 
 | ||||
|     fun genericHashInit(requestedHashLength: Int, key : UByteArray? = null) : GenericHashState | ||||
|     fun genericHashUpdate(state: GenericHashState, messagePart : UByteArray) | ||||
|     fun genericHashFinal(state : GenericHashState) : UByteArray | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -3,17 +3,30 @@ package com.ionspin.kotlin.crypto.generichash | ||||
| import kotlinx.cinterop.addressOf | ||||
| import kotlinx.cinterop.convert | ||||
| import kotlinx.cinterop.pin | ||||
| import kotlinx.cinterop.pointed | ||||
| import kotlinx.cinterop.ptr | ||||
| import kotlinx.cinterop.reinterpret | ||||
| import libsodium.crypto_generichash | ||||
| import libsodium.crypto_generichash_final | ||||
| import libsodium.crypto_generichash_init | ||||
| import libsodium.crypto_generichash_state | ||||
| import libsodium.crypto_generichash_update | ||||
| import platform.posix.malloc | ||||
| 
 | ||||
| /** | ||||
|  * Created by Ugljesa Jovanovic | ||||
|  * ugljesa.jovanovic@ionspin.com | ||||
|  * on 21-Aug-2020 | ||||
|  */ | ||||
| 
 | ||||
| actual typealias GenericHashStateInternal = libsodium.crypto_generichash_blake2b_state | ||||
| 
 | ||||
| actual object GenericHashing { | ||||
|     val _emitByte: Byte = 0 | ||||
|     val _emitByteArray: ByteArray = ByteArray(0) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     actual fun genericHash(message: UByteArray, requestedHashLength: Int, key: UByteArray?) : UByteArray { | ||||
|         val hash = UByteArray(requestedHashLength) | ||||
|         val pinnedHash = hash.pin() | ||||
| @ -32,4 +45,48 @@ actual object GenericHashing { | ||||
|         pinnedMessage.unpin() | ||||
|         return hash | ||||
|     } | ||||
| 
 | ||||
|     actual fun genericHashInit( | ||||
|         requestedHashLength: Int, | ||||
|         key: UByteArray? | ||||
|     ): GenericHashState { | ||||
|         val stateAllocated = malloc(GenericHashStateInternal.size.convert()) | ||||
|         val statePointed = stateAllocated!!.reinterpret<GenericHashStateInternal>().pointed | ||||
|         val pinnedKey = key?.pin() | ||||
|         crypto_generichash_init( | ||||
|             statePointed.ptr, | ||||
|             pinnedKey?.addressOf(0), | ||||
|             (key?.size ?: 0).convert(), | ||||
|             requestedHashLength.convert() | ||||
|         ) | ||||
|         pinnedKey?.unpin() | ||||
|         return GenericHashState(requestedHashLength, statePointed) | ||||
|     } | ||||
| 
 | ||||
|     actual fun genericHashUpdate( | ||||
|         state: GenericHashState, | ||||
|         messagePart: UByteArray | ||||
|     ) { | ||||
|         val pinnedMessage = messagePart.pin() | ||||
|         crypto_generichash_update( | ||||
|             state.state.ptr, | ||||
|             pinnedMessage.addressOf(0), | ||||
|             messagePart.size.convert() | ||||
|         ) | ||||
|         pinnedMessage.unpin() | ||||
|     } | ||||
| 
 | ||||
|     actual fun genericHashFinal(state: GenericHashState): UByteArray { | ||||
|         val hashResult = UByteArray(state.hashLength) | ||||
|         val hashResultPinned = hashResult.pin() | ||||
|         crypto_generichash_final( | ||||
|             state.state.ptr, | ||||
|             hashResultPinned.addressOf(0), | ||||
|             state.hashLength.convert() | ||||
|         ) | ||||
|         hashResultPinned.unpin() | ||||
|         return hashResult | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -145,7 +145,8 @@ internal class AesCbcPure internal constructor(val aesKey: InternalAesKey, val m | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Encrypt fed data and return it alongside the randomly chosen initialization vector | ||||
|      * Encrypt fed data and return it alongside the randomly chosen initialization vector. | ||||
|      * This also applies correct PKCS#7 padding | ||||
|      * @return Encrypted data and initialization vector | ||||
|      */ | ||||
|     fun encrypt(): EncryptedDataAndInitializationVector { | ||||
| @ -158,6 +159,8 @@ internal class AesCbcPure internal constructor(val aesKey: InternalAesKey, val m | ||||
|             } else { | ||||
|                 output += consumeBlock(lastBlockPadded) | ||||
|             } | ||||
|         } else { | ||||
|             output += consumeBlock(UByteArray(BLOCK_BYTES) { BLOCK_BYTES.toUByte()}) | ||||
|         } | ||||
|         return EncryptedDataAndInitializationVector( | ||||
|             output.reversed().foldRight(UByteArray(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes }, | ||||
| @ -172,11 +175,10 @@ internal class AesCbcPure internal constructor(val aesKey: InternalAesKey, val m | ||||
|     fun decrypt(): UByteArray { | ||||
|         val removePaddingCount = output.last().last() | ||||
| 
 | ||||
| 
 | ||||
|         val removedPadding = if (removePaddingCount > 0U && removePaddingCount < 16U) { | ||||
|             output.last().dropLast(removePaddingCount.toInt() and 0x7F) | ||||
|         } else { | ||||
|             output.last().toList() | ||||
|             ubyteArrayOf() | ||||
|         }.toUByteArray() | ||||
|         val preparedOutput = (output.dropLast(1) + listOf(removedPadding)) | ||||
|         //JS compiler freaks out here if we don't supply exact type | ||||
| @ -238,4 +240,4 @@ data class EncryptedDataAndInitializationVector(val encryptedData : UByteArray, | ||||
|         result = 31 * result + initializationVector.contentHashCode() | ||||
|         return result | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -54,8 +54,8 @@ internal class AesCtrPure internal constructor(val aesKey: InternalAesKey, val m | ||||
|          * Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all | ||||
|          * data call [decrypt] | ||||
|          */ | ||||
|         fun createDecryptor(aesKey : InternalAesKey) : AesCtrPure { | ||||
|             return AesCtrPure(aesKey, Mode.DECRYPT) | ||||
|         fun createDecryptor(aesKey : InternalAesKey, initialCounter: UByteArray) : AesCtrPure { | ||||
|             return AesCtrPure(aesKey, Mode.DECRYPT, initialCounter = initialCounter) | ||||
|         } | ||||
|         /** | ||||
|          * Bulk encryption, returns encrypted data and a random initial counter | ||||
| @ -68,8 +68,8 @@ internal class AesCtrPure internal constructor(val aesKey: InternalAesKey, val m | ||||
|         /** | ||||
|          * Bulk decryption, returns decrypted data | ||||
|          */ | ||||
|         fun decrypt(aesKey: InternalAesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray { | ||||
|             val aesCtr = AesCtrPure(aesKey, Mode.DECRYPT, initialCounter) | ||||
|         fun decrypt(aesKey: InternalAesKey, data: UByteArray, initialCounter: UByteArray): UByteArray { | ||||
|             val aesCtr = AesCtrPure(aesKey, Mode.DECRYPT, initialCounter = initialCounter) | ||||
|             aesCtr.addData(data) | ||||
|             return aesCtr.decrypt() | ||||
|         } | ||||
|  | ||||
| @ -35,7 +35,9 @@ class AesCbcTest { | ||||
|             val key = "4278b840fb44aaa757c1bf04acbe1a3e" | ||||
|             val iv = "57f02a5c5339daeb0a2908a06ac6393f" | ||||
|             val plaintext = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5" | ||||
|             val expectedCipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7" | ||||
|             val expectedCipherText = "479c89ec14bc98994e62b2c705b5014e" + | ||||
|                     "175bd7832e7e60a1e92aac568a861eb7" + | ||||
|                     "fc2dc2f4a527ce39f79c56b31432c779" | ||||
|             val aesCbc = | ||||
|                 AesCbcPure(InternalAesKey.Aes128Key(key), mode = Mode.ENCRYPT, initializationVector = iv.hexStringToUByteArray()) | ||||
|             aesCbc.addData(plaintext.hexStringToUByteArray()) | ||||
| @ -104,4 +106,4 @@ class AesCbcTest { | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user