From a623db316cc0fe3158e7b0a8d836d21933488a94 Mon Sep 17 00:00:00 2001 From: Sangbum Kim Date: Mon, 10 Oct 2016 14:55:51 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9D=BC=EB=8B=A8=20=EC=95=94=ED=98=B8?= =?UTF-8?q?=ED=99=94=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 37 +++- gradle/wrapper/gradle-wrapper.properties | 2 +- src/main/java/Base58.java | 197 ++++++++++++++++++++ src/main/java/ByteUtil.java | 101 ++++++++++ src/main/java/CryptoUtil.java | 141 ++++++++++++++ src/main/java/Main.java | 55 ++++++ src/main/java/SimpleEncryptor.java | 25 ++- src/main/java/SimpleObfuscator.java | 34 ++-- src/main/java/UUIDUtil.java | 227 +++++++++++++++++++++++ 9 files changed, 789 insertions(+), 30 deletions(-) create mode 100644 src/main/java/Base58.java create mode 100644 src/main/java/ByteUtil.java create mode 100644 src/main/java/CryptoUtil.java create mode 100644 src/main/java/Main.java create mode 100644 src/main/java/UUIDUtil.java diff --git a/build.gradle b/build.gradle index 14280b6..713ae23 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,21 @@ apply plugin: 'java' apply plugin: 'application' +buildscript { + repositories { + mavenLocal() + jcenter() + maven { url 'http://repo.spring.io/snapshot' } + maven { url 'http://repo.spring.io/milestone' } + maven { url 'http://repo.spring.io/plugins-release' } + } + dependencies { + classpath 'org.springframework.build.gradle:propdeps-plugin:0.0.7' + } +} +mainClassName = 'Main' +//mainClassName = 'SimpleObfuscator' +//mainClassName = 'Crypt' repositories { @@ -9,8 +24,24 @@ repositories { maven { url 'http://repo.spring.io/snapshot' } maven { url 'http://repo.spring.io/milestone' } maven { url 'http://repo.spring.io/plugins-release' } +} + + +apply plugin: 'propdeps' +apply plugin: 'propdeps-maven' +apply plugin: 'propdeps-idea' +apply plugin: 'propdeps-eclipse' +dependencies { + compile 'org.bouncycastle:bcprov-jdk15on:1.54' + provided 'org.projectlombok:lombok:1.16.10' + + // commons family + compile 'org.apache.commons:commons-lang3:3.4' + compile 'commons-codec:commons-codec:1.10' + compile 'commons-io:commons-io:2.5' + compile 'commons-fileupload:commons-fileupload:1.3.1' + compile 'com.google.guava:guava:19.0' + compile "com.fasterxml.uuid:java-uuid-generator:3.1.4" + } -dependencies{ - compile group: 'org.bouncycastle:bcprov-jdk15on:1.54' -} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 89950e7..1ab157d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Mon Aug 01 04:55:26 KST 2016 +#Mon Oct 10 00:54:38 KST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/Base58.java b/src/main/java/Base58.java new file mode 100644 index 0000000..479b5b8 --- /dev/null +++ b/src/main/java/Base58.java @@ -0,0 +1,197 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import com.google.common.hash.Hashing; +import org.apache.commons.lang3.ArrayUtils; + +import java.math.BigInteger; +import java.util.Arrays; + +/** + * Base58 is a way to encode Bitcoin addresses (or arbitrary data) as alphanumeric strings. + *

+ * Note that this is not the same base58 as used by Flickr, which you may find referenced around the Internet. + *

+ * adds support for testing the prefix and suffix bytes commonly found in addresses. + *

+ * Satoshi explains: why base-58 instead of standard base-64 encoding? + *

+ *

+ * However, note that the encoding/decoding runs in O(n²) time, so it is not useful for large data. + *

+ * The basic idea of the encoding is to treat the data bytes as a large number represented using + * base-256 digits, convert the number to be represented using base-58 digits, preserve the exact + * number of leading zeros (which are otherwise lost during the mathematical operations on the + * numbers), and finally represent the resulting base-58 digits as alphanumeric ASCII characters. + */ +public class Base58 { + private static final char[] ALPHABET = ("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz").toCharArray(); + private static final char ENCODED_ZERO = ALPHABET[0]; + private static final int[] INDEXES = new int[128]; + + static { + Arrays.fill(INDEXES, -1); + for (int i = 0; i < ALPHABET.length; i++) { + INDEXES[ALPHABET[i]] = i; + } + } + + public static String encodeChecked(byte[] input) { + byte[] data = Arrays.copyOfRange(input, 0, input.length); + byte[] checksum = ByteUtil.toBytes(Hashing.sha256().hashBytes(data).hashCode()); + return encode(ArrayUtils.addAll(data,checksum)); + } + /** + * Encodes the given bytes as a base58 string (no checksum is appended). + * + * @param input the bytes to encode + * @return the base58-encoded string + */ + public static String encode(byte[] input) { + if (input.length == 0) { + return ""; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input.length && input[zeros] == 0) { + ++zeros; + } + // Convert base-256 digits to base-58 digits (plus conversion to ASCII characters) + input = Arrays.copyOf(input, input.length); // since we modify it in-place + char[] encoded = new char[input.length * 2]; // upper bound + int outputStart = encoded.length; + for (int inputStart = zeros; inputStart < input.length; ) { + encoded[--outputStart] = ALPHABET[divmod(input, inputStart, 256, 58)]; + if (input[inputStart] == 0) { + ++inputStart; // optimization - skip leading zeros + } + } + // Preserve exactly as many leading encoded zeros in output as there were leading zeros in input. + while (outputStart < encoded.length && encoded[outputStart] == ENCODED_ZERO) { + ++outputStart; + } + while (--zeros >= 0) { + encoded[--outputStart] = ENCODED_ZERO; + } + // Return encoded string (including encoded leading zeros). + return new String(encoded, outputStart, encoded.length - outputStart); + } + + /** + * Decodes the given base58 string into the original data bytes. + * + * @param input the base58-encoded string to decode + * @return the decoded data bytes + * @throws IllegalArgumentException if the given string is not a valid base58 string + */ + public static byte[] decode(String input) throws IllegalArgumentException { + if (input.length() == 0) { + return new byte[0]; + } + // Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits). + byte[] input58 = new byte[input.length()]; + for (int i = 0; i < input.length(); ++i) { + char c = input.charAt(i); + int digit = c < 128 ? INDEXES[c] : -1; + if (digit < 0) { + System.out.printf("Illegal character %d at position %d\n",c,i); + return null; + } + input58[i] = (byte) digit; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input58.length && input58[zeros] == 0) { + ++zeros; + } + // Convert base-58 digits to base-256 digits. + byte[] decoded = new byte[input.length()]; + int outputStart = decoded.length; + for (int inputStart = zeros; inputStart < input58.length; ) { + decoded[--outputStart] = divmod(input58, inputStart, 58, 256); + if (input58[inputStart] == 0) { + ++inputStart; // optimization - skip leading zeros + } + } + // Ignore extra leading zeroes that were added during the calculation. + while (outputStart < decoded.length && decoded[outputStart] == 0) { + ++outputStart; + } + // Return decoded data (including original number of leading zeros). + return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length); + } + + public static BigInteger decodeToBigInteger(String input) throws IllegalArgumentException { + return new BigInteger(1, decode(input)); + } + + /** + * Decodes the given base58 string into the original data bytes, using the checksum in the + * last 4 bytes of the decoded data to verify that the rest are correct. The checksum is + * removed from the returned data. + * + * @param input the base58-encoded string to decode (which should include the checksum) + * @throws IllegalArgumentException if the input is not base 58 or the checksum does not validate. + */ + public static byte[] decodeChecked(String input) throws IllegalArgumentException { + byte[] decoded = decode(input); + if (decoded.length < 8) { + System.out.println("Input too short"); + return null; + } + byte[] data = Arrays.copyOfRange(decoded, 0, decoded.length - 4); + byte[] checksum = Arrays.copyOfRange(decoded, decoded.length -4, decoded.length); + byte[] actualChecksum = ByteUtil.toBytes(Hashing.sha256().hashBytes(data).hashCode()); + + if (!Arrays.equals(checksum, actualChecksum)) { + System.out.println("Checksum does not validate"); + return null; + } + return data; + } + + /** + * Divides a number, represented as an array of bytes each containing a single digit + * in the specified base, by the given divisor. The given number is modified in-place + * to contain the quotient, and the return value is the remainder. + * + * @param number the number to divide + * @param firstDigit the index within the array of the first non-zero digit + * (this is used for optimization by skipping the leading zeros) + * @param base the base in which the number's digits are represented (up to 256) + * @param divisor the number to divide by (up to 256) + * @return the remainder of the division operation + */ + private static byte divmod(byte[] number, int firstDigit, int base, int divisor) { + // this is just long division which accounts for the base of the input digits + int remainder = 0; + for (int i = firstDigit; i < number.length; i++) { + int digit = (int) number[i] & 0xFF; + int temp = remainder * base + digit; + number[i] = (byte) (temp / divisor); + remainder = temp % divisor; + } + return (byte) remainder; + } + +} \ No newline at end of file diff --git a/src/main/java/ByteUtil.java b/src/main/java/ByteUtil.java new file mode 100644 index 0000000..c6dffc0 --- /dev/null +++ b/src/main/java/ByteUtil.java @@ -0,0 +1,101 @@ + +public class ByteUtil { + public static int fromBytesAsInt(byte[] i) { + + return + (((int) i[3] & 0xFF) << 24) | + (((int) i[2] & 0xFF) << 16) | + (((int) i[1] & 0xFF) << 8) | + (((int) i[0] & 0xFF)); + } + + public static long fromBytesAsLong(byte[] i) { + + + return + (((long) i[0] & 0xFF) << 56) | + (((long) i[1] & 0xFF) << 48) | + (((long) i[2] & 0xFF) << 40) | + (((long) i[3] & 0xFF) << 32) | + (((long) i[4] & 0xFF) << 24) | + (((long) i[5] & 0xFF) << 16) | + (((long) i[6] & 0xFF) << 8) | + (((long) i[7] & 0xFF)); + } + + public static long fromBytesAsLongMost(byte[] i) { + + return + (((long) i[0] & 0xFF) << 56) | + (((long) i[1] & 0xFF) << 48) | + (((long) i[2] & 0xFF) << 40) | + (((long) i[3] & 0xFF) << 32) | + (((long) i[4] & 0xFF) << 24) | + (((long) i[5] & 0xFF) << 16) | + (((long) i[6] & 0xFF) << 8) | + (((long) i[7] & 0xFF)); + } + + public static long fromBytesAsLongLast(byte[] i) { + + return + (((long) i[8] & 0xFF) << 56) | + (((long) i[9] & 0xFF) << 48) | + (((long) i[10] & 0xFF) << 40) | + (((long) i[11] & 0xFF) << 32) | + (((long) i[12] & 0xFF) << 24) | + (((long) i[13] & 0xFF) << 16) | + (((long) i[14] & 0xFF) << 8) | + (((long) i[15] & 0xFF)); + } + + + public static byte[] toBytes(int i) { + byte[] result = new byte[4]; + + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + + return result; + } + + public static byte[] toBytes(long i) { + byte[] result = new byte[8]; + + result[0] = (byte) (i >> 56); + result[1] = (byte) (i >> 48); + result[2] = (byte) (i >> 40); + result[3] = (byte) (i >> 32); + result[4] = (byte) (i >> 24); + result[5] = (byte) (i >> 16); + result[6] = (byte) (i >> 8); + result[7] = (byte) (i /*>> 0*/); + + return result; + } + + public static byte[] toBytes(long most, long last) { + byte[] result = new byte[16]; + + result[0] = (byte) (most >> 56); + result[1] = (byte) (most >> 48); + result[2] = (byte) (most >> 40); + result[3] = (byte) (most >> 32); + result[4] = (byte) (most >> 24); + result[5] = (byte) (most >> 16); + result[6] = (byte) (most >> 8); + result[7] = (byte) (most /*>> 0*/); + result[8] = (byte) (last >> 56); + result[9] = (byte) (last >> 48); + result[10] = (byte) (last >> 40); + result[11] = (byte) (last >> 32); + result[12] = (byte) (last >> 24); + result[13] = (byte) (last >> 16); + result[14] = (byte) (last >> 8); + result[15] = (byte) (last /*>> 0*/); + + return result; + } +} diff --git a/src/main/java/CryptoUtil.java b/src/main/java/CryptoUtil.java new file mode 100644 index 0000000..2ca71fd --- /dev/null +++ b/src/main/java/CryptoUtil.java @@ -0,0 +1,141 @@ +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; +import org.bouncycastle.crypto.params.KeyParameter; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.Charset; +import java.util.StringTokenizer; + +public class CryptoUtil { + + private static final Charset characterSetUtf8 = Charset.forName("UTF-8"); + + private static final Charset characterSetAscii = Charset.forName("US-ASCII"); + + public static Cipher cipherFactory(String secretKey, String secretIv, String salt, int mode) { + try { + + + //PBKDF2WithHmacSHA256 + final PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); + gen.init(secretKey.getBytes(characterSetAscii), salt.getBytes(characterSetAscii), 2); + final byte[] dk = ((KeyParameter) gen.generateDerivedParameters(256)).getKey(); + SecretKey secret = new SecretKeySpec(dk, "AES"); + + + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(mode, secret, new IvParameterSpec(secretIv.getBytes(characterSetAscii))); + return cipher; + } catch (Exception e) { + System.out.printf("CryptoUtil.cipherFactory - fail to create cipher %s %s\n", e.getMessage(), mode); + return null; + } + } + + + + public static byte[] encode(Cipher cipher, byte[] payload) { + if (payload == null || cipher == null) { + return null; + } + try { + return cipher.doFinal(payload); + } catch (Exception e) { + System.out.printf("CryptoUtil.decode - fail to encode %s %s", payload, e.getMessage()); + } + return null; + } + + public static byte[] decode(Cipher cipher, byte[] encrypted) { + if (encrypted== null) { + return null; + } + try { + return cipher.doFinal(encrypted); + } catch (Exception e) { + System.out.printf("CryptoUtil.decode - fail to decode {} {}", encrypted, e.getMessage()); + } + return null; + } + + public static String encode64(Cipher cipher, String payload) { + if (payload == null || cipher == null) { + return null; + } + try { + byte[] encrypted = cipher.doFinal(payload.getBytes(characterSetUtf8)); + return String.valueOf(Base64.encode(encrypted)); + } catch (Exception e) { + System.out.printf("CryptoUtil.decode - fail to encode %s %s", payload, e.getMessage()); + } + return null; + } + + public static String decode64(Cipher cipher, String encryptedSessionInfo) { + if (encryptedSessionInfo == null) { + return null; + } + try { + byte[] byteStr = Base64.decode(encryptedSessionInfo); + return new String(cipher.doFinal(byteStr), characterSetUtf8); + + } catch (Exception e) { + System.out.printf("CryptoUtil.decode - fail to decode {} {}", encryptedSessionInfo, e.getMessage()); + } + return null; + } + + public static String encode58(Cipher cipher, String payload) { + if (payload == null || cipher == null) { + return null; + } + try { + byte[] encrypted = cipher.doFinal(payload.getBytes(characterSetUtf8)); + return Base58.encodeChecked(encrypted); + } catch (Exception e) { + System.out.printf("CryptoUtil.decode - fail to encode %s %s", payload, e.getMessage()); + } + return null; + } + + public static String decode58(Cipher cipher, String encryptedSessionInfo) { + if (encryptedSessionInfo == null) { + return null; + } + try { + byte[] byteStr = Base58.decodeChecked(encryptedSessionInfo); + if(byteStr==null){ + return null; + } + return new String(cipher.doFinal(byteStr), characterSetUtf8); + + } catch (Exception e) { + System.out.printf("CryptoUtil.decode - fail to decode {} {}", encryptedSessionInfo, e.getMessage()); + } + return null; + } + + /** + * timestamp + * + * @param encodedSessionInfo + * @return + */ + public static String getAccessTokenIfValid(Cipher cipher, String encodedSessionInfo) { + if (encodedSessionInfo == null || cipher == null) { + return null; + } + + String decodedSessionInfo = decode58(cipher, encodedSessionInfo); + StringTokenizer splitted = decodedSessionInfo == null ? null : new StringTokenizer(decodedSessionInfo, ":"); + + if (splitted == null || splitted.countTokens() != 2) { + return null; + } + return decodedSessionInfo; + } +} \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 0000000..9d056f4 --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,55 @@ +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; +import org.bouncycastle.crypto.params.KeyParameter; + +import javax.crypto.*; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.Charset; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.UUID; + +/** + * Created by spi-ca on 10/10/2016. + */ +public class Main { + + + private static final Charset characterSetUtf8 = Charset.forName("UTF-8"); + + private static final Charset characterSetAscii = Charset.forName("US-ASCII"); + + + public static void main(String[] args) { + UUID target = UUID.fromString("abd91313-e6d6-45be-9913-13e6d6d5bef2"); + + String secretKey = "WHc3zv6ZaWnnBz2XZwvhKWucwXWk3Tzz"; + String secretIv = "mRzpK5yUsLreMCTg"; + String salt = "vvgKbpRxzY8zC9LC"; + + //PBKDF2WithHmacSHA256 + final PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); + gen.init(secretKey.getBytes(characterSetAscii), salt.getBytes(characterSetAscii), 2); + final byte[] dk = ((KeyParameter) gen.generateDerivedParameters(256)).getKey(); + + SecretKey secret = new SecretKeySpec(dk, "AES"); + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(secretIv.getBytes(characterSetAscii))); + byte[] encrypted = cipher.doFinal(UUIDUtil.UUIDToBytes(target)); + + System.out.printf("uuid : %s base58 : %s enc: %s \n", + target.toString(), + Base58.encode(UUIDUtil.UUIDToBytes(target)), + Base58.encode(encrypted) + ); + + } catch (InvalidKeyException | InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException e) { + e.printStackTrace(); + } + +// Cipher encryptor = CryptoUtil.cipherFactory(secretKey, secretIv, salt, Cipher.ENCRYPT_MODE); + } +} diff --git a/src/main/java/SimpleEncryptor.java b/src/main/java/SimpleEncryptor.java index 69fa483..06240be 100644 --- a/src/main/java/SimpleEncryptor.java +++ b/src/main/java/SimpleEncryptor.java @@ -4,9 +4,7 @@ import org.bouncycastle.crypto.params.KeyParameter; import javax.crypto.Cipher; import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.Charset; import java.security.GeneralSecurityException; @@ -38,13 +36,6 @@ public class SimpleEncryptor { try { -// SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); -// KeySpec keySpec = new PBEKeySpec(new String(keyValue, characterSetAscii).toCharArray(), salt, 2, 256); -// SecretKey tmp = factory.generateSecret(keySpec); -// -// - - //PBKDF2WithHmacSHA256 final PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); gen.init(keyValue, salt, 2); @@ -60,7 +51,6 @@ public class SimpleEncryptor { } } - public byte[] encrypt(byte[] source) { if (source == null) { return null; @@ -81,7 +71,6 @@ public class SimpleEncryptor { return decryptor.doFinal(source); } catch (Exception e) { e.printStackTrace(); - return null; } } @@ -91,7 +80,11 @@ public class SimpleEncryptor { return null; } try { - return new String(Base64.encode(encryptor.doFinal(source.getBytes(characterSetAscii)))); + byte[] payload = encrypt(source.getBytes(characterSetAscii)); + if (payload == null) { + return null; + } + return new String(Base64.encode(payload)); } catch (Exception e) { e.printStackTrace(); return null; @@ -103,10 +96,16 @@ public class SimpleEncryptor { return null; } try { - return new String(decryptor.doFinal(Base64.decode(source)), characterSetUtf8); + + byte[] payload = decrypt(Base64.decode(source)); + if (payload == null) { + return null; + } + return new String(payload, characterSetUtf8); } catch (Exception e) { e.printStackTrace(); return null; } } + } diff --git a/src/main/java/SimpleObfuscator.java b/src/main/java/SimpleObfuscator.java index 20a9810..cf7393b 100644 --- a/src/main/java/SimpleObfuscator.java +++ b/src/main/java/SimpleObfuscator.java @@ -1,6 +1,9 @@ +import javax.crypto.Cipher; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.UUID; public class SimpleObfuscator { @@ -59,16 +62,18 @@ public class SimpleObfuscator { // "sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=", // "sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=" // }; + + //dbkeys byte[][] keys = { {-45, 38, 70, -101, -53, 80, 47, -11, -103, 19, 60, 72, 95, -86, 105, 121, -68, 58, 106, -100, -72, 56, -44, -43, 35, 100, -35, 40, 125, -93, 58, -120, 96, -56, 50, -18, -113, -50, 62, 27, -76, -36, -99, 36, 112, 62, -6, -39, 117, -56, -74, 68, 82, 35, -50, -109, -66, 11, 69, 124, 11, -36, -9, -1}, - {-11,-95,82,80,114,-61,-119,-35,-87,38,34,79,-110,5,57,-93,-40,-83,46,53,-56,-86,-14,-114,52,95,67,5,-30,-91,-40,43,-88,-5,-74,11,38,-84,-33,89,-60,64,35,1,23,66,102,54,16,-116,59,51,127,55,20,-103,109,-52,-51,106,77,83,114,-118}, - {-7,-12,-21,-123,-88,-7,115,-14,-81,102,-59,101,-108,-55,18,-101,-54,73,57,-1,116,17,-26,-2,61,-75,18,-47,55,64,-13,25,112,113,32,80,-23,119,84,24,9,25,-82,-115,61,35,117,-20,-2,-83,108,25,31,45,22,-29,-122,-33,44,11,-121,85,52,-4} + {-11, -95, 82, 80, 114, -61, -119, -35, -87, 38, 34, 79, -110, 5, 57, -93, -40, -83, 46, 53, -56, -86, -14, -114, 52, 95, 67, 5, -30, -91, -40, 43, -88, -5, -74, 11, 38, -84, -33, 89, -60, 64, 35, 1, 23, 66, 102, 54, 16, -116, 59, 51, 127, 55, 20, -103, 109, -52, -51, 106, 77, 83, 114, -118}, + {-7, -12, -21, -123, -88, -7, 115, -14, -81, 102, -59, 101, -108, -55, 18, -101, -54, 73, 57, -1, 116, 17, -26, -2, 61, -75, 18, -47, 55, 64, -13, 25, 112, 113, 32, 80, -23, 119, 84, 24, 9, 25, -82, -115, 61, 35, 117, -20, -2, -83, 108, 25, 31, 45, 22, -29, -122, -33, 44, 11, -121, 85, 52, -4} }; - for (int i = 0; i < keys.length; i++) { + for (int i = 0; i < 1; i++) { // String sourceStr = keys[i]; - byte[] selT = keys[i];//sourceStr.getBytes(characterSet); + byte[] selT = keys[i]; // String output = new String(selT, 0, selT.length, characterSet); // @@ -82,23 +87,26 @@ public class SimpleObfuscator { byte[] out = soe.obfuscate(selT); - log.append(" {"); - for (int j = 0; j < out.length; j++) { - log.append(String.valueOf(out[j]) + ","); - } - log.append(" }"); + System.out.println(Arrays.toString(out)); - log.append('\t'); +// log.append(" {"); +// for (int j = 0; j < out.length; j++) { +// log.append(String.valueOf(out[j]) + ","); +// } +// log.append(" }"); +// +// log.append('\t'); - byte[] reout = soe.unobfuscate(out); + byte[] reout = soe.unobfuscate(selT); - String outputRe = new String(reout, 0, reout.length, characterSet); +// String outputRe = new String(reout, 0, reout.length, characterSet); + System.out.println(Arrays.toString(reout)); // if (!sourceStr.equals(outputRe)) { // log.append(" NG\t"); // } - log.append('\n'); +// log.append('\n'); } System.out.println(log.toString()); diff --git a/src/main/java/UUIDUtil.java b/src/main/java/UUIDUtil.java new file mode 100644 index 0000000..552fe42 --- /dev/null +++ b/src/main/java/UUIDUtil.java @@ -0,0 +1,227 @@ +import com.fasterxml.uuid.Generators; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.LongBuffer; +import java.util.StringTokenizer; +import java.util.UUID; + +public class UUIDUtil { + private static final int[] uuidLength = {8, 4, 4, 4, 12}; + + + public static UUID generateUUIDByName(String name) { + return Generators.nameBasedGenerator().generate(name); + } + + + public static UUID generateUUIDRandomly() { + return Generators.randomBasedGenerator().generate(); + } + + public static UUID generateUUIDTimely() { + + UUID uuid = Generators.timeBasedGenerator().generate(); + final ByteBuffer sourceBuffer = ByteBuffer.allocateDirect(16); + + int time_low = (int) (uuid.getMostSignificantBits() >> 32); + short time_mid = (short) ((uuid.getMostSignificantBits() >> 16) & 0xffff); + short time_high_and_version = (short) ((uuid.getMostSignificantBits()) & 0xffff); + short variant_and_sequence = (short) ((uuid.getLeastSignificantBits() >> 48) & 0xffff); + short node_most = (short) ((uuid.getLeastSignificantBits() >> 32) & 0xffff); + int node_least = (int) uuid.getLeastSignificantBits(); + + sourceBuffer.clear(); + sourceBuffer.putShort(time_high_and_version); + sourceBuffer.putShort(time_mid); + sourceBuffer.putInt(time_low); + sourceBuffer.putShort(variant_and_sequence); + sourceBuffer.putShort(node_most); + sourceBuffer.putInt(node_least); + sourceBuffer.flip(); + +// return time_high_and_version + '-' + time_mid + '-' + time_low + '-' + variant_and_sequence + '-' + node; + + return new UUID(sourceBuffer.getLong(), sourceBuffer.getLong()); + + } + + public static String generateUUIDSerialTimely() { + final UUID uuid = generateUUIDTimely(); + return UUIDToString(uuid); + } + + + public static String UUIDToBase64(final UUID orgUUID) { + if (orgUUID == null) { + return null; + } + final long most = orgUUID.getMostSignificantBits(); + final long last = orgUUID.getLeastSignificantBits(); + return new String(Base64.encode(ByteUtil.toBytes(most, last))); + } + + + public static UUID base64ToUUID(final String uuidString) { + + if (uuidString == null) { + return null; + } + try { + byte[] decoded = Base64.decode(uuidString); + if (decoded == null) { + return null; + } + final ByteBuffer sourceBuffer = ByteBuffer.allocateDirect(16); + sourceBuffer.clear(); + sourceBuffer.put(decoded); + sourceBuffer.flip(); + return new UUID(sourceBuffer.getLong(), sourceBuffer.getLong()); + } catch (Exception iae) { + return null; + } + } + + + public static String generateUUIDBase58() { + final UUID uuid = generateUUIDTimely(); + return UUIDToBase58(uuid); + } + + public static String generateUUIDBase58Checked() { + final UUID uuid = generateUUIDTimely(); + return UUIDToBase58Checked(uuid); + } + + public static byte[] UUIDToBytes(final UUID orgUUID) { + if (orgUUID == null) { + return null; + } + final long most = orgUUID.getMostSignificantBits(); + final long last = orgUUID.getLeastSignificantBits(); + return ByteUtil.toBytes(most, last); + } + + + public static String UUIDToBase58(final UUID orgUUID) { + if (orgUUID == null) { + return null; + } + final long most = orgUUID.getMostSignificantBits(); + final long last = orgUUID.getLeastSignificantBits(); + return Base58.encode(ByteUtil.toBytes(most, last)); + } + + + public static String UUIDToBase58Checked(final UUID orgUUID) { + if (orgUUID == null) { + return null; + } + final long most = orgUUID.getMostSignificantBits(); + final long last = orgUUID.getLeastSignificantBits(); + return Base58.encodeChecked(ByteUtil.toBytes(most, last)); + } + + public static UUID base58ToUUID(final String uuidString) { + + if (uuidString == null) { + return null; + } + try { + + final ByteBuffer sourceBuffer = ByteBuffer.allocateDirect(16); + sourceBuffer.clear(); + sourceBuffer.put(Base58.decode(uuidString)); + sourceBuffer.flip(); + return new UUID(sourceBuffer.getLong(), sourceBuffer.getLong()); + } catch (IllegalArgumentException iae) { + return null; + } + } + + public static UUID base58ToUUIDChecked(final String uuidString) { + + if (uuidString == null) { + return null; + } + byte[] decoded = Base58.decodeChecked(uuidString); + if (decoded == null) { + return null; + } + final ByteBuffer sourceBuffer = ByteBuffer.allocateDirect(16); + sourceBuffer.clear(); + sourceBuffer.put(decoded); + sourceBuffer.flip(); + return new UUID(sourceBuffer.getLong(), sourceBuffer.getLong()); + } + + public static UUID bytesToUUID(byte[] uuidByte) { + if (uuidByte == null || uuidByte.length != 16) { + return null; + } + final long most = ByteUtil.fromBytesAsLongMost(uuidByte); + final long last = ByteUtil.fromBytesAsLongLast(uuidByte); + return new UUID(most, last); + } + + + public static String UUIDToString(final UUID orgUUID) { + + if (orgUUID == null) { + return null; + } + final CharBuffer sourceBuffer = ByteBuffer.allocateDirect(Character.BYTES * 32).asCharBuffer(); + sourceBuffer.clear(); + + final String orgStr = orgUUID.toString(); + final StringTokenizer orgStrings = new StringTokenizer(orgStr, "-"); + while (orgStrings.hasMoreElements()) { + sourceBuffer.put(orgStrings.nextToken()); + } + sourceBuffer.flip(); + return sourceBuffer.toString(); + } + + public static UUID stringToUUID(final String uuidString) { + if (uuidString == null) { + return null; + } + switch (uuidString.length()) { + case 36: + return UUID.fromString(uuidString); + case 32: + final CharBuffer sourceBuffer = ByteBuffer.allocateDirect(Character.BYTES * uuidString.length()).asCharBuffer(); + final LongBuffer targetBuffer = ByteBuffer.allocateDirect(Long.BYTES * uuidLength.length).asLongBuffer(); + sourceBuffer.clear(); + sourceBuffer.put(uuidString); + sourceBuffer.flip(); + targetBuffer.clear(); + + for (int size : uuidLength) { + final StringBuilder builder = new StringBuilder(); + final char[] buf = new char[size]; + builder.append("0x"); + sourceBuffer.get(buf, 0, size); + builder.append(buf); + targetBuffer.put(Long.decode(builder.toString())); + } + targetBuffer.flip(); + long mostSigBits = targetBuffer.get(); + mostSigBits <<= 16; + + mostSigBits |= targetBuffer.get(); + mostSigBits <<= 16; + + mostSigBits |= targetBuffer.get(); + + long leastSigBits = targetBuffer.get(); + leastSigBits <<= 48; + leastSigBits |= targetBuffer.get(); + + return new UUID(mostSigBits, leastSigBits); + default: + return null; + } + } +} +