diff options
Diffstat (limited to 'okio/src/hashFunctions/kotlin/okio/internal/Sha256.kt')
-rw-r--r-- | okio/src/hashFunctions/kotlin/okio/internal/Sha256.kt | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/okio/src/hashFunctions/kotlin/okio/internal/Sha256.kt b/okio/src/hashFunctions/kotlin/okio/internal/Sha256.kt new file mode 100644 index 00000000..aa0d24d0 --- /dev/null +++ b/okio/src/hashFunctions/kotlin/okio/internal/Sha256.kt @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2020 Square, Inc. + * + * 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 okio.internal + +import okio.and + +internal class Sha256 : HashFunction { + private var messageLength = 0L + private val unprocessed = ByteArray(64) + private var unprocessedLimit = 0 + private val words = IntArray(64) + + private var h0 = 1779033703 + private var h1 = -1150833019 + private var h2 = 1013904242 + private var h3 = -1521486534 + private var h4 = 1359893119 + private var h5 = -1694144372 + private var h6 = 528734635 + private var h7 = 1541459225 + + override fun update( + input: ByteArray, + offset: Int, + byteCount: Int + ) { + messageLength += byteCount + var pos = offset + val limit = pos + byteCount + val unprocessed = this.unprocessed + val unprocessedLimit = this.unprocessedLimit + + if (unprocessedLimit > 0) { + if (unprocessedLimit + byteCount < 64) { + // Not enough bytes for a chunk. + input.copyInto(unprocessed, unprocessedLimit, pos, limit) + this.unprocessedLimit = unprocessedLimit + byteCount + return + } + + // Process a chunk combining leftover bytes and the input. + val consumeByteCount = 64 - unprocessedLimit + input.copyInto(unprocessed, unprocessedLimit, pos, pos + consumeByteCount) + processChunk(unprocessed, 0) + this.unprocessedLimit = 0 + pos += consumeByteCount + } + + while (pos < limit) { + val nextPos = pos + 64 + + if (nextPos > limit) { + // Not enough bytes for a chunk. + input.copyInto(unprocessed, 0, pos, limit) + this.unprocessedLimit = limit - pos + return + } + + // Process a chunk. + processChunk(input, pos) + pos = nextPos + } + } + + private fun processChunk(input: ByteArray, pos: Int) { + val words = this.words + + var pos = pos + for (w in 0 until 16) { + words[w] = ((input[pos++] and 0xff) shl 24) or + ((input[pos++] and 0xff) shl 16) or + ((input[pos++] and 0xff) shl 8) or + ((input[pos++] and 0xff)) + } + + for (w in 16 until 64) { + val w15 = words[w - 15] + val s0 = ((w15 ushr 7) or (w15 shl 25)) xor ((w15 ushr 18) or (w15 shl 14)) xor (w15 ushr 3) + val w2 = words[w - 2] + val s1 = ((w2 ushr 17) or (w2 shl 15)) xor ((w2 ushr 19) or (w2 shl 13)) xor (w2 ushr 10) + val w16 = words[w - 16] + val w7 = words[w - 7] + words[w] = w16 + s0 + w7 + s1 + } + + hash(words) + } + + private fun hash( + words: IntArray + ) { + val localK = k + 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 64) { + val s0 = ((a ushr 2) or (a shl 30)) xor + ((a ushr 13) or (a shl 19)) xor + ((a ushr 22) or (a shl 10)) + val s1 = ((e ushr 6) or (e shl 26)) xor + ((e ushr 11) or (e shl 21)) xor + ((e ushr 25) or (e shl 7)) + + val ch = (e and f) xor + (e.inv() and g) + val maj = (a and b) xor + (a and c) xor + (b and c) + + val t1 = h + s1 + ch + localK[i] + words[i] + val t2 = s0 + maj + + h = g + g = f + f = e + e = d + t1 + d = c + c = b + b = a + a = t1 + t2 + } + + h0 += a + h1 += b + h2 += c + h3 += d + h4 += e + h5 += f + h6 += g + h7 += h + } + + /* ktlint-disable */ + override fun digest(): ByteArray { + val unprocessed = this.unprocessed + var unprocessedLimit = this.unprocessedLimit + val messageLengthBits = messageLength * 8 + + unprocessed[unprocessedLimit++] = 0x80.toByte() + if (unprocessedLimit > 56) { + unprocessed.fill(0, unprocessedLimit, 64) + processChunk(unprocessed, 0) + unprocessed.fill(0, 0, unprocessedLimit) + } else { + unprocessed.fill(0, unprocessedLimit, 56) + } + unprocessed[56] = (messageLengthBits ushr 56).toByte() + unprocessed[57] = (messageLengthBits ushr 48).toByte() + unprocessed[58] = (messageLengthBits ushr 40).toByte() + unprocessed[59] = (messageLengthBits ushr 32).toByte() + unprocessed[60] = (messageLengthBits ushr 24).toByte() + unprocessed[61] = (messageLengthBits ushr 16).toByte() + unprocessed[62] = (messageLengthBits ushr 8).toByte() + unprocessed[63] = (messageLengthBits ).toByte() + processChunk(unprocessed, 0) + + val a = h0 + val b = h1 + val c = h2 + val d = h3 + val e = h4 + val f = h5 + val g = h6 + val h = h7 + + reset() + + return byteArrayOf( + (a shr 24).toByte(), + (a shr 16).toByte(), + (a shr 8).toByte(), + (a ).toByte(), + (b shr 24).toByte(), + (b shr 16).toByte(), + (b shr 8).toByte(), + (b ).toByte(), + (c shr 24).toByte(), + (c shr 16).toByte(), + (c shr 8).toByte(), + (c ).toByte(), + (d shr 24).toByte(), + (d shr 16).toByte(), + (d shr 8).toByte(), + (d ).toByte(), + (e shr 24).toByte(), + (e shr 16).toByte(), + (e shr 8).toByte(), + (e ).toByte(), + (f shr 24).toByte(), + (f shr 16).toByte(), + (f shr 8).toByte(), + (f ).toByte(), + (g shr 24).toByte(), + (g shr 16).toByte(), + (g shr 8).toByte(), + (g ).toByte(), + (h shr 24).toByte(), + (h shr 16).toByte(), + (h shr 8).toByte(), + (h ).toByte() + ) + } + /* ktlint-enable */ + + private fun reset() { + messageLength = 0L + unprocessed.fill(0) + unprocessedLimit = 0 + words.fill(0) + + h0 = 1779033703 + h1 = -1150833019 + h2 = 1013904242 + h3 = -1521486534 + h4 = 1359893119 + h5 = -1694144372 + h6 = 528734635 + h7 = 1541459225 + } + + companion object { + private val k = intArrayOf( + 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, + -1424204075, -670586216, 310598401, 607225278, 1426881987, 1925078388, -2132889090, + -1680079193, -1046744716, -459576895, -272742522, 264347078, 604807628, 770255983, 1249150122, + 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, + -710438585, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, + 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, + -778901479, -694614492, -200395387, 275423344, 430227734, 506948616, 659060556, 883997877, + 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, + -1933114872, -1866530822, -1538233109, -1090935817, -965641998 + ) + } +} |