Java Implementation of DSS Signing and Cipher Cryptanalysis
Digital Signature Standard (DSS) Client Implementation
This Java class, DssClient, demonstrates the generation of a Digital Signature Standard (DSS) signature and subsequent transmission of the parameters to a verification server via a socket connection.
1.1. DssClient Class Structure and Signature Generation
The dssSign method calculates the signature components r and s, along with the public key y, based on input parameters (primes p, q, generator g, private key x, message hash H(m), and random nonce k).
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class DssClient {
public static long[] dssSign(long p, long q, long g, long x, long Hm, long k) {
long y = modPow(g, x, p);
long r = modPow(g, k, p) % q;
long kInv = modInverse(k, q);
long s = (kInv * (Hm + x * r)) % q;
System.out.println("\n---- Client: Signature Generation ----");
System.out.println("y = " + y);
System.out.println("r = " + r);
System.out.println("s = " + s);
return new long[]{r, s, y}; }
1.2. Modular Arithmetic Helper Functions
Modular Exponentiation (modPow)
This utility calculates (base^exp) mod mod efficiently.
// Modular exponentiation
public static long modPow(long base, long exp, long mod) {
long result = 1;
base %= mod;
while (exp > 0) {
if ((exp & 1) == 1) result = (result * base) % mod;
base = (base * base) % mod;
exp >>= 1; }
return result; }
Modular Inverse (modInverse) using Extended Euclidean Algorithm
This function finds the modular multiplicative inverse necessary for calculating the signature component s.
// Modular inverse using Extended Euclid
public static long modInverse(long a, long m) {
long m0 = m, t, q;
long x0 = 0, x1 = 1;
if (m == 1) return 0;
while (a > 1) {
q = a / m;
t = m;
m = a % m;
a = t;
t = x0;
x0 = x1 - q * x0;
x1 = t; }
if (x1 < 0) x1 += m0;
return x1; }
1.3. Client Main Execution and Data Transmission
The main method prompts the user for all necessary DSS parameters, generates the signature, and sends the data package (p, q, g, H(m), r, s, y) to a server listening on port 5000.
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
System.out.print("Enter p: ");
long p = sc.nextLong();
System.out.print("Enter q: ");
long q = sc.nextLong();
System.out.print("Enter g: ");
long g = sc.nextLong();
System.out.print("Enter private key x: ");
long x = sc.nextLong();
System.out.print("Enter H(m): ");
long Hm = sc.nextLong();
System.out.print("Enter random k: ");
long k = sc.nextLong();
long[] result = dssSign(p, q, g, x, Hm, k);
long r = result[0], s = result[1], y = result[2];
Socket socket = new Socket("localhost", 5000);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String data = p + "," + q + "," + g + "," + Hm + "," + r + "," + s + "," + y;
out.println(data);
String serverMsg = in.readLine();
System.out.println("\nServer says: " + serverMsg);
socket.close();
sc.close();}}
Caesar Cipher Server and Cryptanalysis Tools
This section presents a server implementation designed to receive ciphertext and perform cryptanalysis using common attack methods.
2.1. Server Setup and Decryption Method
The server uses basic networking imports. Note that the decrypt method structure was fragmented in the source material, and the implementation logic is incomplete, but the provided lines are preserved.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class CeasarCipherServer {
private final String alpha = "abcdefghijklmnopqrstuvwxyz";
public String decrypt(String cipher, int k) {
return plain.toString();
}
2.2. Brute-Force Attack Implementation
The brute-force method systematically attempts decryption using every possible key (0 through 25) for the Caesar cipher.
public void bruteForce(String ciphertxt) {
System.out.println("\n🔎 Brute-force results (all possible keys):");
for (int i = 0; i < 26; i++) {
String plaintxt = decrypt(ciphertxt, i);
System.out.println("Key: " + i + " -> " + plaintxt);
}
}
2.3. Frequency Analysis Attack
This method performs a statistical attack by identifying the most frequent character in the ciphertext and assuming it corresponds to the most common letter in English (‘e’).
public void freqAttack(String ciphertxt) {
int[] freq = new int[26];
for (char ch : ciphertxt.toCharArray()) {
int idx = alpha.indexOf(ch);
if (idx >= 0) freq[idx]++;
}
int maxFreq = 0, guessIndex = -1;
for (int i = 0; i < 26; i++) {
if (freq[i] > maxFreq) {
maxFreq = freq[i];
guessIndex = i;
}
}
if (guessIndex == -1) {
System.out.println("\nFrequency analysis: no alphabetic characters found.");
return;
}
// Assuming most frequent plaintext letter is 'e' (index 4)
int eIndex = 4;
int probableKey = (guessIndex - eIndex + 26) % 26;
String guess = decrypt(ciphertxt, probableKey);
System.out.println("\n🧠Frequency Analysis Guess:");
System.out.println("Most frequent cipher letter: " + alpha.charAt(guessIndex));
System.out.println("Probable key (assuming 'e' most common): " + probableKey);
System.out.println("Decrypted guess: " + guess);
}
2.4. Server Main Execution
The server listens on port 5055, receives the ciphertext from a client, and initiates the cryptanalysis routines.
public static void main(String[] args) {
int port = 5055;
System.out.println("Server starting, listening on port " + port + " ... (waiting for a client)");
try (ServerSocket ss = new ServerSocket(port);
Socket sock = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()))) {
System.out.println("Connection established from " + sock.getInetAddress());
String ciphertxt = br.readLine(); // client must send a newline-terminated line
if (ciphertxt == null) {
System.out.println("No data received.");
return;
}
System.out.println("\nReceived ciphertext: " + ciphertxt);
CeasarCipherServer cp = new CeasarCipherServer();
cp.bruteForce(ciphertxt);
cp.freqAttack(ciphertxt);
System.out.println("\nServer finished analysis and will exit.");
} catch (Exception e) {
System.err.println("Server error: " + e.getMessage());
e.printStackTrace();
}
}
}
