Skip to content

Commit 806ce40

Browse files
Implement Huffman decoding
1 parent f1382b6 commit 806ce40

File tree

1 file changed

+43
-6
lines changed
  • app/src/main/java/org/vonderheidt/hips/utils

1 file changed

+43
-6
lines changed

app/src/main/java/org/vonderheidt/hips/utils/Huffman.kt

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.vonderheidt.hips.utils
22

3-
import kotlinx.coroutines.delay
43
import org.vonderheidt.hips.data.Settings
54

65
/**
@@ -101,13 +100,51 @@ object Huffman {
101100
* Function to decode a cover text into (the encrypted binary representation of) the secret message using Huffman decoding.
102101
*
103102
* Corresponds to Stegasuras method `decode_huffman` in `huffman_baseline.py`.
103+
*
104+
* @param context The context to decode the cover text with.
105+
* @param coverText The cover text containing a secret message.
106+
* @return The encrypted binary representation of the secret message.
104107
*/
105-
suspend fun decode(context: String, coverText: String, bitsPerToken: Int = Settings.bitsPerToken): ByteArray {
106-
// Wait 5 seconds
107-
delay(5000)
108+
fun decode(context: String, coverText: String): ByteArray {
109+
// Tokenize context and cover text
110+
val contextTokens = LlamaCpp.tokenize(context)
111+
val coverTextTokens = LlamaCpp.tokenize(coverText)
112+
113+
// Initialize string to store cipher bits
114+
var cipherBitString = ""
115+
116+
// Initialize variables and flags for loop (similar to encode)
117+
var i = 0
118+
119+
var isFirstRun = true
120+
var coverTextToken = -1 // Will always be overwritten with last cover text token
121+
122+
// Decode every cover text token into bitsPerToken bits
123+
while (i < coverTextTokens.size) {
124+
// Calculate the logit matrix again initially from context tokens, then from last cover text token, and get last row
125+
val logits = LlamaCpp.getLogits(if (isFirstRun) contextTokens else intArrayOf(coverTextToken)).last()
126+
127+
// Get top 2^bitsPerToken logits
128+
val topLogits = getTopLogits(logits)
129+
130+
// Construct Huffman tree
131+
val huffmanCoding = HuffmanCoding()
132+
huffmanCoding.buildHuffmanTree(topLogits)
133+
huffmanCoding.mergeHuffmanNodes()
134+
huffmanCoding.generateHuffmanCodes() // Return value (root) is not needed here as Huffman tree is not traversed manually
135+
136+
// Querying Huffman tree for the path to the current cover text token decodes the encoded information
137+
cipherBitString += huffmanCoding.huffmanCodes[coverTextTokens[i]]
138+
139+
// Update loop variables and flags
140+
coverTextToken = coverTextTokens[i]
141+
isFirstRun = false
142+
143+
i++
144+
}
108145

109-
// Return placeholder
110-
val cipherBits = ByteArray(size = 0)
146+
// Create ByteArray from bit string to return cipher bits
147+
val cipherBits = Format.asByteArray(cipherBitString)
111148

112149
return cipherBits
113150
}

0 commit comments

Comments
 (0)