Watermarking Text

Overview

Tesla used space characters in internal emails to identify leaks

Github: https://github.com/gitorko/project06

Watermarking

The below code embeds a binary message with spaces in a given text, this can be used to trace the origin of the text message and which user it belonged to.

Code

 1package com.demo.project06;
 2
 3import java.util.ArrayList;
 4import java.util.List;
 5
 6public class Main {
 7
 8    public static String[] userNames = {"jack@company.com", "adam@company.com", "sally@company.com"};
 9
10    public static String[][] users;
11
12    public static void main(String[] args) {
13        String message = "Hello, How are you today? This is a test message for watermarking. Have a great day!";
14        String[] sentences = message.split("(?<=[.\\?])");
15        if (sentences.length < 3) {
16            throw new RuntimeException("Sentences are too few to encode watermark");
17        }
18        generateUserBinaryIds();
19        // Encoding and Decoding process
20        String user = "adam@company.com";
21        String encodedMessage = encodeMessage(message, user);
22        System.out.println("Watermarked message for " + user + ": \n" + encodedMessage);
23
24        String decodedUser = decodeMessage(encodedMessage);
25        System.out.println("Message belongs to: " + decodedUser);
26    }
27
28    private static void generateUserBinaryIds() {
29
30        users = new String[userNames.length + 1][2];
31        users[0][0] = "NA";
32        users[0][1] = "000";
33
34        for (int i = 1; i <= userNames.length; i++) {
35            // Convert the index into a binary string with padding (e.g., "001", "010", "011", ...)
36            String binaryId = String.format("%3s", Integer.toBinaryString(i)).replace(' ', '0');
37            users[i][0] = userNames[i - 1];
38            users[i][1] = binaryId;
39        }
40    }
41
42    public static String encodeMessage(String message, String user) {
43        // Loop through the users to find the binary ID of the user
44        for (String[] u : users) {
45            if (user.equals(u[0])) {
46                String binaryId = u[1];
47                return watermarkMessage(message, binaryId);
48            }
49        }
50        throw new RuntimeException("Unknown user: " + user);
51    }
52
53    public static String decodeMessage(String message) {
54        // Split the message into sentences, keeping the period (. or ?)
55        String[] sentences = message.split("(?<=[.\\?])");
56        StringBuilder binaryPattern = new StringBuilder();
57        for (String sentence : sentences) {
58            int spaceCount = countLeadingSpaces(sentence);
59            binaryPattern.append(spaceCount == 0 ? "0" : "1");
60        }
61        System.out.println("Binary Code: " + binaryPattern);
62        for (String[] user : users) {
63            String name = user[0];
64            String binaryId = user[1];
65            if (binaryPattern.toString().equals(binaryId)) {
66                return name;
67            }
68        }
69        return "Unknown User";
70    }
71
72    private static String watermarkMessage(String message, String binaryId) {
73        // Split the message into sentences, keeping the period (. or ?)
74        String[] sentences = message.split("(?<=[.\\?])");
75
76        List<String> watermarkedSentences = new ArrayList<>();
77        for (int i = 0; i < sentences.length; i++) {
78            char spaceCount = binaryId.charAt(i % binaryId.length());
79            int spacesToAdd = spaceCount == '1' ? 1 : 0;  // If '1', add 1 space; if '0', add 0 spaces
80            String sentenceWithSpaces = " ".repeat(spacesToAdd) + sentences[i];
81            watermarkedSentences.add(sentenceWithSpaces);
82        }
83        return String.join("", watermarkedSentences);
84    }
85
86    private static int countLeadingSpaces(String sentence) {
87        int count = 0;
88        int length = sentence.length();
89        while (count < length && sentence.charAt(count) == ' ') {
90            count++;
91        }
92        return count > 1 ? 1 : 0;
93    }
94}

Setup

 1# Project06
 2
 3Encode and Decode watermarked text message
 4
 5### Version
 6
 7Check version
 8
 9```bash
10$java --version
11openjdk 21
12```

References

https://en.wikipedia.org/wiki/Text_watermarking

comments powered by Disqus