Added sha256 updateable mode
This commit is contained in:
		
							parent
							
								
									3528dd390f
								
							
						
					
					
						commit
						187282232e
					
				@ -29,11 +29,11 @@ import com.ionspin.kotlin.crypto.rotateRight
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					@ExperimentalUnsignedTypes
 | 
				
			||||||
class Sha256() : Hash {
 | 
					class Sha256 : Hash {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    companion object {
 | 
					    companion object {
 | 
				
			||||||
        const val BLOCK_SIZE = 512
 | 
					        const val BLOCK_SIZE = 512
 | 
				
			||||||
        const val W_SIZE = 64
 | 
					        const val BLOCK_SIZE_IN_BYTES = 64
 | 
				
			||||||
        const val UINT_MASK = 0xFFFFFFFFU
 | 
					        const val UINT_MASK = 0xFFFFFFFFU
 | 
				
			||||||
        const val BYTE_MASK_FROM_ULONG = 0xFFUL
 | 
					        const val BYTE_MASK_FROM_ULONG = 0xFFUL
 | 
				
			||||||
        const val BYTE_MASK_FROM_UINT = 0xFFU
 | 
					        const val BYTE_MASK_FROM_UINT = 0xFFU
 | 
				
			||||||
@ -61,103 +61,37 @@ class Sha256() : Hash {
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @ExperimentalStdlibApi
 | 
					        @ExperimentalStdlibApi
 | 
				
			||||||
        fun digest(message : String) : Array<UByte> {
 | 
					        fun digest(message: String): Array<UByte> {
 | 
				
			||||||
            return digest(message.encodeToByteArray().map { it.toUByte() }.toTypedArray())
 | 
					            return digest(message.encodeToByteArray().map { it.toUByte() }.toTypedArray())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fun digest(message: Array<UByte>) : Array<UByte> {
 | 
					        fun digest(message: Array<UByte>): Array<UByte> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var h0 = 0x6a09e667U
 | 
					            var h = iv.copyOf()
 | 
				
			||||||
            var h1 = 0xbb67ae85U
 | 
					 | 
				
			||||||
            var h2 = 0x3c6ef372U
 | 
					 | 
				
			||||||
            var h3 = 0xa54ff53aU
 | 
					 | 
				
			||||||
            var h4 = 0x510e527fU
 | 
					 | 
				
			||||||
            var h5 = 0x9b05688cU
 | 
					 | 
				
			||||||
            var h6 = 0x1f83d9abU
 | 
					 | 
				
			||||||
            var h7 = 0x5be0cd19U
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            val originalMessageSizeInBits = message.size * 8
 | 
					            val expansionArray = createExpansionArray(message.size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            val chunks = (
 | 
				
			||||||
            //K such that L + 1 + K + 64 is a multiple of 512
 | 
					                        message +
 | 
				
			||||||
            val expandedRemainderOf512 = (originalMessageSizeInBits + 65) % BLOCK_SIZE
 | 
					                                expansionArray +
 | 
				
			||||||
            val zeroAddAmount = when (expandedRemainderOf512) {
 | 
					                                (message.size * 8).toULong().toPaddedByteArray()
 | 
				
			||||||
                0 -> 0
 | 
					                        )
 | 
				
			||||||
                else -> (BLOCK_SIZE - expandedRemainderOf512) / 8
 | 
					                    .chunked(BLOCK_SIZE_IN_BYTES)
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            val expansionArray = Array<UByte>(zeroAddAmount + 1) {
 | 
					 | 
				
			||||||
                when (it) {
 | 
					 | 
				
			||||||
                    0 -> 0b10000000U //TODO This wont work if there the byte needs to be shared with the L (length) ULong
 | 
					 | 
				
			||||||
                    else -> 0U
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            val chunks = (message + expansionArray + originalMessageSizeInBits.toULong().toPaddedByteArray()).chunked(64)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            chunks.forEach { chunk ->
 | 
					            chunks.forEach { chunk ->
 | 
				
			||||||
                val w = Array<UInt>(W_SIZE) {
 | 
					                val w = expandChunk(chunk)
 | 
				
			||||||
                    when (it) {
 | 
					                mix(h, w).copyInto(h)
 | 
				
			||||||
                        in 0 until 16 -> {
 | 
					 | 
				
			||||||
                            var collected = (chunk[(it * 4)].toUInt() shl 24) +
 | 
					 | 
				
			||||||
                                    (chunk[(it * 4) + 1].toUInt() shl 16 ) +
 | 
					 | 
				
			||||||
                                    (chunk[(it * 4) + 2].toUInt() shl 8 ) +
 | 
					 | 
				
			||||||
                                    (chunk[(it * 4) + 3].toUInt())
 | 
					 | 
				
			||||||
                            collected
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        else -> 0U
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                for (i in 16 until W_SIZE) {
 | 
					 | 
				
			||||||
                    val s0 = scheduleSigma0(w[i - 15])
 | 
					 | 
				
			||||||
                    val s1 = scheduleSigma1(w[i - 2])
 | 
					 | 
				
			||||||
                    w[i] = w[i-16] + s0 + w[i - 7] + s1
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var a = h0
 | 
					 | 
				
			||||||
                var b = h1
 | 
					 | 
				
			||||||
                var c = h2
 | 
					 | 
				
			||||||
                var d = h3
 | 
					 | 
				
			||||||
                var e = h4
 | 
					 | 
				
			||||||
                var f = h5
 | 
					 | 
				
			||||||
                var g = h6
 | 
					 | 
				
			||||||
                var h = h7
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                for (i in 0 until W_SIZE) {
 | 
					 | 
				
			||||||
                    val s1 = compressionSigma1(e)
 | 
					 | 
				
			||||||
                    val ch = ch(e, f, g)
 | 
					 | 
				
			||||||
                    val temp1 = h + s1 + ch + k[i] + w[i]
 | 
					 | 
				
			||||||
                    val s0 = compressionSigma0(a)
 | 
					 | 
				
			||||||
                    val maj = maj(a,b,c)
 | 
					 | 
				
			||||||
                    val temp2 = s0 + maj
 | 
					 | 
				
			||||||
                    h = g
 | 
					 | 
				
			||||||
                    g = f
 | 
					 | 
				
			||||||
                    f = e
 | 
					 | 
				
			||||||
                    e = d + temp1
 | 
					 | 
				
			||||||
                    d = c
 | 
					 | 
				
			||||||
                    c = b
 | 
					 | 
				
			||||||
                    b = a
 | 
					 | 
				
			||||||
                    a = temp1 + temp2
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                h0 += a
 | 
					 | 
				
			||||||
                h1 += b
 | 
					 | 
				
			||||||
                h2 += c
 | 
					 | 
				
			||||||
                h3 += d
 | 
					 | 
				
			||||||
                h4 += e
 | 
					 | 
				
			||||||
                h5 += f
 | 
					 | 
				
			||||||
                h6 += g
 | 
					 | 
				
			||||||
                h7 += h
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            val digest =  h0.toPaddedByteArray() +
 | 
					            val digest = h[0].toPaddedByteArray() +
 | 
				
			||||||
                    h1.toPaddedByteArray() +
 | 
					                    h[1].toPaddedByteArray() +
 | 
				
			||||||
                    h2.toPaddedByteArray() +
 | 
					                    h[2].toPaddedByteArray() +
 | 
				
			||||||
                    h3.toPaddedByteArray() +
 | 
					                    h[3].toPaddedByteArray() +
 | 
				
			||||||
                    h4.toPaddedByteArray() +
 | 
					                    h[4].toPaddedByteArray() +
 | 
				
			||||||
                    h5.toPaddedByteArray() +
 | 
					                    h[5].toPaddedByteArray() +
 | 
				
			||||||
                    h6.toPaddedByteArray() +
 | 
					                    h[6].toPaddedByteArray() +
 | 
				
			||||||
                    h7.toPaddedByteArray()
 | 
					                    h[7].toPaddedByteArray()
 | 
				
			||||||
            return digest
 | 
					            return digest
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -165,27 +99,104 @@ class Sha256() : Hash {
 | 
				
			|||||||
            return value.rotateRight(7) xor value.rotateRight(18) xor (value shr 3)
 | 
					            return value.rotateRight(7) xor value.rotateRight(18) xor (value shr 3)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun scheduleSigma1(value : UInt) : UInt {
 | 
					        private fun scheduleSigma1(value: UInt): UInt {
 | 
				
			||||||
            return value.rotateRight(17) xor value.rotateRight(19) xor (value shr 10)
 | 
					            return value.rotateRight(17) xor value.rotateRight(19) xor (value shr 10)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun compressionSigma0(a : UInt) : UInt {
 | 
					        private fun compressionSigma0(a: UInt): UInt {
 | 
				
			||||||
            return (a rotateRight  2) xor (a rotateRight 13) xor (a rotateRight 22)
 | 
					            return (a rotateRight 2) xor (a rotateRight 13) xor (a rotateRight 22)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun compressionSigma1(e : UInt) : UInt {
 | 
					        private fun compressionSigma1(e: UInt): UInt {
 | 
				
			||||||
            return (e rotateRight  6) xor (e rotateRight 11) xor (e rotateRight 25)
 | 
					            return (e rotateRight 6) xor (e rotateRight 11) xor (e rotateRight 25)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun ch(x : UInt, y : UInt, z : UInt) : UInt {
 | 
					        private fun ch(x: UInt, y: UInt, z: UInt): UInt {
 | 
				
			||||||
            return ((x and y) xor ((x xor UINT_MASK) and z))
 | 
					            return ((x and y) xor ((x xor UINT_MASK) and z))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun maj(x : UInt, y : UInt, z : UInt) : UInt {
 | 
					        private fun maj(x: UInt, y: UInt, z: UInt): UInt {
 | 
				
			||||||
            return (((x and y) xor (x and z) xor (y and z)))
 | 
					            return (((x and y) xor (x and z) xor (y and z)))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private fun expandChunk(chunk: Array<UByte>): Array<UInt> {
 | 
				
			||||||
 | 
					            val w = Array<UInt>(BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
 | 
					                when (it) {
 | 
				
			||||||
 | 
					                    in 0 until 16 -> {
 | 
				
			||||||
 | 
					                        var collected = (chunk[(it * 4)].toUInt() shl 24) +
 | 
				
			||||||
 | 
					                                (chunk[(it * 4) + 1].toUInt() shl 16) +
 | 
				
			||||||
 | 
					                                (chunk[(it * 4) + 2].toUInt() shl 8) +
 | 
				
			||||||
 | 
					                                (chunk[(it * 4) + 3].toUInt())
 | 
				
			||||||
 | 
					                        collected
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else -> 0U
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            for (i in 16 until BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
 | 
					                val s0 = scheduleSigma0(w[i - 15])
 | 
				
			||||||
 | 
					                val s1 = scheduleSigma1(w[i - 2])
 | 
				
			||||||
 | 
					                w[i] = w[i - 16] + s0 + w[i - 7] + s1
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return w
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private fun mix(h: Array<UInt>, w: Array<UInt>): Array<UInt> {
 | 
				
			||||||
 | 
					            var paramA = h[0]
 | 
				
			||||||
 | 
					            var paramB = h[1]
 | 
				
			||||||
 | 
					            var paramC = h[2]
 | 
				
			||||||
 | 
					            var paramD = h[3]
 | 
				
			||||||
 | 
					            var paramE = h[4]
 | 
				
			||||||
 | 
					            var paramF = h[5]
 | 
				
			||||||
 | 
					            var paramG = h[6]
 | 
				
			||||||
 | 
					            var paramH = h[7]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (i in 0 until BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
 | 
					                val s1 = compressionSigma1(paramE)
 | 
				
			||||||
 | 
					                val ch = ch(paramE, paramF, paramG)
 | 
				
			||||||
 | 
					                val temp1 = paramH + s1 + ch + k[i] + w[i]
 | 
				
			||||||
 | 
					                val s0 = compressionSigma0(paramA)
 | 
				
			||||||
 | 
					                val maj = maj(paramA, paramB, paramC)
 | 
				
			||||||
 | 
					                val temp2 = s0 + maj
 | 
				
			||||||
 | 
					                paramH = paramG
 | 
				
			||||||
 | 
					                paramG = paramF
 | 
				
			||||||
 | 
					                paramF = paramE
 | 
				
			||||||
 | 
					                paramE = paramD + temp1
 | 
				
			||||||
 | 
					                paramD = paramC
 | 
				
			||||||
 | 
					                paramC = paramB
 | 
				
			||||||
 | 
					                paramB = paramA
 | 
				
			||||||
 | 
					                paramA = temp1 + temp2
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            h[0] += paramA
 | 
				
			||||||
 | 
					            h[1] += paramB
 | 
				
			||||||
 | 
					            h[2] += paramC
 | 
				
			||||||
 | 
					            h[3] += paramD
 | 
				
			||||||
 | 
					            h[4] += paramE
 | 
				
			||||||
 | 
					            h[5] += paramF
 | 
				
			||||||
 | 
					            h[6] += paramG
 | 
				
			||||||
 | 
					            h[7] += paramH
 | 
				
			||||||
 | 
					            return h
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fun createExpansionArray(originalSizeInBytes : Int) : Array<UByte> {
 | 
				
			||||||
 | 
					            val originalMessageSizeInBits = originalSizeInBytes * 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //K such that L + 1 + K + 64 is a multiple of 512
 | 
				
			||||||
 | 
					            val expandedRemainderOf512 = (originalMessageSizeInBits + BLOCK_SIZE_IN_BYTES + 1) % BLOCK_SIZE
 | 
				
			||||||
 | 
					            val zeroAddAmount = when (expandedRemainderOf512) {
 | 
				
			||||||
 | 
					                0 -> 0
 | 
				
			||||||
 | 
					                else -> (BLOCK_SIZE - expandedRemainderOf512) / 8
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            val expansionArray = Array<UByte>(zeroAddAmount + 1) {
 | 
				
			||||||
 | 
					                when (it) {
 | 
				
			||||||
 | 
					                    0 -> 0b10000000U
 | 
				
			||||||
 | 
					                    else -> 0U
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return expansionArray
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun ULong.toPaddedByteArray(): Array<UByte> {
 | 
					        private fun ULong.toPaddedByteArray(): Array<UByte> {
 | 
				
			||||||
            val byteMask = BYTE_MASK_FROM_ULONG
 | 
					            val byteMask = BYTE_MASK_FROM_ULONG
 | 
				
			||||||
@ -219,10 +230,85 @@ class Sha256() : Hash {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var h = iv.copyOf()
 | 
				
			||||||
 | 
					    var counter = 0
 | 
				
			||||||
 | 
					    var bufferCounter = 0
 | 
				
			||||||
 | 
					    var buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) { 0U }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ExperimentalStdlibApi
 | 
				
			||||||
 | 
					    fun update(message: String) {
 | 
				
			||||||
 | 
					        return update(message.encodeToByteArray().map { it.toUByte() }.toTypedArray())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun update(array: Array<UByte>) {
 | 
				
			||||||
 | 
					        if (array.isEmpty()) {
 | 
				
			||||||
 | 
					            throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        when {
 | 
				
			||||||
 | 
					            bufferCounter + array.size < BLOCK_SIZE_IN_BYTES -> appendToBuffer(array, bufferCounter)
 | 
				
			||||||
 | 
					            bufferCounter + array.size >= BLOCK_SIZE_IN_BYTES -> {
 | 
				
			||||||
 | 
					                val chunked = array.chunked(BLOCK_SIZE_IN_BYTES)
 | 
				
			||||||
 | 
					                chunked.forEach { chunk ->
 | 
				
			||||||
 | 
					                    if (bufferCounter + chunk.size < BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
 | 
					                        appendToBuffer(chunk, bufferCounter)
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        chunk.copyInto(
 | 
				
			||||||
 | 
					                            destination = buffer,
 | 
				
			||||||
 | 
					                            destinationOffset = bufferCounter,
 | 
				
			||||||
 | 
					                            startIndex = 0,
 | 
				
			||||||
 | 
					                            endIndex = BLOCK_SIZE_IN_BYTES - bufferCounter
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                        counter += BLOCK_SIZE_IN_BYTES
 | 
				
			||||||
 | 
					                        consumeBlock(buffer)
 | 
				
			||||||
 | 
					                        buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
 | 
					                            when (it) {
 | 
				
			||||||
 | 
					                                in (0 until (chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter))) -> {
 | 
				
			||||||
 | 
					                                    chunk[it + (BLOCK_SIZE_IN_BYTES - bufferCounter)]
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                else -> {
 | 
				
			||||||
 | 
					                                    0U
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        bufferCounter = chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun consumeBlock(block: Array<UByte>) {
 | 
				
			||||||
 | 
					        val w = expandChunk(block)
 | 
				
			||||||
 | 
					        mix(h, w).copyInto(h)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun digest() : Array<UByte> {
 | 
				
			||||||
 | 
					        val length = counter + bufferCounter
 | 
				
			||||||
 | 
					        val expansionArray = createExpansionArray(length)
 | 
				
			||||||
 | 
					        val finalBlock = buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPaddedByteArray()
 | 
				
			||||||
 | 
					        finalBlock.chunked(BLOCK_SIZE_IN_BYTES).forEach {
 | 
				
			||||||
 | 
					            consumeBlock(it)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val digest = h[0].toPaddedByteArray() +
 | 
				
			||||||
 | 
					                h[1].toPaddedByteArray() +
 | 
				
			||||||
 | 
					                h[2].toPaddedByteArray() +
 | 
				
			||||||
 | 
					                h[3].toPaddedByteArray() +
 | 
				
			||||||
 | 
					                h[4].toPaddedByteArray() +
 | 
				
			||||||
 | 
					                h[5].toPaddedByteArray() +
 | 
				
			||||||
 | 
					                h[6].toPaddedByteArray() +
 | 
				
			||||||
 | 
					                h[7].toPaddedByteArray()
 | 
				
			||||||
 | 
					        return digest
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun appendToBuffer(array: Array<UByte>, start: Int) {
 | 
				
			||||||
 | 
					        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
				
			||||||
 | 
					        bufferCounter += array.size
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -146,14 +146,14 @@ class Sha512 : Hash {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //K such that L + 1 + K + 64 is a multiple of 512
 | 
					            //K such that L + 1 + K + 64 is a multiple of 512
 | 
				
			||||||
            val expandedRemainderOf1024 = (originalMessageSizeInBits + 129) % BLOCK_SIZE
 | 
					            val expandedRemainderOf1024 = (originalMessageSizeInBits + 130) % BLOCK_SIZE
 | 
				
			||||||
            val zeroAddAmount = when (expandedRemainderOf1024) {
 | 
					            val zeroAddAmount = when (expandedRemainderOf1024) {
 | 
				
			||||||
                0 -> 0
 | 
					                0 -> 0
 | 
				
			||||||
                else -> (BLOCK_SIZE - expandedRemainderOf1024) / 8
 | 
					                else -> (BLOCK_SIZE - expandedRemainderOf1024) / 8
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val expansionArray = Array<UByte>(zeroAddAmount + 1) {
 | 
					            val expansionArray = Array<UByte>(zeroAddAmount + 1) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    0 -> 0b10000000U //TODO This wont work if there the byte needs to be shared with the L (length) ULong
 | 
					                    0 -> 0b10000000U
 | 
				
			||||||
                    else -> 0U
 | 
					                    else -> 0U
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    Copyright 2019 Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 *    you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 *    You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *        http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 *    distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 *    See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 *    limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package com.ionspin.kotlin.crypto.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.chunked
 | 
				
			||||||
 | 
					import kotlin.test.Test
 | 
				
			||||||
 | 
					import kotlin.test.assertTrue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 17-Jul-2019
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@ExperimentalUnsignedTypes
 | 
				
			||||||
 | 
					class Sha256UpdateableTest {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ExperimentalStdlibApi
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun testWellKnownValue() {
 | 
				
			||||||
 | 
					        val sha256 = Sha256()
 | 
				
			||||||
 | 
					        sha256.update("abc")
 | 
				
			||||||
 | 
					        val result = sha256.digest()
 | 
				
			||||||
 | 
					        val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
 | 
				
			||||||
 | 
					        assertTrue {
 | 
				
			||||||
 | 
					            result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toTypedArray())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ExperimentalStdlibApi
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun testWellKnownDoubleBlock() {
 | 
				
			||||||
 | 
					        val sha256 = Sha256()
 | 
				
			||||||
 | 
					        sha256.update(message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
 | 
				
			||||||
 | 
					        val resultDoubleBlock = sha256.digest()
 | 
				
			||||||
 | 
					        println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
 | 
				
			||||||
 | 
					        val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
 | 
				
			||||||
 | 
					        assertTrue {
 | 
				
			||||||
 | 
					            resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user