· 7 years ago · Jul 31, 2018, 10:04 PM
1package q;
2
3import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
4import com.sun.org.apache.xml.internal.security.utils.Base64;
5import org.bouncycastle.jce.provider.BouncyCastleProvider;
6import q.f5.Extract;
7import q.f5.ortega.HuffmanDecode;
8
9import javax.crypto.Cipher;
10import javax.crypto.SecretKey;
11import javax.crypto.SecretKeyFactory;
12import javax.crypto.spec.IvParameterSpec;
13import javax.crypto.spec.PBEKeySpec;
14import javax.crypto.spec.SecretKeySpec;
15import java.io.*;
16import java.nio.charset.Charset;
17import java.nio.charset.StandardCharsets;
18import java.nio.file.Files;
19import java.nio.file.Path;
20import java.nio.file.Paths;
21import java.security.Security;
22import java.security.spec.KeySpec;
23import java.util.ArrayList;
24import java.util.List;
25import java.util.Timer;
26import java.util.TimerTask;
27import java.util.concurrent.ExecutionException;
28import java.util.concurrent.ExecutorService;
29import java.util.concurrent.Executors;
30import java.util.concurrent.Future;
31import java.util.concurrent.atomic.AtomicLong;
32
33public class Main {
34
35 public static String DecryptWithPassword(String password, byte[] iv, byte[] message, byte[] salt) {
36 String new_message = null;
37
38 try {
39 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
40 KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
41 SecretKey tmp = factory.generateSecret(spec);
42 SecretKey secret_key = new SecretKeySpec(tmp.getEncoded(), "AES");
43
44 Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
45 cipher.init(Cipher.DECRYPT_MODE, secret_key, new IvParameterSpec(iv));
46
47 new_message = new String(cipher.doFinal(message));
48 } catch (Exception e) {
49 e.printStackTrace();
50 }
51
52 return new_message;
53 }
54
55 private static String extractPassword(String from_password) {
56 return from_password.substring(0, from_password.length()/3);
57 }
58
59 private static String extractPasswordSalt(String from_password) {
60 return from_password.substring(from_password.length()/3, (from_password.length()/3)*2);
61 }
62
63 private static String extractF5Seed(String from_password) {
64 return from_password.substring((from_password.length()/3)*2);
65 }
66
67 public static class Constants {
68 public final static String PASSWORD_SENTINEL = "----* PK v 1.0 REQUIRES PASSWORD ----*";
69 }
70
71 public static int extract(int[] coeff, String mPassword) {
72 Extract e = new Extract();
73 OutputStream ostream = new ByteArrayOutputStream();
74 try {
75 e.extract(coeff, ostream, extractF5Seed(mPassword));
76 // TEST - FOR BRUTE FORCING LAST 1/3
77 //e.extract(coeff, ostream, mPassword);
78 } catch (IOException e1) {
79 e1.printStackTrace();
80 }
81
82 String mMessage = ostream.toString();
83 // System.out.println("message is " + mMessage);
84
85 if (mMessage != null && mMessage.indexOf(Constants.PASSWORD_SENTINEL) == 0) {
86 String secret_message = mMessage.substring(Constants.PASSWORD_SENTINEL.length());
87 System.out.println("!!!!!!!!!!! PARTIAL MATCH - " + mPassword);
88 System.out.println("!!!!!!!!!!! PARTIAL MATCH - " + mPassword);
89 System.out.println("!!!!!!!!!!! PARTIAL MATCH - " + mPassword);
90 System.out.println("!!!!!!!!!!! PARTIAL MATCH - " + mPassword);
91 // TEST - FOR BRUTE FORCING LAST 1/3
92 // Runtime.getRuntime().halt(1);
93 int idx = secret_message.indexOf("\n");
94
95 String mMsg = secret_message.substring(idx + 1, secret_message.length());
96 String mIv = secret_message.substring(0, idx);
97
98 byte[] message = new byte[0];
99 byte[] iv = new byte[0];
100 try {
101 message = Base64.decode(mMsg);
102 iv = Base64.decode(mIv);
103 } catch (Base64DecodingException e1) {
104 e1.printStackTrace();
105 }
106
107 String sm = DecryptWithPassword(extractPassword(mPassword), iv, message, extractPasswordSalt(mPassword).getBytes());
108 if (sm != null) {
109 mMessage = sm;
110 System.out.println("CORRECT PASSWORD " + mPassword);
111 System.out.println("==============================");
112 System.out.println(mMessage);
113 System.out.println("==============================");
114 return 1;
115 } else {
116 // Wrong password
117 System.out.println("decryption error with password " + mPassword);
118 }
119 } else {
120 //System.out.println("bad password [" + mPassword + "] ");
121 }
122 return 0;
123 }
124
125 public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
126 Security.addProvider(new BouncyCastleProvider());
127
128 final File f = new File(args[0]);
129 final FileInputStream fis = new FileInputStream(f);
130 byte[] carrier; // carrier data
131 carrier = new byte[(int) f.length()];
132 fis.read(carrier);
133 final HuffmanDecode hd = new HuffmanDecode(carrier);
134 System.out.println("Huffman decoding starts");
135 final int[] coeff = hd.decode(); // dct values
136
137 final long startTime = System.currentTimeMillis();
138 AtomicLong lineCount = new AtomicLong(0);
139 Timer t = new Timer();
140 t.schedule(new TimerTask() {
141 @Override
142 public void run() {
143 long estimatedTime = (System.currentTimeMillis() - startTime) / 1000L;
144 System.out.println("count: " + lineCount.get() + " elapsed: " + estimatedTime + "s = rate: " + (lineCount.get() / estimatedTime) + " pw/s");
145 }
146 }, 60000, 60000);
147
148 Path filePath = Paths.get(args[1]);
149 Files.readAllLines(filePath, StandardCharsets.ISO_8859_1)
150 .parallelStream()
151 .forEach(line -> {
152 // System.out.println("trying " + line);
153 int res = extract(coeff, line);
154 if (res == 1) {
155 System.exit(1);
156 }
157 lineCount.incrementAndGet();
158 for (int j = 1; j<line.length() - 3; j++) {
159 String l = line.substring(j);
160 // System.out.println("trying " + l);
161 res = extract(coeff, l);
162 if (res == 1) {
163 System.exit(1);
164 }
165 lineCount.incrementAndGet();
166 }
167 });
168 Runtime.getRuntime().halt(1);
169
170 }
171}