The ISAAC cipher: Difference between revisions

Added Kotlin
m (→‎{{header|Sidef}}: updated code)
(Added Kotlin)
Line 2,163:
}
}</lang>
 
=={{header|Kotlin}}==
{{trans|C}}
<lang scala>// version 1.1.3
 
/* external results */
val randrsl = IntArray(256)
var randcnt = 0
/* internal state */
val mm = IntArray(256)
var aa = 0
var bb = 0
var cc = 0
 
const val GOLDEN_RATIO = 0x9e3779b9.toInt()
 
fun isaac() {
cc++ // cc just gets incremented once per 256 results
bb += cc // then combined with bb
for (i in 0..255) {
val x = mm[i]
when (i % 4) {
0 -> aa = aa xor (aa shl 13)
1 -> aa = aa xor (aa ushr 6)
2 -> aa = aa xor (aa shl 2)
3 -> aa = aa xor (aa ushr 16)
}
aa += mm[(i + 128) % 256]
val y = mm[(x ushr 2) % 256] + aa + bb
mm[i] = y
bb = mm[(y ushr 10) % 256] + x
randrsl[i] = bb
}
randcnt = 0
}
 
/* if (flag == true), then use the contents of randrsl to initialize mm. */
fun mix(n: IntArray) {
n[0] = n[0] xor (n[1] shl 11); n[3] += n[0]; n[1] += n[2]
n[1] = n[1] xor (n[2] ushr 2); n[4] += n[1]; n[2] += n[3]
n[2] = n[2] xor (n[3] shl 8); n[5] += n[2]; n[3] += n[4]
n[3] = n[3] xor (n[4] ushr 16); n[6] += n[3]; n[4] += n[5]
n[4] = n[4] xor (n[5] shl 10); n[7] += n[4]; n[5] += n[6]
n[5] = n[5] xor (n[6] ushr 4); n[0] += n[5]; n[6] += n[7]
n[6] = n[6] xor (n[7] shl 8); n[1] += n[6]; n[7] += n[0]
n[7] = n[7] xor (n[0] ushr 9); n[2] += n[7]; n[0] += n[1]
}
 
fun randinit(flag: Boolean) {
aa = 0
bb = 0
cc = 0
val n = IntArray(8) { GOLDEN_RATIO }
for (i in 0..3) mix(n) // scramble the array
 
for (i in 0..255 step 8) { // fill in mm with messy stuff
if (flag) { // use all the information in the seed
for (j in 0..7) n[j] += randrsl[i + j]
}
mix(n)
for (j in 0..7) mm[i + j] = n[j]
}
 
if (flag) {
/* do a second pass to make all of the seed affect all of mm */
for (i in 0..255 step 8) {
for (j in 0..7) n[j] += mm[i + j]
mix(n)
for (j in 0..7) mm[i + j] = n[j]
}
}
 
isaac() // fill in the first set of results
randcnt = 0 // prepare to use the first set of results
}
 
/* As Kotlin doesn't (yet) support unsigned types, we need to use
Long here to get a random value in the range of a UInt */
fun iRandom(): Long {
val r = randrsl[randcnt++]
if (randcnt > 255) {
isaac()
randcnt = 0
}
return r.toLong() and 0xFFFFFFFFL
}
 
/* Get a random character (as Int) in printable ASCII range */
fun iRandA() = (iRandom() % 95 + 32).toInt()
 
/* Seed ISAAC with a string */
fun iSeed(seed: String, flag: Boolean) {
for (i in 0..255) mm[i] = 0
val m = seed.length
for (i in 0..255) {
/* in case seed has less than 256 elements */
randrsl[i] = if (i >= m) 0 else seed[i].toInt()
}
/* initialize ISAAC with seed */
randinit(flag)
}
 
/* XOR cipher on random stream. Output: ASCII string */
fun vernam(msg: String) : String {
val len = msg.length
val v = ByteArray(len)
for (i in 0 until len) {
v[i] = (iRandA() xor msg[i].toInt()).toByte()
}
return v.toString(charset("ASCII"))
}
 
/* constants for Caesar */
const val MOD = 95
const val START = 32
 
/* cipher modes for Caesar */
enum class CipherMode {
ENCIPHER, DECIPHER, NONE
}
 
/* Caesar-shift a printable character */
fun caesar(m: CipherMode, ch: Int, shift: Int, modulo: Int, start: Int): Char {
val sh = if (m == CipherMode.DECIPHER) -shift else shift
var n = (ch - start) + sh
n %= modulo
if (n < 0) n += modulo
return (start + n).toChar()
}
 
/* Caesar-shift a string on a pseudo-random stream */
fun caesarStr(m: CipherMode, msg: String, modulo: Int, start: Int): String {
val sb = StringBuilder(msg.length)
/* Caesar-shift message */
for (c in msg) {
sb.append(caesar(m, c.toInt(), iRandA(), modulo, start))
}
return sb.toString()
}
 
fun String.toHexByteString() =
this.map { "%02X".format(it.toInt()) }.joinToString("")
fun main(args: Array<String>) {
val msg = "a Top Secret secret"
val key = "this is my secret key"
 
// Vernam & Caesar ciphertext
iSeed(key, true)
val vctx = vernam(msg)
val cctx = caesarStr(CipherMode.ENCIPHER, msg, MOD, START)
// Vernam & Caesar plaintext
iSeed(key, true)
val vptx = vernam(vctx)
val cptx = caesarStr(CipherMode.DECIPHER, cctx, MOD, START)
// Program output
println("Message : $msg")
println("Key : $key")
println("XOR : ${vctx.toHexByteString()}")
println("XOR dcr : $vptx")
println("MOD : ${cctx.toHexByteString()}")
println("MOD dcr : $cptx")
}</lang>
 
{{out}}
<pre>
Message : a Top Secret secret
Key : this is my secret key
XOR : 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR dcr : a Top Secret secret
MOD : 734270227D36772A783B4F2A5F206266236978
MOD dcr : a Top Secret secret
</pre>
 
=={{header|Pascal}}==
9,476

edits