package uc.crypto; import helpers.GH; import java.security.GeneralSecurityException; import java.security.SecureRandom; import java.util.List; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import uc.protocols.DCProtocol; public class UDPEncryption { //private static final Logger logger = LoggerFactory.make(); public static final short KEYLENGTH = 16; private static final SecureRandom SRAND = new SecureRandom(); private static final Cipher CIPHER; private static final byte[] start; static { Cipher d = null; try { d = Cipher.getInstance("AES/CBC/PKCS5Padding"); } catch (GeneralSecurityException e) { e.printStackTrace(); } CIPHER = d; start = "URES ".getBytes(DCProtocol.ADC_CHARSET); } public static boolean isUDPEncryptionSupported() { return CIPHER != null; } // public static void main(String... args) throws IOException,Exception { // byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, // 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; // // byte[] message = "hello world".getBytes(); // byte[] cypher = encryptMessage(message,keyBytes); // System.out.println("Message size: "+message.length+ " cipherlength: "+cypher.length +" "+new String(cypher)); // byte[] decrypted = decryptMessage(cypher, keyBytes); // System.out.println(new String(decrypted)); // } public static byte[] encryptMessage(byte[] input,byte[] keyBytes) throws GeneralSecurityException { if (keyBytes.length != KEYLENGTH) { throw new IllegalArgumentException(); } SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); // System.out.println(new String(input)); byte[] ivBytes = new byte[KEYLENGTH] ; synchronized (SRAND) { SRAND.nextBytes(ivBytes); } IvParameterSpec iv = new IvParameterSpec(new byte[KEYLENGTH]); byte[] packetToEncrypt = GH.concatenate(ivBytes,input); // // encryption pass // byte[] encryptedIV; // synchronized (CIPHER_IV) { // CIPHER_IV.init(Cipher.ENCRYPT_MODE, key); // // byte[] encryptedIVwork = new byte[CIPHER_IV.getOutputSize(ivBytes.length)]; // // int ctLength = CIPHER_IV.update(ivBytes, 0, ivBytes.length, encryptedIVwork, 0); // ctLength += CIPHER_IV.doFinal(encryptedIVwork, ctLength); // encryptedIV = GH.subarray(encryptedIVwork, 0, ctLength); // } byte[] encryptedPacket; synchronized (CIPHER) { CIPHER.init(Cipher.ENCRYPT_MODE, key, iv); byte[] encryptedPacketWork = new byte[CIPHER.getOutputSize(packetToEncrypt.length)]; int ctLength = CIPHER.update(packetToEncrypt, 0, packetToEncrypt.length, encryptedPacketWork, 0); ctLength += CIPHER.doFinal(encryptedPacketWork, ctLength); encryptedPacket = GH.subarray(encryptedPacketWork, 0, ctLength); } return encryptedPacket; } public static byte[] decryptMessage(byte[] encrypted,byte[] keyBytes) throws GeneralSecurityException { if (keyBytes.length != KEYLENGTH || encrypted.length < KEYLENGTH*2) { throw new IllegalArgumentException(); } SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); IvParameterSpec iv = new IvParameterSpec(new byte[KEYLENGTH]); synchronized (CIPHER) { CIPHER.init(Cipher.DECRYPT_MODE, key,iv); byte[] plainPacket = new byte[CIPHER.getOutputSize(encrypted.length)]; int ptLength = CIPHER.update(encrypted, 0, encrypted.length, plainPacket, 0); ptLength += CIPHER.doFinal(plainPacket, ptLength); return GH.subarray(plainPacket, KEYLENGTH, ptLength-KEYLENGTH); } } /** * tries out all provided key on the message.. * if the message is encrypted this will return the decrypted message ... * null otherwise * * @param potentialEncrypted - the message that might or might not be encrypted * @param keys - the keys that could be tried * @return */ public static byte[] decryptMessage(byte[] potentialEncrypted,List<byte[]> keys) { for (byte[] key: keys) { try { byte[] decrypted = decryptMessage(potentialEncrypted, key); boolean matches = true; for (int i = 0; matches && i < start.length ; i++) { matches = decrypted[i] == start[i]; } if (matches) { return decrypted; } } catch(GeneralSecurityException gse) {} } return null; } public static byte[] getRandomKey() { byte[] encryptionKey = new byte[KEYLENGTH]; synchronized(SRAND) { SRAND.nextBytes(encryptionKey); } return encryptionKey; } }