package org.openstack.atlas.util.crypto;
import org.openstack.atlas.util.crypto.exception.DecryptException;
import org.openstack.atlas.util.crypto.exception.EncryptException;
import org.apache.log4j.Logger;
import org.junit.Ignore;
import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@Ignore
public class CryptoUtilTest {
public static final Logger LOGGER = Logger.getLogger(CryptoUtilTest.class);
public static final String[] UNICODE_NAMES = {"!@#$%^&*()_+{}:\"<>?|./;'[]\\-=`~", // Randomness (ASCII)"
// +
"Andrew Young", // English (ASCII)
"Jos\u00E9 Antonio Calder\u00F3n-Iglesias", // Spanish
// (ISO-8859-1)
"Proven\u00E7al", // French (ISO-8859-1)
"AD\u00C9LA\u00CFDE", // French (ISO-8859-1)
"\u010Ca\u01D4", // Esperanto (ISO-8859-3). (Also uses
// character composition)
"J\u00FCrgen", // German (ISO-8859-1)
"Gu\u00F0r\u00FAn Eva M\u00EDnervud\u00F3ttir", // Icelandic
// (ISO-8859-1)
// Now for some more exotic ones.
"\u0399\u03B5\u03C1\u03B5\u03BC\u03AF\u03B1\u03C2", // Greek
// (ISO-8859-7)
"\u90ED\u674E\u5EFA\u592B", // Chinese (EUC-CN, Big5, GBK,
// GB18030, etc)
"\u753A\u7530\u307E\u3053\u3068", // Japanese (EUC-JP,
// ISO-2022-JP, Shift-JIS,
// etc)
"\uC774\uB984 \uC131\uBA85", // Korean (EUC-KR, ISO-2022-KR,
// etc)
"Nguy\u1EC5n Ph\u1EA1m", // Vietnamese (VISCII)
"\u0E2D\u0E07\u0E04\u0E4C\u0E40\u0E25\u0E47\u0E01", // Thai
// (ISO-8859-11)
// Ok, and now some RTL for the heck of it.
"\u0645\u0646\u0635\u0648\u0631 \u062D\u0644\u0627\u062C", // Farsi
// (Persian)
// (ISO-8859-6)
"\u05E6\u05D3\u05E7\u05D9\u05D4\u05D5", // Hebrew
// (ISO-8859-8)
};
public static final String[] ENCRYPTED_NAMES = {
"79a46b39151228e1dd6e582a34eeb551af7aae5425c91a524f2770b42dfb673f",
"b9d260dfc4aa08fb8316b5752825e38b",
"09d8f6e9587f12b219985238bc411179a152e40d98106c94e2c728218bb808c1",
"007910ecfbc55eb68b04118ae1d8f3a4", "641e3a310db820f0538dc6e8e23486e6",
"1a14749a9c5e586227853f386d82bfae", "537f574858604599c24eaef8edc7f37d",
"2af8ea34695c608bbb18ed4da0011a61351b3d2d59f5de290fba0122a278ce37",
"3434d3b63d75c564f01f7870aaf0905b", "b4d9d866faef5307ace1ddd3ad072059",
"021a1bd68bea49d88212c19c41bde4b5", "8d820f0f148f452b4ac82ea86bab5425",
"927ac46ea64e2c63bc4b159512e8d419",
"0427a000f28d44fb5226cb20a9a3a9e70c7d368c17fd780115367a03cdbdc29c",
"05e4c27e9fc2bef0b23afd6d2144059b0cfc770b3887c4b3a2c4ed84b3b91c3a",
"ca50c98286b4ce789d6ba2a9942f1bf3"};
@Test
public void AsBytes() throws DecryptException {
String testHex;
byte[] actual;
byte[] expected;
byte notUsed = -1;
testHex = "000000";
expected = new byte[]{0, 0, 0};
actual = CryptoUtil.asBytes(testHex, notUsed);
assertByteArrays("3 byte min value", expected, actual);
testHex = "ffffff";
expected = new byte[]{-1, -1, -1};
actual = CryptoUtil.asBytes(testHex, notUsed);
assertByteArrays("3 byte max value", expected, actual);
testHex = "101010";
expected = new byte[]{16, 16, 16};
actual = CryptoUtil.asBytes(testHex, notUsed);
assertByteArrays("3 byte 16s place", expected, actual);
testHex = "010101";
expected = new byte[]{1, 1, 1};
actual = CryptoUtil.asBytes(testHex, notUsed);
assertByteArrays("3 byte 1s place", expected, actual);
}
@Test(expected = DecryptException.class)
public void AsBytesShouldFailWhenGivenBadInput() throws DecryptException {
String testHex;
byte notUsed = -1;
testHex = "bbb";
CryptoUtil.asBytes(testHex, notUsed);
}
@Test
public void AsHex() {
byte[] testBytes;
String actual;
String expected;
testBytes = new byte[]{0, 0, 0};
expected = "000000";
actual = CryptoUtil.asHex(testBytes);
assertEquals("3 byte min value", expected, actual);
testBytes = new byte[]{-1, -1, -1};
expected = "ffffff";
actual = CryptoUtil.asHex(testBytes);
assertEquals("3 byte max value", expected, actual);
testBytes = new byte[]{16, 16, 16};
expected = "101010";
actual = CryptoUtil.asHex(testBytes);
assertEquals("3 byte 16s place", expected, actual);
testBytes = new byte[]{1, 1, 1};
expected = "010101";
actual = CryptoUtil.asHex(testBytes);
assertEquals("3 byte 1s place", expected, actual);
}
@Test
public void EncryptedFormat() throws Exception {
int failed = 0;
for (int i = 0; i < ENCRYPTED_NAMES.length; i++) {
String encrypted = ENCRYPTED_NAMES[i];
try {
String decrypted = CryptoUtil.decrypt(encrypted);
if (!UNICODE_NAMES[i].equals(decrypted)) {
LOGGER.error(String.format("String changed during decryption. Original: %s, New: %s",
UNICODE_NAMES[i], decrypted));
failed++;
}
} catch (DecryptException e) {
LOGGER.error(String.format("Decryption Failed For '%s': %s", encrypted, e.getMessage()), e);
failed++;
}
}
assertEquals(String.format("%d Failures", failed), 0, failed);
}
@Test
public void Unicode() throws Exception {
int failed = 0;
for (int i = 0; i < UNICODE_NAMES.length; i++) {
String name = UNICODE_NAMES[i];
try {
String encrypted = CryptoUtil.encrypt(name);
if (encrypted == null || !encrypted.equals(ENCRYPTED_NAMES[i])) {
LOGGER.error(String.format(
"Encrypted Format Has Changed. Input: %s, Original: %s, New: %s", name,
ENCRYPTED_NAMES[i], encrypted));
failed++;
}
String decrypted = CryptoUtil.decrypt(encrypted);
if (!name.equals(decrypted)) {
LOGGER.error(String.format(
"String changed during encryption/decryption. Original: %s, New: %s", name,
decrypted));
failed++;
}
} catch (EncryptException e) {
LOGGER.error(String.format("Encryption Failed For '%s': %s", name, e.getMessage()), e);
failed++;
} catch (DecryptException e) {
LOGGER.error(String.format("Decryption Failed For '%s': %s", name, e.getMessage()), e);
failed++;
}
}
assertEquals(String.format("%d Failures", failed), 0, failed);
}
private void assertByteArrays(String message, byte[] expected, byte[] actual) {
assertEquals("[" + message + "] arrays should be the same size", expected.length, actual.length);
assertTrue("[" + message + "] should be equal", Arrays.equals(expected, actual));
}
}