@@ -2,111 +2,48 @@ package org.komputing.khash.sha512
22
33/* *
44 * Digest Class for SHA-512.
5- * Original Java version at hhttps ://github.com/trittimo/SHA512
5+ * Original Java version at https ://github.com/trittimo/SHA512
66 */
77object Sha512 {
88
9- private var K = longArrayOf(
10- 0x428A2F98D728AE22L ,
11- 0x7137449123EF65CDL ,
12- - 0x4a3f043013b2c4d1L ,
13- - 0x164a245a7e762444L ,
14- 0x3956C25BF348B538L ,
15- 0x59F111F1B605D019L ,
16- - 0x6dc07d5b50e6b065L ,
17- - 0x54e3a12a25927ee8L ,
18- - 0x27f855675cfcfdbeL ,
19- 0x12835B0145706FBEL ,
20- 0x243185BE4EE4B28CL ,
21- 0x550C7DC3D5FFB4E2L ,
22- 0x72BE5D74F27B896FL ,
23- - 0x7f214e01c4e9694fL ,
24- - 0x6423f958da38edcbL ,
25- - 0x3e640e8b3096d96cL ,
26- - 0x1b64963e610eb52eL ,
27- - 0x1041b879c7b0da1dL ,
28- 0x0FC19DC68B8CD5B5L ,
29- 0x240CA1CC77AC9C65L ,
30- 0x2DE92C6F592B0275L ,
31- 0x4A7484AA6EA6E483L ,
32- 0x5CB0A9DCBD41FBD4L ,
33- 0x76F988DA831153B5L ,
34- - 0x67c1aead11992055L ,
35- - 0x57ce3992d24bcdf0L ,
36- - 0x4ffcd8376704dec1L ,
37- - 0x40a680384110f11cL ,
38- - 0x391ff40cc257703eL ,
39- - 0x2a586eb86cf558dbL ,
40- 0x06CA6351E003826FL ,
41- 0x142929670A0E6E70L ,
42- 0x27B70A8546D22FFCL ,
43- 0x2E1B21385C26C926L ,
44- 0x4D2C6DFC5AC42AEDL ,
45- 0x53380D139D95B3DFL ,
46- 0x650A73548BAF63DEL ,
47- 0x766A0ABB3C77B2A8L ,
48- - 0x7e3d36d1b812511aL ,
49- - 0x6d8dd37aeb7dcac5L ,
50- - 0x5d40175eb30efc9cL ,
51- - 0x57e599b443bdcfffL ,
52- - 0x3db4748f2f07686fL ,
53- - 0x3893ae5cf9ab41d0L ,
54- - 0x2e6d17e62910ade8L ,
55- - 0x2966f9dbaa9a56f0L ,
56- - 0xbf1ca7aa88edfd6L ,
57- 0x106AA07032BBD1B8L ,
58- 0x19A4C116B8D2D0C8L ,
59- 0x1E376C085141AB53L ,
60- 0x2748774CDF8EEB99L ,
61- 0x34B0BCB5E19B48A8L ,
62- 0x391C0CB3C5C95A63L ,
63- 0x4ED8AA4AE3418ACBL ,
64- 0x5B9CCA4F7763E373L ,
65- 0x682E6FF3D6B2B8A3L ,
66- 0x748F82EE5DEFB2FCL ,
67- 0x78A5636F43172F60L ,
68- - 0x7b3787eb5e0f548eL ,
69- - 0x7338fdf7e59bc614L ,
70- - 0x6f410005dc9ce1d8L ,
71- - 0x5baf9314217d4217L ,
72- - 0x41065c084d3986ebL ,
73- - 0x398e870d1c8dacd5L ,
74- - 0x35d8c13115d99e64L ,
75- - 0x2e794738de3f3df9L ,
76- - 0x15258229321f14e2L ,
77- - 0xa82b08011912e88L ,
78- 0x06F067AA72176FBAL ,
79- 0x0A637DC5A2C898A6L ,
80- 0x113F9804BEF90DAEL ,
81- 0x1B710B35131C471BL ,
82- 0x28DB77F523047D84L ,
83- 0x32CAAB7B40C72493L ,
84- 0x3C9EBE0A15C9BEBCL ,
85- 0x431D67C49C100D4CL ,
86- 0x4CC5D4BECB3E42B6L ,
87- 0x597F299CFC657E2AL ,
88- 0x5FCB6FAB3AD6FAECL ,
89- 0x6C44198C4A475817L
9+ private val K = longArrayOf(
10+ 0x428A2F98D728AE22L , 0x7137449123EF65CDL , - 0x4a3f043013b2c4d1L , - 0x164a245a7e762444L ,
11+ 0x3956C25BF348B538L , 0x59F111F1B605D019L , - 0x6dc07d5b50e6b065L , - 0x54e3a12a25927ee8L ,
12+ - 0x27f855675cfcfdbeL , 0x12835B0145706FBEL , 0x243185BE4EE4B28CL , 0x550C7DC3D5FFB4E2L ,
13+ 0x72BE5D74F27B896FL , - 0x7f214e01c4e9694fL , - 0x6423f958da38edcbL , - 0x3e640e8b3096d96cL ,
14+ - 0x1b64963e610eb52eL , - 0x1041b879c7b0da1dL , 0x0FC19DC68B8CD5B5L , 0x240CA1CC77AC9C65L ,
15+ 0x2DE92C6F592B0275L , 0x4A7484AA6EA6E483L , 0x5CB0A9DCBD41FBD4L , 0x76F988DA831153B5L ,
16+ - 0x67c1aead11992055L , - 0x57ce3992d24bcdf0L , - 0x4ffcd8376704dec1L , - 0x40a680384110f11cL ,
17+ - 0x391ff40cc257703eL , - 0x2a586eb86cf558dbL , 0x06CA6351E003826FL , 0x142929670A0E6E70L ,
18+ 0x27B70A8546D22FFCL , 0x2E1B21385C26C926L , 0x4D2C6DFC5AC42AEDL , 0x53380D139D95B3DFL ,
19+ 0x650A73548BAF63DEL , 0x766A0ABB3C77B2A8L , - 0x7e3d36d1b812511aL , - 0x6d8dd37aeb7dcac5L ,
20+ - 0x5d40175eb30efc9cL , - 0x57e599b443bdcfffL , - 0x3db4748f2f07686fL , - 0x3893ae5cf9ab41d0L ,
21+ - 0x2e6d17e62910ade8L , - 0x2966f9dbaa9a56f0L , - 0xbf1ca7aa88edfd6L , 0x106AA07032BBD1B8L ,
22+ 0x19A4C116B8D2D0C8L , 0x1E376C085141AB53L , 0x2748774CDF8EEB99L , 0x34B0BCB5E19B48A8L ,
23+ 0x391C0CB3C5C95A63L , 0x4ED8AA4AE3418ACBL , 0x5B9CCA4F7763E373L , 0x682E6FF3D6B2B8A3L ,
24+ 0x748F82EE5DEFB2FCL , 0x78A5636F43172F60L , - 0x7b3787eb5e0f548eL , - 0x7338fdf7e59bc614L ,
25+ - 0x6f410005dc9ce1d8L , - 0x5baf9314217d4217L , - 0x41065c084d3986ebL , - 0x398e870d1c8dacd5L ,
26+ - 0x35d8c13115d99e64L , - 0x2e794738de3f3df9L , - 0x15258229321f14e2L , - 0xa82b08011912e88L ,
27+ 0x06F067AA72176FBAL , 0x0A637DC5A2C898A6L , 0x113F9804BEF90DAEL , 0x1B710B35131C471BL ,
28+ 0x28DB77F523047D84L , 0x32CAAB7B40C72493L , 0x3C9EBE0A15C9BEBCL , 0x431D67C49C100D4CL ,
29+ 0x4CC5D4BECB3E42B6L , 0x597F299CFC657E2AL , 0x5FCB6FAB3AD6FAECL , 0x6C44198C4A475817L
9030 )
9131
92- private var H0 = longArrayOf(
32+ private val H0 = longArrayOf(
9333 0x6A09E667F3BCC908L , - 0x4498517a7b3558c5L , 0x3C6EF372FE94F82BL , - 0x5ab00ac5a0e2c90fL ,
9434 0x510E527FADE682D1L , - 0x64fa9773d4c193e1L , 0x1F83D9ABFB41BD6BL , 0x5BE0CD19137E2179L
9535 )
9636
97- fun digest (input : ByteArray ): ByteArray {
98- return digest(input, H0 )
99- }
37+ fun digest (input : ByteArray ) = digest(input, H0 )
10038
10139 // Does the actual hash
10240 internal fun digest (input : ByteArray , h0 : LongArray ): ByteArray {
10341 // First pad the input to the correct length, adding the bits specified in the SHA algorithm
104- var input = input
105- input = padMessage(input)
42+ val paddedInput = padMessage(input)
10643 // Break the padded input up into blocks
107- val blocks: Array <LongArray > = toBlocks(input )
44+ val blocks: Array <LongArray > = toBlocks(paddedInput )
10845 // And get the expanded message blocks
109- val W : Array <LongArray > = calculateMessageBlocks(blocks)
46+ val expandedMessageBlocks : Array <LongArray > = calculateMessageBlocks(blocks)
11047 // Set up the buffer which will eventually contain the final hash
11148 // Initially, it's set to the constants provided as part of the algorithm
11249 val buffer: LongArray = h0.clone()
@@ -122,8 +59,7 @@ object Sha512 {
12259 var h = buffer[7 ]
12360 // Run 80 rounds of the SHA-512 compression function on a-h
12461 for (j in 0 .. 79 ) {
125- val t1: Long =
126- h + bigSig1(e) + ch(e, f, g) + K [j] + W [i][j]
62+ val t1: Long = h + bigSig1(e) + ch(e, f, g) + K [j] + expandedMessageBlocks[i][j]
12763 val t2: Long = bigSig0(a) + maj(a, b, c)
12864 h = g
12965 g = f
@@ -135,14 +71,14 @@ object Sha512 {
13571 a = t1 + t2
13672 }
13773 // After finishing the compression, save the state to the buffer
138- buffer[0 ] = a + buffer[ 0 ]
139- buffer[1 ] = b + buffer[ 1 ]
140- buffer[2 ] = c + buffer[ 2 ]
141- buffer[3 ] = d + buffer[ 3 ]
142- buffer[4 ] = e + buffer[ 4 ]
143- buffer[5 ] = f + buffer[ 5 ]
144- buffer[6 ] = g + buffer[ 6 ]
145- buffer[7 ] = h + buffer[ 7 ]
74+ buffer[0 ] + = a
75+ buffer[1 ] + = b
76+ buffer[2 ] + = c
77+ buffer[3 ] + = d
78+ buffer[4 ] + = e
79+ buffer[5 ] + = f
80+ buffer[6 ] + = g
81+ buffer[7 ] + = h
14682 }
14783 return buffer.foldIndexed(ByteArray (64 )) { index, acc, value ->
14884 val indexBytes = index * 8
@@ -159,19 +95,13 @@ object Sha512 {
15995 }
16096
16197 // Used in the compression function
162- private fun ch (x : Long , y : Long , z : Long ): Long {
163- return x and y xor (x.inv () and z)
164- }
98+ private fun ch (x : Long , y : Long , z : Long ) = x and y xor (x.inv () and z)
16599
166100 // Used in the compression function
167- private fun maj (x : Long , y : Long , z : Long ): Long {
168- return x and y xor (x and z) xor (y and z)
169- }
101+ private fun maj (x : Long , y : Long , z : Long ) = x and y xor (x and z) xor (y and z)
170102
171103 // Used in the compression function
172- private fun rotate (x : Long , l : Int ): Long {
173- return x ushr l or (x shl java.lang.Long .SIZE - l)
174- }
104+ private fun rotate (x : Long , l : Int ) = x ushr l or (x shl java.lang.Long .SIZE - l)
175105
176106 // Used in the compression function
177107 // Sn = right rotate by n bits
@@ -199,65 +129,45 @@ object Sha512 {
199129 private fun padMessage (input : ByteArray ): ByteArray {
200130 // Need to append at least 17 bytes (16 for length of the message, and 1 for the '1' bit)
201131 // then fill with 0s until multiple of 128 bytes
202- var size = input.size + 17
203-
204- val remainder = size % 128
205- if (remainder != 0 ) {
206- size + = 128 - remainder
132+ val size = (input.size + 17 ).let {
133+ if (it % 128 == 0 ) it else it + 128 - it % 128
207134 }
135+
136+ val len = input.size * 8L
208137 // The padded byte array
209- val out = ByteArray (size)
210- // Copy over the old stuff
211- for (i in input.indices) {
212- out [i] = input[i]
138+ return ByteArray (size) { i ->
139+ when {
140+ i < input.size -> input[i]
141+ i == input.size -> 0x80 .toByte()
142+ i == size - 1 -> len.toByte()
143+ i == size - 2 -> (len ushr 8 ).toByte()
144+ i == size - 3 -> (len ushr 16 ).toByte()
145+ i == size - 4 -> (len ushr 24 ).toByte()
146+ else -> 0
147+ }
213148 }
214- // Add the '1' bit
215- out [input.size] = 0x80 .toByte()
216- // And put original length of input at the end of our padded input
217- val len = input.size * 8L
218- out [size - 1 ] = len.toByte()
219- out [size - 2 ] = (len ushr 8 ).toByte()
220- out [size - 3 ] = (len ushr 16 ).toByte()
221- out [size - 4 ] = (len ushr 24 ).toByte()
222- return out
149+
223150 }
224151
225152 // Converts the byte array input starting at index j into a long
226- private fun arrToLong (input : ByteArray , j : Int ): Long {
227- var v: Long = 0
228- for (i in 0 .. 7 ) {
229- v = (v shl 8 ) + input[i + j].toUByte().toLong()
230- }
231- return v
153+ private fun arrToLong (input : ByteArray , j : Int ) = (0 .. 7 ).fold(0L ) { acc, i ->
154+ (acc shl 8 ) + input[i + j].toUByte().toLong()
232155 }
233156
234157 // Converts the byte array input into blocks of longs
235- private fun toBlocks (input : ByteArray ): Array <LongArray > { // a block has: 1024 bits = 128 bytes = 16 longs
236- val blocks = Array (input.size / 128 ) {
237- val block = LongArray (16 )
238- for (j in 0 .. 15 ) { // Set the block value to the correct one
239- block[j] = arrToLong(input, it * 128 + j * 8 )
240- }
241- block
242- }
243- return blocks
158+ // a block has: 1024 bits = 128 bytes = 16 longs
159+ private fun toBlocks (input : ByteArray ) = Array (input.size / 128 ) {
160+ LongArray (16 ) { j -> arrToLong(input, it * 128 + j * 8 ) }
244161 }
245162
246163 // Calculates the expanded message blocks W0-W79
247- private fun calculateMessageBlocks (M : Array <LongArray >): Array < LongArray > {
248- val W = Array ( M .size ) { LongArray ( 80 ) }
249- // For each block in the input
164+ private fun calculateMessageBlocks (M : Array <LongArray >) = Array ( M .size) { i ->
165+ LongArray ( 80 ) { j -> if (j < 16 ) M [i][j] else 0 }
166+ }. apply {
250167 for (i in M .indices) {
251- // For each long in the block
252- for (j in 0 .. 15 ) { // Set the initial values of W to be the value of the input directly
253- W [i][j] = M [i][j]
254- }
255- // For the rest of the values
256- for (j in 16 .. 79 ) { // Do some math from the SHA512 algorithm
257- W [i][j] =
258- smallSig1(W [i][j - 2 ]) + W [i][j - 7 ] + smallSig0(W [i][j - 15 ]) + W [i][j - 16 ]
168+ (16 .. 79 ).forEach { j ->
169+ get(i)[j] = smallSig1(get(i)[j - 2 ]) + get(i)[j - 7 ] + smallSig0(get(i)[j - 15 ]) + get(i)[j - 16 ]
259170 }
260171 }
261- return W
262172 }
263173}
0 commit comments