package de.debugco.jairport;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.net.InetAddress;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
public class Utils {
public static String byteAddrToString(byte[] addr) {
StringBuilder sb = new StringBuilder();
for (byte b : addr) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static byte[] getByteArrayFromStream(InputStream is) throws IOException {
byte[] b = new byte[10000];
int read;
ByteArrayOutputStream out = new ByteArrayOutputStream();
while((read = is.read(b, 0, b.length)) > 0) {
out.write(b, 0, read);
}
return out.toByteArray();
}
public static byte[] readFile(String filename) throws IOException {
FileInputStream fis = new FileInputStream(filename);
try {
return getByteArrayFromStream(fis);
} finally {
fis.close();
}
}
public static String getChallengeResponse(String challengeStr, InetAddress address, byte[] hwAddress) {
try {
byte[] challenge = decodeBase64(challengeStr);
ByteArrayOutputStream out = new ByteArrayOutputStream();
// Challenge
out.write(challenge);
// IP-Address
out.write(address.getAddress());
// HW-Addr
out.write(hwAddress);
// Pad to 32 Bytes
int padLen = 32 - out.size();
for(int i = 0; i < padLen; ++i) {
out.write(0x00);
}
String response = encodeBase64(encrypt(out.toByteArray()));
return response.replace("=", "").replace("\r", "").replace("\n", ""); // remove padding and other chars
} catch(Exception e) {
throw new RuntimeException(e);
}
}
private static Key getKey() {
try {
InputStream fis = ClassLoader.getSystemResourceAsStream("key.pk8");
if(fis == null) {
throw new RuntimeException("Cannot find keyfile");
}
try {
// openssl pkcs8 -inform pem -outform der -topk8 -nocrypt -in key.pem -out key.pk8
return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(getByteArrayFromStream(fis)));
} finally {
fis.close();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Cipher getRsaCipher(String padding) throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
return Cipher.getInstance("RSA/ECB/" + padding);
}
public static String encodeBase64(byte[] data) {
return new BASE64Encoder().encode(data);
}
public static byte[] decodeBase64(String base64Data) {
try {
return new BASE64Decoder().decodeBuffer(base64Pad(base64Data));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static byte[] decryptBase64(String base64encodedData) {
return decrypt(decodeBase64(base64encodedData));
}
public static byte[] decrypt(byte[] data) {
try {
Cipher c = getRsaCipher("OAEPWITHSHA1ANDMGF1PADDING");
c.init(Cipher.DECRYPT_MODE, getKey());
return c.doFinal(data);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] encrypt(byte[] data) {
try {
Cipher c = getRsaCipher("PKCS1PADDING");
c.init(Cipher.ENCRYPT_MODE, getKey());
return c.doFinal(data);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Pads a given String s to be usable for BASE64Decoder (if it isn't padded the resulting deoceded data may be wrong)
* @param s
* @return
*/
public static String base64Pad(String s) {
int toPad = s.length() % 4;
for(int i = 0; i < toPad; ++i) {
s = s + "=";
}
return s;
}
public static boolean isNullOrEmpty(String client) {
return client == null || "".equals(client.trim());
}
}