// Skein 1.3 512-512. Author: Thomas Mueller, 2008-2009. Public domain. package skein object Skein512 { var d = "ND3EAJ.;1QDGLXV)G>B8-1*R9=GK(6XC".getBytes def hash(m: Array[Byte], h: Array[Byte]) { val c = Array.make(9, 0L) def block(b: Array[Byte], t0: Long, t1: Long, o: Int) { val x = Array.make(8, 0L); val k = Array.make(8, 0L) c(8) = 0x1BD11BDAA9FC1A22L for (i <- 0 until 8) { for (j <- 0 until 8) k(i) = (k(i) << 8) + (b(o + i * 8 + 7 - j) & 255) x(i) = k(i) + c(i); c(8) ^= c(i) } x(5) += t0; x(6) += t1; val t = Array(t0, t1, t0 ^ t1) for (r <- 0 until 18) { for (i <- 0 until 16) { val m = 2 * ((i + (1 + i + i) * (i / 4)) & 3) val n = (1 + i + i) & 7 val s = d(16 * (r & 1) + i) - 32 x(m) += x(n); x(n) = (x(n) << s | x(n) >>> (64 - s)) ^ x(m) } for (i <- 0 until 8) x(i) += c((r + 1 + i) % 9) x(5) += t((r + 1) % 3); x(6) += t((r + 2) % 3); x(7) += r + 1 } for (i <- 0 until 8) c(i) = k(i) ^ x(i) } val b = "SHA3\1\0\0\0\0\2".getBytes ++ new Array[Byte](54) block(b, 32, 196L << 56, 0) var t0 = 0; var t1 = 112L << 56 while(t0 < m.length - 64) { t0 += 64; block(m, t0, t1, t0 - 64); t1 = 48L << 56 } for(i <- 0 until 64) b(i) = if (i + t0 < m.length) m(i + t0) else 0 block(b, m.length, t1 | 128L << 56, 0) block(new Array[Byte](64), 8, 255L << 56, 0) for (i <- 0 until 64) h(i) = (c(i / 8) >> (i & 7) * 8).toByte } }