]>
jfr.im git - irc/rizon/acid.git/blob - acid/src/main/java/net/rizon/acid/util/CloakGenerator.java
fe27d35e1d33f81b372d6bd8f28547f64b2eebe6
1 package net
.rizon
.acid
.util
;
3 import java
.net
.InetAddress
;
4 import java
.net
.Inet4Address
;
5 import java
.net
.Inet6Address
;
6 import java
.net
.UnknownHostException
;
7 import java
.security
.MessageDigest
;
8 import java
.security
.NoSuchAlgorithmException
;
11 * CloakGenerator that generates a cloaked host from an input IP or hostname.
15 public class CloakGenerator
18 protected String
[] keys
;
19 protected String hostPrefix
;
20 protected MessageDigest digest
;
22 public static boolean validateCloakKey(final String key
)
24 boolean hasLowerCase
= false;
25 boolean hasUpperCase
= false;
26 boolean hasDigit
= false;
28 for (int i
= 0; i
< key
.length(); i
++)
30 char c
= key
.charAt(i
);
31 if (!hasLowerCase
&& Character
.isLowerCase(c
))
35 if (!hasUpperCase
&& Character
.isUpperCase(c
))
39 if (!hasDigit
&& Character
.isDigit(c
))
43 if (hasLowerCase
&& hasUpperCase
&& hasDigit
)
52 public CloakGenerator(String
[] keys
, String hostPrefix
) throws NoSuchAlgorithmException
55 this.hostPrefix
= hostPrefix
;
56 this.digest
= MessageDigest
.getInstance("MD5");
60 * * Cloak an arbitrary host. Will do detection to figure out what kind
63 public String
cloak(String host
)
66 if (host
.contains(":"))
68 /* Plexus' cloaking code has an IPv6 parsing bug where it stops scanning at the first ::. */
69 int cutoff
= host
.indexOf("::");
72 host
= host
.substring(0, cutoff
+ 2);
77 return this.cloak(Inet6Address
.getByName(host
));
79 catch (UnknownHostException e
)
85 else if (host
.contains("."))
87 for (char c
: host
.toCharArray())
89 if (c
!= '.' && !Character
.isDigit(c
)) /* Host. */ {
90 return this.cloakHost(host
);
96 return this.cloak(Inet4Address
.getByName(host
));
98 catch (UnknownHostException e
)
106 return this.cloakHost(host
);
111 * Cloak an internet address.
113 public String
cloak(InetAddress addr
)
115 if (addr
instanceof Inet4Address
)
117 return this.cloakIPv4((Inet4Address
) addr
);
119 else if (addr
instanceof Inet6Address
)
121 return this.cloakIPv6((Inet6Address
) addr
);
127 * Cloak an IPv4 address.
129 * Cloak format: A.B.C.D -> ALPHA.BETA.GAMMA.IP
131 * ALPHA: downmix(md5(md5(keys[1]:A.B.C.D:keys[2])keys[0])) BETA:
132 * downmix(md5(md5(keys[2]:A.B.C:keys[0])keys[1])) GAMMA:
133 * downmix(md5(md5(keys[0]:A.B:keys[1])keys[2]))
135 public String
cloakIPv4(Inet4Address addr
)
137 /* Gather IP pieces. */
138 byte[] bytePieces
= addr
.getAddress();
139 int[] pieces
= new int[bytePieces
.length
];
140 for (int i
= 0; i
< bytePieces
.length
; i
++)
142 pieces
[i
] = bytePieces
[i
] & 0xFF;
145 /* Generate alpha. */
146 String alphaInput
= String
.format("%d.%d.%d.%d", pieces
[0], pieces
[1], pieces
[2], pieces
[3]);
147 String alpha
= this.stage(alphaInput
, this.keys
[1], this.keys
[2], this.keys
[0]);
150 String betaInput
= String
.format("%d.%d.%d", pieces
[0], pieces
[1], pieces
[2]);
151 String beta
= this.stage(betaInput
, this.keys
[2], this.keys
[0], this.keys
[1]);
153 /* Generate gamma. */
154 String gammaInput
= String
.format("%d.%d", pieces
[0], pieces
[1]);
155 String gamma
= this.stage(gammaInput
, this.keys
[0], this.keys
[1], this.keys
[2]);
157 return alpha
+ "." + beta
+ "." + gamma
+ ".IP";
161 * Cloak an IPv6 address.
163 * Cloak format: a:b:c:d:e:f:g:h -> ALPHA:BETA:GAMMA:IP
165 * ALPHA: downmix(md5(md5(keys[1]:a:b:c:d:e:f:g:h:keys[2])keys[0]))
166 * BETA: downmix(md5(md5(keys[2]:a:b:c:d:e:f:g:keys[0])keys[1])) GAMMA:
167 * downmix(md5(md5(keys[0]:a:b:c:d:keys[1])keys[2]))
169 public String
cloakIPv6(Inet6Address addr
)
171 /* Gather IP pieces. */
172 byte[] bytePieces
= addr
.getAddress();
173 int[] pieces
= new int[bytePieces
.length
/ 2];
174 System
.out
.println("Byte length: " + bytePieces
.length
);
175 for (int i
= 0; i
< bytePieces
.length
; i
+= 2)
177 pieces
[i
/ 2] = ((bytePieces
[i
] & 0xFF) << 8) | (bytePieces
[i
+ 1] & 0xFF);
180 /* Generate alpha. */
181 String alphaInput
= String
.format("%x:%x:%x:%x:%x:%x:%x:%x",
182 pieces
[0], pieces
[1], pieces
[2], pieces
[3], pieces
[4], pieces
[5], pieces
[6], pieces
[7]);
183 String alpha
= this.stage(alphaInput
, this.keys
[1], this.keys
[2], this.keys
[0]);
186 String betaInput
= String
.format("%x:%x:%x:%x:%x:%x:%x",
187 pieces
[0], pieces
[1], pieces
[2], pieces
[3], pieces
[4], pieces
[5], pieces
[6]);
188 String beta
= this.stage(betaInput
, this.keys
[2], this.keys
[0], this.keys
[1]);
190 /* Generate gamma. */
191 String gammaInput
= String
.format("%x:%x:%x:%x", pieces
[0], pieces
[1], pieces
[2], pieces
[3]);
192 String gamma
= this.stage(gammaInput
, this.keys
[0], this.keys
[1], this.keys
[2]);
194 return alpha
+ ":" + beta
+ ":" + gamma
+ ":IP";
198 * Cloak a reverse DNS host.
200 * Cloak format: my.host.com -> PREFIX-ALPHA.host.com localhost ->
203 * ALPHA: downmix(md5(md5(keys[0]:my.host.com:keys[1])keys[2]))
205 public String
cloakHost(String host
)
207 int dot
= host
.indexOf('.');
208 String alpha
= this.stage(host
, this.keys
[0], this.keys
[1], this.keys
[2]);
210 if (dot
== -1 || dot
== host
.length() - 1)
212 return this.hostPrefix
+ alpha
;
216 return this.hostPrefix
+ alpha
+ host
.substring(dot
);
221 * Perform a downmix(md5(md5(key1:host:key2)key3)) stage.
223 protected String
stage(String input
, String key1
, String key2
, String key3
)
225 String salted
= String
.format("%s:%s:%s", key1
, input
, key2
);
226 byte[] firstMD5
= this.md5sum(salted
);
227 byte[] secondMD5
= this.md5sum(firstMD5
, key3
.getBytes());
228 return this.downmix(secondMD5
);
232 * Mix the 128 bits of the MD5 hash into a single 32-bit value.
234 protected String
downmix(byte[] input
)
236 byte[] res
= new byte[4];
237 res
[0] = (byte) (input
[0] ^ input
[1] ^ input
[2] ^ input
[3]);
238 res
[1] = (byte) (input
[4] ^ input
[5] ^ input
[6] ^ input
[7]);
239 res
[2] = (byte) (input
[8] ^ input
[9] ^ input
[10] ^ input
[11]);
240 res
[3] = (byte) (input
[12] ^ input
[13] ^ input
[14] ^ input
[15]);
242 int r
= (((int) res
[0] & 0xFFFFFFFF) << 24)
243 + (((int) res
[1] & 0xFFFFFFFF) << 16)
244 + (((int) res
[2] & 0xFFFFFFFF) << 8)
245 + ((int) res
[3] & 0xFFFFFFFF);
246 return String
.format("%X", r
);
249 protected byte[] md5sum(String input
)
251 return this.md5sum(input
.getBytes());
254 protected byte[] md5sum(byte[]... input
)
257 for (byte[] b
: input
)
259 this.digest
.update(b
);
261 return this.digest
.digest();