aboutsummaryrefslogtreecommitdiff
path: root/okio/src/hashFunctions/kotlin/okio/internal/Sha256.kt
diff options
context:
space:
mode:
Diffstat (limited to 'okio/src/hashFunctions/kotlin/okio/internal/Sha256.kt')
-rw-r--r--okio/src/hashFunctions/kotlin/okio/internal/Sha256.kt253
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
+ )
+ }
+}