@@ -9,72 +9,72 @@ import kotlinx.io.*
99import kotlin.test.Test
1010import kotlin.test.assertEquals
1111
12- /* *
13- * Source decrypting all the data read from the downstream using RC4 algorithm.
14- *
15- * See https://en.wikipedia.org/wiki/RC4 for more information about the cypher.
16- *
17- * Implementation of RC4 stream cypher based on http://cypherpunks.venona.com/archive/1994/09/msg00304.html
18- */
19- @OptIn(ExperimentalUnsignedTypes ::class )
20- class RC4DecryptingSource (private val downstream : RawSource , key : String ): RawSource {
21- private val buffer = Buffer ()
22- private val key = RC4Key (key)
12+ class RC4SourceSample {
13+ @Test
14+ fun rc4 () {
15+ /* *
16+ * Source decrypting all the data read from the downstream using RC4 algorithm.
17+ *
18+ * See https://en.wikipedia.org/wiki/RC4 for more information about the cypher.
19+ *
20+ * Implementation of RC4 stream cypher based on http://cypherpunks.venona.com/archive/1994/09/msg00304.html
21+ */
22+ @OptIn(ExperimentalUnsignedTypes ::class )
23+ class RC4DecryptingSource (private val downstream : RawSource , key : String ): RawSource {
24+ private val buffer = Buffer ()
25+ private val key = RC4Key (key)
2326
24- override fun readAtMostTo (sink : Buffer , byteCount : Long ): Long {
25- val bytesRead = downstream.readAtMostTo(buffer, byteCount)
26- if (bytesRead == - 1L ) {
27- return - 1L
28- }
27+ override fun readAtMostTo (sink : Buffer , byteCount : Long ): Long {
28+ val bytesRead = downstream.readAtMostTo(buffer, byteCount)
29+ if (bytesRead == - 1L ) {
30+ return - 1L
31+ }
2932
30- while (! buffer.exhausted()) {
31- val byte = buffer.readByte()
32- sink.writeByte(byte.xor(key.nextByte()))
33- }
33+ while (! buffer.exhausted()) {
34+ val byte = buffer.readByte()
35+ sink.writeByte(byte.xor(key.nextByte()))
36+ }
3437
35- return bytesRead
36- }
38+ return bytesRead
39+ }
3740
38- override fun close () = downstream.close()
41+ override fun close () = downstream.close()
3942
40- private class RC4Key (key : String ) {
41- private var keyState: UByteArray
42- private var keyX: Int = 0
43- private var keyY: Int = 0
43+ private inner class RC4Key (key : String ) {
44+ private var keyState: UByteArray
45+ private var keyX: Int = 0
46+ private var keyY: Int = 0
4447
45- init {
46- require(key.isNotEmpty()) { " Key could not be empty" }
47- val keyBytes = key.encodeToByteArray()
48- keyState = UByteArray (256 ) { it.toUByte() }
49- var index1 = 0
50- var index2 = 0
48+ init {
49+ require(key.isNotEmpty()) { " Key could not be empty" }
50+ val keyBytes = key.encodeToByteArray()
51+ keyState = UByteArray (256 ) { it.toUByte() }
52+ var index1 = 0
53+ var index2 = 0
5154
52- for (idx in keyState.indices) {
53- index2 = (keyBytes[index1] + keyState[idx].toInt() + index2) % 256
54- swapStateBytes(idx, index2)
55- index1 = (index1 + 1 ) % keyBytes.size
56- }
57- }
55+ for (idx in keyState.indices) {
56+ index2 = (keyBytes[index1] + keyState[idx].toInt() + index2) % 256
57+ swapStateBytes(idx, index2)
58+ index1 = (index1 + 1 ) % keyBytes.size
59+ }
60+ }
5861
59- fun nextByte (): Byte {
60- keyX = (keyX + 1 ) % 256
61- keyY = (keyState[keyX].toInt() + keyY) % 256
62- swapStateBytes(keyX, keyY)
63- val idx = (keyState[keyX] + keyState[keyY]) % 256U
64- return keyState[idx.toInt()].toByte()
65- }
62+ fun nextByte (): Byte {
63+ keyX = (keyX + 1 ) % 256
64+ keyY = (keyState[keyX].toInt() + keyY) % 256
65+ swapStateBytes(keyX, keyY)
66+ val idx = (keyState[keyX] + keyState[keyY]) % 256U
67+ return keyState[idx.toInt()].toByte()
68+ }
6669
67- private fun swapStateBytes (x : Int , y : Int ) {
68- val tmp = keyState[x]
69- keyState[x] = keyState[y]
70- keyState[y] = tmp
70+ private fun swapStateBytes (x : Int , y : Int ) {
71+ val tmp = keyState[x]
72+ keyState[x] = keyState[y]
73+ keyState[y] = tmp
74+ }
75+ }
7176 }
72- }
73- }
7477
75- class RC4SourceSample {
76- @Test
77- fun rc4 () {
7878 val key = " key"
7979 val source = Buffer ().also { it.write(byteArrayOf(0x58 , 0x09 , 0x57 , 0x9fU .toByte(), 0x41 , 0xfbU .toByte())) }
8080 val rc4Source = RC4DecryptingSource (source, key).buffered()
0 commit comments