Android Tutorial - Security
- DES
- RSA
- AES
- Authentication
The Data Encryption Standard. DES is a 64-bit block cipher with a 56-bit key,
import java.math.BigInteger; import java.security.InvalidKeyException; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.Map; class DES extends BaseCipher { // Constants and variables // ------------------------------------------------------------------------- /** DES operates on 64 bit blocks. */ public static final int BLOCK_SIZE = 8; /** DES uses 56 bits of a 64 bit parity-adjusted key. */ public static final int KEY_SIZE = 8; // S-Boxes 1 through 8. private static final int[] SP1 = new int[] { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 }; private static final int[] SP2 = new int[] { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 }; private static final int[] SP3 = new int[] { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 }; private static final int[] SP4 = new int[] { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 }; private static final int[] SP5 = new int[] { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 }; private static final int[] SP6 = new int[] { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 }; private static final int[] SP7 = new int[] { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 }; private static final int[] SP8 = new int[] { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 }; /** * Constants that help in determining whether or not a byte array is parity * adjusted. */ private static final byte[] PARITY = { 8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3, 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, 4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8 }; // Key schedule constants. private static final byte[] ROTARS = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 }; private static final byte[] PC1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; private static final byte[] PC2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; public static final byte[][] WEAK_KEYS = { Util.toBytesFromString("0101010101010101"), Util.toBytesFromString("01010101FEFEFEFE"), Util.toBytesFromString("FEFEFEFE01010101"), Util.toBytesFromString("FEFEFEFEFEFEFEFE") }; public static final byte[][] SEMIWEAK_KEYS = { Util.toBytesFromString("01FE01FE01FE01FE"), Util.toBytesFromString("FE01FE01FE01FE01"), Util.toBytesFromString("1FE01FE00EF10EF1"), Util.toBytesFromString("E01FE01FF10EF10E"), Util.toBytesFromString("01E001E001F101F1"), Util.toBytesFromString("E001E001F101F101"), Util.toBytesFromString("1FFE1FFE0EFE0EFE"), Util.toBytesFromString("FE1FFE1FFE0EFE0E"), Util.toBytesFromString("011F011F010E010E"), Util.toBytesFromString("1F011F010E010E01"), Util.toBytesFromString("E0FEE0FEF1FEF1FE"), Util.toBytesFromString("FEE0FEE0FEF1FEF1") }; /** Possible weak keys (parity adjusted) --produce 4 instead of 16 subkeys. */ public static final byte[][] POSSIBLE_WEAK_KEYS = { Util.toBytesFromString("1F1F01010E0E0101"), Util.toBytesFromString("011F1F01010E0E01"), Util.toBytesFromString("1F01011F0E01010E"), Util.toBytesFromString("01011F1F01010E0E"), Util.toBytesFromString("E0E00101F1F10101"), Util.toBytesFromString("FEFE0101FEFE0101"), Util.toBytesFromString("FEE01F01FEF10E01"), Util.toBytesFromString("E0FE1F01F1FE0E01"), Util.toBytesFromString("FEE0011FFEF1010E"), Util.toBytesFromString("E0FE011FF1FE010E"), Util.toBytesFromString("E0E01F1FF1F10E0E"), Util.toBytesFromString("FEFE1F1FFEFE0E0E"), Util.toBytesFromString("1F1F01010E0E0101"), Util.toBytesFromString("011F1F01010E0E01"), Util.toBytesFromString("1F01011F0E01010E"), Util.toBytesFromString("01011F1F01010E0E"), Util.toBytesFromString("01E0E00101F1F101"), Util.toBytesFromString("1FFEE0010EFEF001"), Util.toBytesFromString("1FE0FE010EF1FE01"), Util.toBytesFromString("01FEFE0101FEFE01"), Util.toBytesFromString("1FE0E01F0EF1F10E"), Util.toBytesFromString("01FEE01F01FEF10E"), Util.toBytesFromString("01E0FE1F01F1FE0E"), Util.toBytesFromString("1FFEFE1F0EFEFE0E"), Util.toBytesFromString("E00101E0F10101F1"), Util.toBytesFromString("FE1F01E0FE0E0EF1"), Util.toBytesFromString("FE011FE0FE010EF1"), Util.toBytesFromString("E01F1FE0F10E0EF1"), Util.toBytesFromString("FE0101FEFE0101FE"), Util.toBytesFromString("E01F01FEF10E01FE"), Util.toBytesFromString("E0011FFEF1010EFE"), Util.toBytesFromString("FE1F1FFEFE0E0EFE"), Util.toBytesFromString("1FFE01E00EFE01F1"), Util.toBytesFromString("01FE1FE001FE0EF1"), Util.toBytesFromString("1FE001FE0EF101FE"), Util.toBytesFromString("01E01FFE01F10EFE"), Util.toBytesFromString("0101E0E00101F1F1"), Util.toBytesFromString("1F1FE0E00E0EF1F1"), Util.toBytesFromString("1F01FEE00E01FEF1"), Util.toBytesFromString("011FFEE0010EFEF1"), Util.toBytesFromString("1F01E0FE0E01F1FE"), Util.toBytesFromString("011FE0FE010EF1FE"), Util.toBytesFromString("0101FEFE0001FEFE"), Util.toBytesFromString("1F1FFEFE0E0EFEFE"), Util.toBytesFromString("FEFEE0E0FEFEF1F1"), Util.toBytesFromString("E0FEFEE0F1FEFEF1"), Util.toBytesFromString("FEE0E0FEFEF1F1FE"), Util.toBytesFromString("E0E0FEFEF1F1FEFE") }; // Constructor(s) // ------------------------------------------------------------------------- /** Default 0-argument constructor. */ public DES() { super("des", BLOCK_SIZE, KEY_SIZE); } // Class methods // ------------------------------------------------------------------------- public static void adjustParity(byte[] kb, int offset) { for (int i = offset; i < KEY_SIZE; i++) { kb[i] ^= (PARITY[kb[i] & 0xff] == 8) ? 1 : 0; } } rity adjusted. <code>false</code> otherwise. */ public static boolean isParityAdjusted(byte[] kb, int offset) { int w = 0x88888888; int n = PARITY[kb[offset+0] & 0xff]; n <<= 4; n |= PARITY[kb[offset+1] & 0xff]; n <<= 4; n |= PARITY[kb[offset+2] & 0xff]; n <<= 4; n |= PARITY[kb[offset+3] & 0xff]; n <<= 4; n |= PARITY[kb[offset+4] & 0xff]; n <<= 4; n |= PARITY[kb[offset+5] & 0xff]; n <<= 4; n |= PARITY[kb[offset+6] & 0xff]; n <<= 4; n |= PARITY[kb[offset+7] & 0xff]; return (n & w) == 0; } public static boolean isWeak(byte[] kb) { // return Arrays.equals(kb, WEAK_KEYS[0]) || Arrays.equals(kb, WEAK_KEYS[1]) // || Arrays.equals(kb, WEAK_KEYS[2]) || Arrays.equals(kb, WEAK_KEYS[3]) // || Arrays.equals(kb, WEAK_KEYS[4]) || Arrays.equals(kb, WEAK_KEYS[5]) // || Arrays.equals(kb, WEAK_KEYS[6]) || Arrays.equals(kb, WEAK_KEYS[7]); for (int i = 0; i < WEAK_KEYS.length; i++) { if (Arrays.equals(WEAK_KEYS[i], kb)) { return true; } } return false; } public static boolean isSemiWeak(byte[] kb) { // return Arrays.equals(kb, SEMIWEAK_KEYS[0]) // || Arrays.equals(kb, SEMIWEAK_KEYS[1]) // || Arrays.equals(kb, SEMIWEAK_KEYS[2]) // || Arrays.equals(kb, SEMIWEAK_KEYS[3]) // || Arrays.equals(kb, SEMIWEAK_KEYS[4]) // || Arrays.equals(kb, SEMIWEAK_KEYS[5]) // || Arrays.equals(kb, SEMIWEAK_KEYS[6]) // || Arrays.equals(kb, SEMIWEAK_KEYS[7]) // || Arrays.equals(kb, SEMIWEAK_KEYS[8]) // || Arrays.equals(kb, SEMIWEAK_KEYS[9]) // || Arrays.equals(kb, SEMIWEAK_KEYS[10]) // || Arrays.equals(kb, SEMIWEAK_KEYS[11]); for (int i = 0; i < SEMIWEAK_KEYS.length; i++) { if (Arrays.equals(SEMIWEAK_KEYS[i], kb)) { return true; } } return false; } public static boolean isPossibleWeak(byte[] kb) { for (int i = 0; i < POSSIBLE_WEAK_KEYS.length; i++) { if (Arrays.equals(POSSIBLE_WEAK_KEYS[i], kb)) { return true; } } return false; } private static void desFunc(byte[] in, int i, byte[] out, int o, int[] key) { int right, left, work; // Load. left = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 | (in[i++] & 0xff) << 8 | in[i++] & 0xff; right = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 | (in[i++] & 0xff) << 8 | in[i ] & 0xff; // Initial permutation. work = ((left >>> 4) ^ right) & 0x0F0F0F0F; left ^= work << 4; right ^= work; work = ((left >>> 16) ^ right) & 0x0000FFFF; left ^= work << 16; right ^= work; work = ((right >>> 2) ^ left) & 0x33333333; right ^= work << 2; left ^= work; work = ((right >>> 8) ^ left) & 0x00FF00FF; right ^= work << 8; left ^= work; right = ((right << 1) | ((right >>> 31) & 1)) & 0xFFFFFFFF; work = (left ^ right) & 0xAAAAAAAA; left ^= work; right ^= work; left = ((left << 1) | ((left >>> 31) & 1)) & 0xFFFFFFFF; int k = 0, t; for (int round = 0; round < 8; round++) { work = right >>> 4 | right << 28; work ^= key[k++]; t = SP7[work & 0x3F]; work >>>= 8; t |= SP5[work & 0x3F]; work >>>= 8; t |= SP3[work & 0x3F]; work >>>= 8; t |= SP1[work & 0x3F]; work = right ^ key[k++]; t |= SP8[work & 0x3F]; work >>>= 8; t |= SP6[work & 0x3F]; work >>>= 8; t |= SP4[work & 0x3F]; work >>>= 8; t |= SP2[work & 0x3F]; left ^= t; work = left >>> 4 | left << 28; work ^= key[k++]; t = SP7[work & 0x3F]; work >>>= 8; t |= SP5[work & 0x3F]; work >>>= 8; t |= SP3[work & 0x3F]; work >>>= 8; t |= SP1[work & 0x3F]; work = left ^ key[k++]; t |= SP8[work & 0x3F]; work >>>= 8; t |= SP6[work & 0x3F]; work >>>= 8; t |= SP4[work & 0x3F]; work >>>= 8; t |= SP2[work & 0x3F]; right ^= t; } // The final permutation. right = (right << 31) | (right >>> 1); work = (left ^ right) & 0xAAAAAAAA; left ^= work; right ^= work; left = (left << 31) | (left >>> 1); work = ((left >>> 8) ^ right) & 0x00FF00FF; left ^= work << 8; right ^= work; work = ((left >>> 2) ^ right) & 0x33333333; left ^= work << 2; right ^= work; work = ((right >>> 16) ^ left) & 0x0000FFFF; right ^= work << 16; left ^= work; work = ((right >>> 4) ^ left) & 0x0F0F0F0F; right ^= work << 4; left ^= work; out[o++] = (byte)(right >>> 24); out[o++] = (byte)(right >>> 16); out[o++] = (byte)(right >>> 8); out[o++] = (byte) right; out[o++] = (byte)(left >>> 24); out[o++] = (byte)(left >>> 16); out[o++] = (byte)(left >>> 8); out[o ] = (byte) left; } // Instance methods implementing BaseCipher // ------------------------------------------------------------------------- public Object clone() { return new DES(); } public Iterator blockSizes() { return Collections.singleton(new Integer(BLOCK_SIZE)).iterator(); } public Iterator keySizes() { return Collections.singleton(new Integer(KEY_SIZE)).iterator(); } public Object makeKey(byte[] kb, int bs) throws InvalidKeyException { if (kb == null || kb.length != KEY_SIZE) throw new InvalidKeyException("DES keys must be 8 bytes long"); // if (Properties.checkForWeakKeys() // && (isWeak(kb) || isSemiWeak(kb) || isPossibleWeak(kb))) { // throw new WeakKeyException(); // } int i, j, l, m, n; long pc1m = 0, pcr = 0; for (i = 0; i < 56; i++) { l = PC1[i]; pc1m |= ((kb[l >>> 3] & (0x80 >>> (l & 7))) != 0) ? (1L << (55 - i)) : 0; } Context ctx = new Context(); // Encryption key first. for (i = 0; i < 16; i++) { pcr = 0; m = i << 1; n = m + 1; for (j = 0; j < 28; j++) { l = j + ROTARS[i]; if (l < 28) pcr |= ((pc1m & 1L << (55 - l)) != 0) ? (1L << (55 - j)) : 0; else pcr |= ((pc1m & 1L << (55 - (l - 28))) != 0) ? (1L << (55 - j)) : 0; } for (j = 28; j < 56; j++) { l = j + ROTARS[i]; if (l < 56) pcr |= ((pc1m & 1L << (55 - l)) != 0) ? (1L << (55 - j)) : 0; else pcr |= ((pc1m & 1L << (55 - (l - 28))) != 0) ? (1L << (55 - j)) : 0; } for (j = 0; j < 24; j++) { if ((pcr & 1L << (55 - PC2[j ])) != 0) ctx.ek[m] |= 1 << (23 - j); if ((pcr & 1L << (55 - PC2[j+24])) != 0) ctx.ek[n] |= 1 << (23 - j); } } // The decryption key is the same, but in reversed order. for (i = 0; i < Context.EXPANDED_KEY_SIZE; i += 2) { ctx.dk[30 - i] = ctx.ek[i]; ctx.dk[31 - i] = ctx.ek[i+1]; } // "Cook" the keys. for (i = 0; i < 32; i += 2) { int x, y; x = ctx.ek[i ]; y = ctx.ek[i+1]; ctx.ek[i ] = ((x & 0x00FC0000) << 6) | ((x & 0x00000FC0) << 10) | ((y & 0x00FC0000) >>> 10) | ((y & 0x00000FC0) >>> 6); ctx.ek[i+1] = ((x & 0x0003F000) << 12) | ((x & 0x0000003F) << 16) | ((y & 0x0003F000) >>> 4) | (y & 0x0000003F); x = ctx.dk[i ]; y = ctx.dk[i+1]; ctx.dk[i ] = ((x & 0x00FC0000) << 6) | ((x & 0x00000FC0) << 10) | ((y & 0x00FC0000) >>> 10) | ((y & 0x00000FC0) >>> 6); ctx.dk[i+1] = ((x & 0x0003F000) << 12) | ((x & 0x0000003F) << 16) | ((y & 0x0003F000) >>> 4) | (y & 0x0000003F); } return ctx; } public void encrypt(byte[] in, int i, byte[] out, int o, Object K, int bs) { desFunc(in, i, out, o, ((Context) K).ek); } public void decrypt(byte[] in, int i, byte[] out, int o, Object K, int bs) { desFunc(in, i, out, o, ((Context) K).dk); } final class Context { // Constants and variables // ---------------------------------------------------------------------- private static final int EXPANDED_KEY_SIZE = 32; /** The encryption key. */ int[] ek; /** The decryption key. */ int[] dk; // Constructor(s) // ---------------------------------------------------------------------- /** Default 0-arguments constructor. */ Context() { ek = new int[EXPANDED_KEY_SIZE]; dk = new int[EXPANDED_KEY_SIZE]; } // Class methods // ---------------------------------------------------------------------- // Instance methods // ---------------------------------------------------------------------- byte[] getEncryptionKeyBytes() { return toByteArray(ek); } byte[] getDecryptionKeyBytes() { return toByteArray(dk); } byte[] toByteArray(int[] k) { byte[] result = new byte[4 * k.length]; for (int i = 0, j = 0; i < k.length; i++) { result[j++] = (byte)(k[i] >>> 24); result[j++] = (byte)(k[i] >>> 16); result[j++] = (byte)(k[i] >>> 8); result[j++] = (byte) k[i]; } return result; } } } class Util { // Constants and variables // ------------------------------------------------------------------------- // Hex charset private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); // Base-64 charset private static final String BASE64_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; private static final char[] BASE64_CHARSET = BASE64_CHARS.toCharArray(); private Util() { super(); } ----------------------------------------------------------------------- public static String toString(byte[] ba) { return toString(ba, 0, ba.length); } public static final String toString(byte[] ba, int offset, int length) { char[] buf = new char[length * 2]; for (int i = 0, j = 0, k; i < length; ) { k = ba[offset + i++]; buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; buf[j++] = HEX_DIGITS[ k & 0x0F]; } return new String(buf); } public static String toReversedString(byte[] ba) { return toReversedString(ba, 0, ba.length); } public static final String toReversedString(byte[] ba, int offset, int length) { char[] buf = new char[length * 2]; for (int i = offset+length-1, j = 0, k; i >= offset; ) { k = ba[offset + i--]; buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; buf[j++] = HEX_DIGITS[ k & 0x0F]; } return new String(buf); } public static byte[] toBytesFromString(String s) { int limit = s.length(); byte[] result = new byte[((limit + 1) / 2)]; int i = 0, j = 0; if ((limit % 2) == 1) { result[j++] = (byte) fromDigit(s.charAt(i++)); } while (i < limit) { result[j ] = (byte) (fromDigit(s.charAt(i++)) << 4); result[j++] |= (byte) fromDigit(s.charAt(i++)); } return result; } public static byte[] toReversedBytesFromString(String s) { int limit = s.length(); byte[] result = new byte[((limit + 1) / 2)]; int i = 0; if ((limit % 2) == 1) { result[i++] = (byte) fromDigit(s.charAt(--limit)); } while (limit > 0) { result[i ] = (byte) fromDigit(s.charAt(--limit)); result[i++] |= (byte) (fromDigit(s.charAt(--limit)) << 4); } return result; } public static int fromDigit(char c) { if (c >= '0' && c <= '9') { return c - '0'; } else if (c >= 'A' && c <= 'F') { return c - 'A' + 10; } else if (c >= 'a' && c <= 'f') { return c - 'a' + 10; } else throw new IllegalArgumentException("Invalid hexadecimal digit: " + c); } public static String toString(int n) { char[] buf = new char[8]; for (int i = 7; i >= 0; i--) { buf[i] = HEX_DIGITS[n & 0x0F]; n >>>= 4; } return new String(buf); } public static String toString(int[] ia) { int length = ia.length; char[] buf = new char[length * 8]; for (int i = 0, j = 0, k; i < length; i++) { k = ia[i]; buf[j++] = HEX_DIGITS[(k >>> 28) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 24) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 20) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 16) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 12) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 8) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; buf[j++] = HEX_DIGITS[ k & 0x0F]; } return new String(buf); } public static String toString(long n) { char[] b = new char[16]; for (int i = 15; i >= 0; i--) { b[i] = HEX_DIGITS[(int)(n & 0x0FL)]; n >>>= 4; } return new String(b); } public static String toUnicodeString(byte[] ba) { return toUnicodeString(ba, 0, ba.length); } public static final String toUnicodeString(byte[] ba, int offset, int length) { StringBuffer sb = new StringBuffer(); int i = 0; int j = 0; int k; sb.append('\n').append("\""); while (i < length) { sb.append("\\u"); k = ba[offset + i++]; sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]); sb.append(HEX_DIGITS[ k & 0x0F]); k = ba[offset + i++]; sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]); sb.append(HEX_DIGITS[ k & 0x0F]); if ((++j % 8) == 0) { sb.append("\"+").append('\n').append("\""); } } sb.append("\"").append('\n'); return sb.toString(); } public static String toUnicodeString(int[] ia) { StringBuffer sb = new StringBuffer(); int i = 0; int j = 0; int k; sb.append('\n').append("\""); while (i < ia.length) { k = ia[i++]; sb.append("\\u"); sb.append(HEX_DIGITS[(k >>> 28) & 0x0F]); sb.append(HEX_DIGITS[(k >>> 24) & 0x0F]); sb.append(HEX_DIGITS[(k >>> 20) & 0x0F]); sb.append(HEX_DIGITS[(k >>> 16) & 0x0F]); sb.append("\\u"); sb.append(HEX_DIGITS[(k >>> 12) & 0x0F]); sb.append(HEX_DIGITS[(k >>> 8) & 0x0F]); sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]); sb.append(HEX_DIGITS[ k & 0x0F]); if ((++j % 4) == 0) { sb.append("\"+").append('\n').append("\""); } } sb.append("\"").append('\n'); return sb.toString(); } public static byte[] toBytesFromUnicode(String s) { int limit = s.length() * 2; byte[] result = new byte[limit]; char c; for (int i = 0; i < limit; i++) { c = s.charAt(i >>> 1); result[i] = (byte)(((i & 1) == 0) ? c >>> 8 : c); } return result; } public static String dumpString(byte[] data, int offset, int length, String m) { if (data == null) { return m + "null\n"; } StringBuffer sb = new StringBuffer(length * 3); if (length > 32) { sb.append(m).append("Hexadecimal dump of ").append(length).append(" bytes...\n"); } // each line will list 32 bytes in 4 groups of 8 each int end = offset + length; String s; int l = Integer.toString(length).length(); if (l < 4) { l = 4; } for ( ; offset < end; offset += 32) { if (length > 32) { s = " " + offset; sb.append(m).append(s.substring(s.length()-l)).append(": "); } int i = 0; for ( ; i < 32 && offset + i + 7 < end; i += 8) { sb.append(toString(data, offset + i, 8)).append(' '); } if (i < 32) { for ( ; i < 32 && offset + i < end; i++) { sb.append(byteToString(data[offset + i])); } } sb.append('\n'); } return sb.toString(); } public static String dumpString(byte[] data) { return (data == null) ? "null\n" : dumpString(data, 0, data.length, ""); } public static String dumpString(byte[] data, String m) { return (data == null) ? "null\n" : dumpString(data, 0, data.length, m); } public static String dumpString(byte[] data, int offset, int length) { return dumpString(data, offset, length, ""); } public static String byteToString(int n) { char[] buf = { HEX_DIGITS[(n >>> 4) & 0x0F], HEX_DIGITS[n & 0x0F] }; return new String(buf); } public static final String toBase64(byte[] buffer) { int len = buffer.length, pos = len % 3; byte b0 = 0, b1 = 0, b2 = 0; switch (pos) { case 1: b2 = buffer[0]; break; case 2: b1 = buffer[0]; b2 = buffer[1]; break; } StringBuffer sb = new StringBuffer(); int c; boolean notleading = false; do { c = (b0 & 0xFC) >>> 2; if (notleading || c != 0) { sb.append(BASE64_CHARSET[c]); notleading = true; } c = ((b0 & 0x03) << 4) | ((b1 & 0xF0) >>> 4); if (notleading || c != 0) { sb.append(BASE64_CHARSET[c]); notleading = true; } c = ((b1 & 0x0F) << 2) | ((b2 & 0xC0) >>> 6); if (notleading || c != 0) { sb.append(BASE64_CHARSET[c]); notleading = true; } c = b2 & 0x3F; if (notleading || c != 0) { sb.append(BASE64_CHARSET[c]); notleading = true; } if (pos >= len) { break; } else { try { b0 = buffer[pos++]; b1 = buffer[pos++]; b2 = buffer[pos++]; } catch (ArrayIndexOutOfBoundsException x) { break; } } } while (true); if (notleading) { return sb.toString(); } return "0"; } public static final byte[] fromBase64(String str) { int len = str.length(); if (len == 0) { throw new NumberFormatException("Empty string"); } byte[] a = new byte[len + 1]; int i, j; for (i = 0; i < len; i++) { try { a[i] = (byte) BASE64_CHARS.indexOf(str.charAt(i)); } catch (ArrayIndexOutOfBoundsException x) { throw new NumberFormatException("Illegal character at #"+i); } } i = len - 1; j = len; try { while (true) { a[j] = a[i]; if (--i < 0) { break; } a[j] |= (a[i] & 0x03) << 6; j--; a[j] = (byte)((a[i] & 0x3C) >>> 2); if (--i < 0) { break; } a[j] |= (a[i] & 0x0F) << 4; j--; a[j] = (byte)((a[i] & 0x30) >>> 4); if (--i < 0) { break; } a[j] |= (a[i] << 2); j--; a[j] = 0; if (--i < 0) { break; } } } catch (Exception ignored) { } try { // ignore leading 0-bytes while(a[j] == 0) { j++; } } catch (Exception x) { return new byte[1]; // one 0-byte } byte[] result = new byte[len - j + 1]; System.arraycopy(a, j, result, 0, len - j + 1); return result; } public static final byte[] trim(BigInteger n) { byte[] in = n.toByteArray(); if (in.length == 0 || in[0] != 0) { return in; } int len = in.length; int i = 1; while (in[i] == 0 && i < len) { ++i; } byte[] result = new byte[len - i]; System.arraycopy(in, i, result, 0, len - i); return result; } public static final String dump(BigInteger x) { return dumpString(trim(x)); } } abstract class BaseCipher implements IBlockCipher, IBlockCipherSpi { // Constants and variables // ------------------------------------------------------------------------- /** The canonical name prefix of the cipher. */ protected String name; /** The default block size, in bytes. */ protected int defaultBlockSize; /** The default key size, in bytes. */ protected int defaultKeySize; /** The current block size, in bytes. */ protected int currentBlockSize; /** The session key for this instance. */ protected transient Object currentKey; /** The instance lock. */ protected Object lock = new Object(); protected BaseCipher(String name, int defaultBlockSize, int defaultKeySize) { super(); this.name = name; this.defaultBlockSize = defaultBlockSize; this.defaultKeySize = defaultKeySize; } public abstract Object clone(); public String name() { StringBuffer sb = new StringBuffer(name).append('-'); if (currentKey == null) { sb.append(String.valueOf(8*defaultBlockSize)); } else { sb.append(String.valueOf(8*currentBlockSize)); } return sb.toString(); } public int defaultBlockSize() { return defaultBlockSize; } public int defaultKeySize() { return defaultKeySize; } public void init(Map attributes) throws InvalidKeyException { synchronized(lock) { if (currentKey != null) { throw new IllegalStateException(); } Integer bs = (Integer) attributes.get(CIPHER_BLOCK_SIZE); if (bs == null) { // no block size was specified. if (currentBlockSize == 0) { // happy birthday currentBlockSize = defaultBlockSize; } // else it's a clone. use as is } else { currentBlockSize = bs.intValue(); // ensure that value is valid Iterator it; boolean ok = false; for (it = blockSizes(); it.hasNext(); ) { ok = (currentBlockSize == ((Integer) it.next()).intValue()); if (ok) { break; } } if (!ok) { throw new IllegalArgumentException(IBlockCipher.CIPHER_BLOCK_SIZE); } } byte[] k = (byte[]) attributes.get(KEY_MATERIAL); currentKey = makeKey(k, currentBlockSize); } } public int currentBlockSize() { if (currentKey == null) { throw new IllegalStateException(); } return currentBlockSize; } public void reset() { synchronized(lock) { // currentBlockSize = 0; currentKey = null; } } public void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) throws IllegalStateException { synchronized(lock) { if (currentKey == null) { throw new IllegalStateException(); } encrypt(in, inOffset, out, outOffset, currentKey, currentBlockSize); } } public void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) throws IllegalStateException { synchronized(lock) { if (currentKey == null) { throw new IllegalStateException(); } decrypt(in, inOffset, out, outOffset, currentKey, currentBlockSize); } } public boolean selfTest() { int ks; Iterator bit; // do symmetry tests for all block-size/key-size combos for (Iterator kit = keySizes(); kit.hasNext(); ) { ks = ((Integer) kit.next()).intValue(); for (bit = blockSizes(); bit.hasNext(); ) { if (!testSymmetry(ks, ((Integer) bit.next()).intValue())) { return false; } } } return true; } // own methods ------------------------------------------------------------- private boolean testSymmetry(int ks, int bs) { try { byte[] kb = new byte[ks]; byte[] pt = new byte[bs]; byte[] ct = new byte[bs]; byte[] cpt = new byte[bs]; int i; for (i = 0; i < ks; i++) { kb[i] = (byte) i; } for (i = 0; i < bs; i++) { pt[i] = (byte) i; } Object k = makeKey(kb, bs); encrypt(pt, 0, ct, 0, k, bs); decrypt(ct, 0, cpt, 0, k, bs); return Arrays.equals(pt, cpt); } catch (Exception x) { x.printStackTrace(System.err); return false; } } protected boolean testKat(byte[] kb, byte[] ct) { return testKat(kb, ct, new byte[ct.length]); // all-zero plaintext } protected boolean testKat(byte[] kb, byte[] ct, byte[] pt) { try { int bs = pt.length; byte[] t = new byte[bs]; Object k = makeKey(kb, bs); // test encryption encrypt(pt, 0, t, 0, k, bs); if (!Arrays.equals(t, ct)) { return false; } // test decryption decrypt(t, 0, t, 0, k, bs); return Arrays.equals(t, pt); } catch (Exception x) { x.printStackTrace(System.err); return false; } } } interface IBlockCipherSpi extends Cloneable { Iterator blockSizes(); Iterator keySizes(); Object makeKey(byte[]k, int bs) throws InvalidKeyException; void encrypt(byte[] in, int inOffset, byte[] out, int outOffset, Object k, int bs); void decrypt(byte[] in, int inOffset, byte[] out, int outOffset, Object k, int bs); interface IBlockCipher extends Cloneable { String CIPHER_BLOCK_SIZE = "gnu.crypto.cipher.block.size"; String KEY_MATERIAL = "gnu.crypto.cipher.key.material"; String name(); int defaultBlockSize(); int defaultKeySize(); Iterator blockSizes(); Iterator keySizes(); Object clone(); void init(Map attributes) throws InvalidKeyException, IllegalStateException; int currentBlockSize() throws IllegalStateException; void reset(); void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) throws IllegalStateException; void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) throws IllegalStateException; boolean selfTest(); }
RSA encrypt/decrypt function (RSA / ECB / PKCS1-Padding)
//package org.andlib.helpers; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import javax.crypto.Cipher; import javax.crypto.Mac; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * * @author meinside@gmail.com * @since 09.11.24. * * last update 10.04.13. * */ final class StringCodec { /** * * @param original * @return null if fails */ public static String urlencode(String original) { try { //return URLEncoder.encode(original, "utf-8"); //fixed: to comply with RFC-3986 return URLEncoder.encode(original, "utf-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } catch(UnsupportedEncodingException e) { // Logger.e(e.toString()); } return null; } /** * * @param encoded * @return null if fails */ public static String urldecode(String encoded) { try { return URLDecoder.decode(encoded, "utf-8"); } catch(UnsupportedEncodingException e) { // Logger.e(e.toString()); } return null; } /** * * @param original * @param key * @return null if fails */ public static String hmacSha1Digest(String original, String key) { return hmacSha1Digest(original.getBytes(), key.getBytes()); } /** * * @param original * @param key * @return null if fails */ public static String hmacSha1Digest(byte[] original, byte[] key) { try { Mac mac = Mac.getInstance("HmacSHA1"); mac.init(new SecretKeySpec(key, "HmacSHA1")); byte[] rawHmac = mac.doFinal(original); return new String(Base64Coder.encode(rawHmac)); } catch (Exception e) { // Logger.e(e.toString()); } return null; } /** * * @param original * @return null if fails */ public static String md5sum(byte[] original) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(original, 0, original.length); StringBuffer md5sum = new StringBuffer(new BigInteger(1, md.digest()).toString(16)); while(md5sum.length() < 32) md5sum.insert(0, "0"); return md5sum.toString(); } catch(NoSuchAlgorithmException e) { //Logger.e(e.toString()); } return null; } /** * * @param original * @return null if fails */ public static String md5sum(String original) { return md5sum(original.getBytes()); } /** * AES encrypt function * * @param original * @param key 16, 24, 32 bytes available * @param iv initial vector (16 bytes) - if null: ECB mode, otherwise: CBC mode * @return */ public static byte[] aesEncrypt(byte[] original, byte[] key, byte[] iv) { if(key == null || (key.length != 16 && key.length != 24 && key.length != 32)) { // Logger.e("key's bit length is not 128/192/256"); return null; } if(iv != null && iv.length != 16) { // Logger.e("iv's bit length is not 16"); return null; } try { SecretKeySpec keySpec = null; Cipher cipher = null; if(iv != null) { keySpec = new SecretKeySpec(key, "AES/CBC/PKCS7Padding"); cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); } else //if(iv == null) { keySpec = new SecretKeySpec(key, "AES/ECB/PKCS7Padding"); cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); } return cipher.doFinal(original); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * AES decrypt function * * @param encrypted * @param key 16, 24, 32 bytes available * @param iv initial vector (16 bytes) - if null: ECB mode, otherwise: CBC mode * @return */ public static byte[] aesDecrypt(byte[] encrypted, byte[] key, byte[] iv) { if(key == null || (key.length != 16 && key.length != 24 && key.length != 32)) { // Logger.e("key's bit length is not 128/192/256"); return null; } if(iv != null && iv.length != 16) { // Logger.e("iv's bit length is not 16"); return null; } try { SecretKeySpec keySpec = null; Cipher cipher = null; if(iv != null) { keySpec = new SecretKeySpec(key, "AES/CBC/PKCS7Padding"); cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv)); } else //if(iv == null) { keySpec = new SecretKeySpec(key, "AES/ECB/PKCS7Padding"); cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec); } return cipher.doFinal(encrypted); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * generates RSA key pair * * @param keySize * @param publicExponent public exponent value (can be RSAKeyGenParameterSpec.F0 or F4) * @return */ public static KeyPair generateRsaKeyPair(int keySize, BigInteger publicExponent) { KeyPair keys = null; try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(keySize, publicExponent); keyGen.initialize(spec); keys = keyGen.generateKeyPair(); } catch(Exception e) { // Logger.e(e.toString()); } return keys; } /** * generates a RSA public key with given modulus and public exponent * * @param modulus (must be positive? don't know exactly) * @param publicExponent * @return */ public static PublicKey generateRsaPublicKey(BigInteger modulus, BigInteger publicExponent) { try { return KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, publicExponent)); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * generates a RSA private key with given modulus and private exponent * * @param modulus (must be positive? don't know exactly) * @param privateExponent * @return */ public static PrivateKey generateRsaPrivateKey(BigInteger modulus, BigInteger privateExponent) { try { return KeyFactory.getInstance("RSA").generatePrivate(new RSAPrivateKeySpec(modulus, privateExponent)); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * RSA encrypt function (RSA / ECB / PKCS1-Padding) * * @param original * @param key * @return */ public static byte[] rsaEncrypt(byte[] original, PublicKey key) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(original); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * RSA decrypt function (RSA / ECB / PKCS1-Padding) * * @param encrypted * @param key * @return */ public static byte[] rsaDecrypt(byte[] encrypted, PrivateKey key) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(encrypted); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * converts given byte array to a hex string * * @param bytes * @return */ public static String byteArrayToHexString(byte[] bytes) { StringBuffer buffer = new StringBuffer(); for(int i=0; i<bytes.length; i++) { if(((int)bytes[i] & 0xff) < 0x10) buffer.append("0"); buffer.append(Long.toString((int) bytes[i] & 0xff, 16)); } return buffer.toString(); } /** * converts given hex string to a byte array * (ex: "0D0A" => {0x0D, 0x0A,}) * * @param str * @return */ public static final byte[] hexStringToByteArray(String str) { int i = 0; byte[] results = new byte[str.length() / 2]; for (int k = 0; k < str.length();) { results[i] = (byte)(Character.digit(str.charAt(k++), 16) << 4); results[i] += (byte)(Character.digit(str.charAt(k++), 16)); i++; } return results; } } //Copyright 2003-2009 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland //www.source-code.biz, www.inventec.ch/chdh // //This module is multi-licensed and may be used under the terms //of any of the following licenses: // //EPL, Eclipse Public License, http://www.eclipse.org/legal //LGPL, GNU Lesser General Public License, http://www.gnu.org/licenses/lgpl.html //AL, Apache License, http://www.apache.org/licenses //BSD, BSD License, http://www.opensource.org/licenses/bsd-license.php // //Please contact the author if you need another license. //This module is provided "as is", without warranties of any kind. /** * A Base64 Encoder/Decoder. * * <p> * This class is used to encode and decode data in Base64 format as described in RFC 1521. * * <p> * Home page: <a href="http://www.source-code.biz">www.source-code.biz</a><br> * Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br> * Multi-licensed: EPL/LGPL/AL/BSD. * * <p> * Version history:<br> * 2003-07-22 Christian d'Heureuse (chdh): Module created.<br> * 2005-08-11 chdh: Lincense changed from GPL to LGPL.<br> * 2006-11-21 chdh:<br> * Method encode(String) renamed to encodeString(String).<br> * Method decode(String) renamed to decodeString(String).<br> * New method encode(byte[],int) added.<br> * New method decode(String) added.<br> * 2009-07-16: Additional licenses (EPL/AL) added.<br> * 2009-09-16: Additional license (BSD) added.<br> */ class Base64Coder { //Mapping table from 6-bit nibbles to Base64 characters. private static char[] map1 = new char[64]; static { int i=0; for (char c='A'; c<='Z'; c++) map1[i++] = c; for (char c='a'; c<='z'; c++) map1[i++] = c; for (char c='0'; c<='9'; c++) map1[i++] = c; map1[i++] = '+'; map1[i++] = '/'; } //Mapping table from Base64 characters to 6-bit nibbles. private static byte[] map2 = new byte[128]; static { for (int i=0; i<map2.length; i++) map2[i] = -1; for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; } /** * Encodes a string into Base64 format. * No blanks or line breaks are inserted. * @param s a String to be encoded. * @return A String with the Base64 encoded data. */ public static String encodeString (String s) { return new String(encode(s.getBytes())); } /** * Encodes a byte array into Base64 format. * No blanks or line breaks are inserted. * @param in an array containing the data bytes to be encoded. * @return A character array with the Base64 encoded data. */ public static char[] encode (byte[] in) { return encode(in,in.length); } /** * Encodes a byte array into Base64 format. * No blanks or line breaks are inserted. * @param in an array containing the data bytes to be encoded. * @param iLen number of bytes to process in <code>in</code>. * @return A character array with the Base64 encoded data. */ public static char[] encode (byte[] in, int iLen) { int oDataLen = (iLen*4+2)/3; // output length without padding int oLen = ((iLen+2)/3)*4; // output length including padding char[] out = new char[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++] & 0xff; int i1 = ip < iLen ? in[ip++] & 0xff : 0; int i2 = ip < iLen ? in[ip++] & 0xff : 0; int o0 = i0 >>> 2; int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : '='; op++; out[op] = op < oDataLen ? map1[o3] : '='; op++; } return out; } /** * Decodes a string from Base64 format. * @param s a Base64 String to be decoded. * @return A String containing the decoded data. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static String decodeString (String s) { return new String(decode(s)); } /** * Decodes a byte array from Base64 format. * @param s a Base64 String to be decoded. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static byte[] decode (String s) { return decode(s.toCharArray()); } /** * Decodes a byte array from Base64 format. * No blanks or line breaks are allowed within the Base64 encoded data. * @param in a character array containing the Base64 encoded data. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static byte[] decode (char[] in) { int iLen = in.length; if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); while (iLen > 0 && in[iLen-1] == '=') iLen--; int oLen = (iLen*3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : 'A'; int i3 = ip < iLen ? in[ip++] : 'A'; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int b0 = map2[i0]; int b1 = map2[i1]; int b2 = map2[i2]; int b3 = map2[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int o0 = ( b0 <<2) | (b1>>>4); int o1 = ((b1 & 0xf)<<4) | (b2>>>2); int o2 = ((b2 & 3)<<6) | b3; out[op++] = (byte)o0; if (op<oLen) out[op++] = (byte)o1; if (op<oLen) out[op++] = (byte)o2; } return out; } //Dummy constructor. private Base64Coder() {} } // end class Base64Coder
Generates RSA key pair
//package org.andlib.helpers; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import javax.crypto.Cipher; import javax.crypto.Mac; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * * @author meinside@gmail.com * @since 09.11.24. * * last update 10.04.13. * */ final class StringCodec { /** * * @param original * @return null if fails */ public static String urlencode(String original) { try { //return URLEncoder.encode(original, "utf-8"); //fixed: to comply with RFC-3986 return URLEncoder.encode(original, "utf-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } catch(UnsupportedEncodingException e) { // Logger.e(e.toString()); } return null; } /** * * @param encoded * @return null if fails */ public static String urldecode(String encoded) { try { return URLDecoder.decode(encoded, "utf-8"); } catch(UnsupportedEncodingException e) { // Logger.e(e.toString()); } return null; } /** * * @param original * @param key * @return null if fails */ public static String hmacSha1Digest(String original, String key) { return hmacSha1Digest(original.getBytes(), key.getBytes()); } /** * * @param original * @param key * @return null if fails */ public static String hmacSha1Digest(byte[] original, byte[] key) { try { Mac mac = Mac.getInstance("HmacSHA1"); mac.init(new SecretKeySpec(key, "HmacSHA1")); byte[] rawHmac = mac.doFinal(original); return new String(Base64Coder.encode(rawHmac)); } catch (Exception e) { // Logger.e(e.toString()); } return null; } /** * * @param original * @return null if fails */ public static String md5sum(byte[] original) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(original, 0, original.length); StringBuffer md5sum = new StringBuffer(new BigInteger(1, md.digest()).toString(16)); while(md5sum.length() < 32) md5sum.insert(0, "0"); return md5sum.toString(); } catch(NoSuchAlgorithmException e) { //Logger.e(e.toString()); } return null; } /** * * @param original * @return null if fails */ public static String md5sum(String original) { return md5sum(original.getBytes()); } /** * AES encrypt function * * @param original * @param key 16, 24, 32 bytes available * @param iv initial vector (16 bytes) - if null: ECB mode, otherwise: CBC mode * @return */ public static byte[] aesEncrypt(byte[] original, byte[] key, byte[] iv) { if(key == null || (key.length != 16 && key.length != 24 && key.length != 32)) { // Logger.e("key's bit length is not 128/192/256"); return null; } if(iv != null && iv.length != 16) { // Logger.e("iv's bit length is not 16"); return null; } try { SecretKeySpec keySpec = null; Cipher cipher = null; if(iv != null) { keySpec = new SecretKeySpec(key, "AES/CBC/PKCS7Padding"); cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); } else //if(iv == null) { keySpec = new SecretKeySpec(key, "AES/ECB/PKCS7Padding"); cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); } return cipher.doFinal(original); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * AES decrypt function * * @param encrypted * @param key 16, 24, 32 bytes available * @param iv initial vector (16 bytes) - if null: ECB mode, otherwise: CBC mode * @return */ public static byte[] aesDecrypt(byte[] encrypted, byte[] key, byte[] iv) { if(key == null || (key.length != 16 && key.length != 24 && key.length != 32)) { // Logger.e("key's bit length is not 128/192/256"); return null; } if(iv != null && iv.length != 16) { // Logger.e("iv's bit length is not 16"); return null; } try { SecretKeySpec keySpec = null; Cipher cipher = null; if(iv != null) { keySpec = new SecretKeySpec(key, "AES/CBC/PKCS7Padding"); cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv)); } else //if(iv == null) { keySpec = new SecretKeySpec(key, "AES/ECB/PKCS7Padding"); cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec); } return cipher.doFinal(encrypted); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * generates RSA key pair * * @param keySize * @param publicExponent public exponent value (can be RSAKeyGenParameterSpec.F0 or F4) * @return */ public static KeyPair generateRsaKeyPair(int keySize, BigInteger publicExponent) { KeyPair keys = null; try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(keySize, publicExponent); keyGen.initialize(spec); keys = keyGen.generateKeyPair(); } catch(Exception e) { // Logger.e(e.toString()); } return keys; } /** * generates a RSA public key with given modulus and public exponent * * @param modulus (must be positive? don't know exactly) * @param publicExponent * @return */ public static PublicKey generateRsaPublicKey(BigInteger modulus, BigInteger publicExponent) { try { return KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, publicExponent)); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * generates a RSA private key with given modulus and private exponent * * @param modulus (must be positive? don't know exactly) * @param privateExponent * @return */ public static PrivateKey generateRsaPrivateKey(BigInteger modulus, BigInteger privateExponent) { try { return KeyFactory.getInstance("RSA").generatePrivate(new RSAPrivateKeySpec(modulus, privateExponent)); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * RSA encrypt function (RSA / ECB / PKCS1-Padding) * * @param original * @param key * @return */ public static byte[] rsaEncrypt(byte[] original, PublicKey key) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(original); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * RSA decrypt function (RSA / ECB / PKCS1-Padding) * * @param encrypted * @param key * @return */ public static byte[] rsaDecrypt(byte[] encrypted, PrivateKey key) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(encrypted); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * converts given byte array to a hex string * * @param bytes * @return */ public static String byteArrayToHexString(byte[] bytes) { StringBuffer buffer = new StringBuffer(); for(int i=0; i<bytes.length; i++) { if(((int)bytes[i] & 0xff) < 0x10) buffer.append("0"); buffer.append(Long.toString((int) bytes[i] & 0xff, 16)); } return buffer.toString(); } /** * converts given hex string to a byte array * (ex: "0D0A" => {0x0D, 0x0A,}) * * @param str * @return */ public static final byte[] hexStringToByteArray(String str) { int i = 0; byte[] results = new byte[str.length() / 2]; for (int k = 0; k < str.length();) { results[i] = (byte)(Character.digit(str.charAt(k++), 16) << 4); results[i] += (byte)(Character.digit(str.charAt(k++), 16)); i++; } return results; } } //Copyright 2003-2009 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland //www.source-code.biz, www.inventec.ch/chdh // //This module is multi-licensed and may be used under the terms //of any of the following licenses: // //EPL, Eclipse Public License, http://www.eclipse.org/legal //LGPL, GNU Lesser General Public License, http://www.gnu.org/licenses/lgpl.html //AL, Apache License, http://www.apache.org/licenses //BSD, BSD License, http://www.opensource.org/licenses/bsd-license.php // //Please contact the author if you need another license. //This module is provided "as is", without warranties of any kind. /** * A Base64 Encoder/Decoder. * * <p> * This class is used to encode and decode data in Base64 format as described in RFC 1521. * * <p> * Home page: <a href="http://www.source-code.biz">www.source-code.biz</a><br> * Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br> * Multi-licensed: EPL/LGPL/AL/BSD. * * <p> * Version history:<br> * 2003-07-22 Christian d'Heureuse (chdh): Module created.<br> * 2005-08-11 chdh: Lincense changed from GPL to LGPL.<br> * 2006-11-21 chdh:<br> * Method encode(String) renamed to encodeString(String).<br> * Method decode(String) renamed to decodeString(String).<br> * New method encode(byte[],int) added.<br> * New method decode(String) added.<br> * 2009-07-16: Additional licenses (EPL/AL) added.<br> * 2009-09-16: Additional license (BSD) added.<br> */ class Base64Coder { //Mapping table from 6-bit nibbles to Base64 characters. private static char[] map1 = new char[64]; static { int i=0; for (char c='A'; c<='Z'; c++) map1[i++] = c; for (char c='a'; c<='z'; c++) map1[i++] = c; for (char c='0'; c<='9'; c++) map1[i++] = c; map1[i++] = '+'; map1[i++] = '/'; } //Mapping table from Base64 characters to 6-bit nibbles. private static byte[] map2 = new byte[128]; static { for (int i=0; i<map2.length; i++) map2[i] = -1; for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; } /** * Encodes a string into Base64 format. * No blanks or line breaks are inserted. * @param s a String to be encoded. * @return A String with the Base64 encoded data. */ public static String encodeString (String s) { return new String(encode(s.getBytes())); } /** * Encodes a byte array into Base64 format. * No blanks or line breaks are inserted. * @param in an array containing the data bytes to be encoded. * @return A character array with the Base64 encoded data. */ public static char[] encode (byte[] in) { return encode(in,in.length); } /** * Encodes a byte array into Base64 format. * No blanks or line breaks are inserted. * @param in an array containing the data bytes to be encoded. * @param iLen number of bytes to process in <code>in</code>. * @return A character array with the Base64 encoded data. */ public static char[] encode (byte[] in, int iLen) { int oDataLen = (iLen*4+2)/3; // output length without padding int oLen = ((iLen+2)/3)*4; // output length including padding char[] out = new char[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++] & 0xff; int i1 = ip < iLen ? in[ip++] & 0xff : 0; int i2 = ip < iLen ? in[ip++] & 0xff : 0; int o0 = i0 >>> 2; int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : '='; op++; out[op] = op < oDataLen ? map1[o3] : '='; op++; } return out; } /** * Decodes a string from Base64 format. * @param s a Base64 String to be decoded. * @return A String containing the decoded data. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static String decodeString (String s) { return new String(decode(s)); } /** * Decodes a byte array from Base64 format. * @param s a Base64 String to be decoded. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static byte[] decode (String s) { return decode(s.toCharArray()); } /** * Decodes a byte array from Base64 format. * No blanks or line breaks are allowed within the Base64 encoded data. * @param in a character array containing the Base64 encoded data. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static byte[] decode (char[] in) { int iLen = in.length; if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); while (iLen > 0 && in[iLen-1] == '=') iLen--; int oLen = (iLen*3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : 'A'; int i3 = ip < iLen ? in[ip++] : 'A'; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int b0 = map2[i0]; int b1 = map2[i1]; int b2 = map2[i2]; int b3 = map2[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int o0 = ( b0 <<2) | (b1>>>4); int o1 = ((b1 & 0xf)<<4) | (b2>>>2); int o2 = ((b2 & 3)<<6) | b3; out[op++] = (byte)o0; if (op<oLen) out[op++] = (byte)o1; if (op<oLen) out[op++] = (byte)o2; } return out; } //Dummy constructor. private Base64Coder() {} } // end class Base64Coder
Generates a RSA public key with given modulus and public/private exponent
//package org.andlib.helpers; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import javax.crypto.Cipher; import javax.crypto.Mac; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; final class StringCodec { public static String urlencode(String original) { try { //return URLEncoder.encode(original, "utf-8"); //fixed: to comply with RFC-3986 return URLEncoder.encode(original, "utf-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } catch(UnsupportedEncodingException e) { // Logger.e(e.toString()); } return null; } public static String urldecode(String encoded) { try { return URLDecoder.decode(encoded, "utf-8"); } catch(UnsupportedEncodingException e) { // Logger.e(e.toString()); } return null; } public static String hmacSha1Digest(String original, String key) { return hmacSha1Digest(original.getBytes(), key.getBytes()); } public static String hmacSha1Digest(byte[] original, byte[] key) { try { Mac mac = Mac.getInstance("HmacSHA1"); mac.init(new SecretKeySpec(key, "HmacSHA1")); byte[] rawHmac = mac.doFinal(original); return new String(Base64Coder.encode(rawHmac)); } catch (Exception e) { // Logger.e(e.toString()); } return null; } public static String md5sum(byte[] original) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(original, 0, original.length); StringBuffer md5sum = new StringBuffer(new BigInteger(1, md.digest()).toString(16)); while(md5sum.length() < 32) md5sum.insert(0, "0"); return md5sum.toString(); } catch(NoSuchAlgorithmException e) { //Logger.e(e.toString()); } return null; } public static String md5sum(String original) { return md5sum(original.getBytes()); } public static byte[] aesEncrypt(byte[] original, byte[] key, byte[] iv) { if(key == null || (key.length != 16 && key.length != 24 && key.length != 32)) { // Logger.e("key's bit length is not 128/192/256"); return null; } if(iv != null && iv.length != 16) { // Logger.e("iv's bit length is not 16"); return null; } try { SecretKeySpec keySpec = null; Cipher cipher = null; if(iv != null) { keySpec = new SecretKeySpec(key, "AES/CBC/PKCS7Padding"); cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); } else //if(iv == null) { keySpec = new SecretKeySpec(key, "AES/ECB/PKCS7Padding"); cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); } return cipher.doFinal(original); } catch(Exception e) { // Logger.e(e.toString()); } return null; } public static byte[] aesDecrypt(byte[] encrypted, byte[] key, byte[] iv) { if(key == null || (key.length != 16 && key.length != 24 && key.length != 32)) { // Logger.e("key's bit length is not 128/192/256"); return null; } if(iv != null && iv.length != 16) { // Logger.e("iv's bit length is not 16"); return null; } try { SecretKeySpec keySpec = null; Cipher cipher = null; if(iv != null) { keySpec = new SecretKeySpec(key, "AES/CBC/PKCS7Padding"); cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv)); } else //if(iv == null) { keySpec = new SecretKeySpec(key, "AES/ECB/PKCS7Padding"); cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec); } return cipher.doFinal(encrypted); } catch(Exception e) { // Logger.e(e.toString()); } return null; } public static KeyPair generateRsaKeyPair(int keySize, BigInteger publicExponent) { KeyPair keys = null; try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(keySize, publicExponent); keyGen.initialize(spec); keys = keyGen.generateKeyPair(); } catch(Exception e) { // Logger.e(e.toString()); } return keys; } public static PublicKey generateRsaPublicKey(BigInteger modulus, BigInteger publicExponent) { try { return KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, publicExponent)); } catch(Exception e) { // Logger.e(e.toString()); } return null; } public static PrivateKey generateRsaPrivateKey(BigInteger modulus, BigInteger privateExponent) { try { return KeyFactory.getInstance("RSA").generatePrivate(new RSAPrivateKeySpec(modulus, privateExponent)); } catch(Exception e) { // Logger.e(e.toString()); } return null; } public static byte[] rsaEncrypt(byte[] original, PublicKey key) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(original); } catch(Exception e) { // Logger.e(e.toString()); } return null; } public static byte[] rsaDecrypt(byte[] encrypted, PrivateKey key) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(encrypted); } catch(Exception e) { // Logger.e(e.toString()); } return null; } public static String byteArrayToHexString(byte[] bytes) { StringBuffer buffer = new StringBuffer(); for(int i=0; i<bytes.length; i++) { if(((int)bytes[i] & 0xff) < 0x10) buffer.append("0"); buffer.append(Long.toString((int) bytes[i] & 0xff, 16)); } return buffer.toString(); } public static final byte[] hexStringToByteArray(String str) { int i = 0; byte[] results = new byte[str.length() / 2]; for (int k = 0; k < str.length();) { results[i] = (byte)(Character.digit(str.charAt(k++), 16) << 4); results[i] += (byte)(Character.digit(str.charAt(k++), 16)); i++; } return results; } } class Base64Coder { //Mapping table from 6-bit nibbles to Base64 characters. private static char[] map1 = new char[64]; static { int i=0; for (char c='A'; c<='Z'; c++) map1[i++] = c; for (char c='a'; c<='z'; c++) map1[i++] = c; for (char c='0'; c<='9'; c++) map1[i++] = c; map1[i++] = '+'; map1[i++] = '/'; } //Mapping table from Base64 characters to 6-bit nibbles. private static byte[] map2 = new byte[128]; static { for (int i=0; i<map2.length; i++) map2[i] = -1; for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; } public static String encodeString (String s) { return new String(encode(s.getBytes())); } public static char[] encode (byte[] in) { return encode(in,in.length); } public static char[] encode (byte[] in, int iLen) { int oDataLen = (iLen*4+2)/3; // output length without padding int oLen = ((iLen+2)/3)*4; // output length including padding char[] out = new char[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++] & 0xff; int i1 = ip < iLen ? in[ip++] & 0xff : 0; int i2 = ip < iLen ? in[ip++] & 0xff : 0; int o0 = i0 >>> 2; int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : '='; op++; out[op] = op < oDataLen ? map1[o3] : '='; op++; } return out; } public static String decodeString (String s) { return new String(decode(s)); } public static byte[] decode (String s) { return decode(s.toCharArray()); } public static byte[] decode (char[] in) { int iLen = in.length; if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); while (iLen > 0 && in[iLen-1] == '=') iLen--; int oLen = (iLen*3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : 'A'; int i3 = ip < iLen ? in[ip++] : 'A'; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int b0 = map2[i0]; int b1 = map2[i1]; int b2 = map2[i2]; int b3 = map2[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int o0 = ( b0 <<2) | (b1>>>4); int o1 = ((b1 & 0xf)<<4) | (b2>>>2); int o2 = ((b2 & 3)<<6) | b3; out[op++] = (byte)o0; if (op<oLen) out[op++] = (byte)o1; if (op<oLen) out[op++] = (byte)o2; } return out; } //Dummy constructor. private Base64Coder() {} } // end class Base64Coder
AES encrypt/decrypt function
//package org.andlib.helpers; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import javax.crypto.Cipher; import javax.crypto.Mac; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * * @author meinside@gmail.com * @since 09.11.24. * * last update 10.04.13. * */ final class StringCodec { /** * * @param original * @return null if fails */ public static String urlencode(String original) { try { //return URLEncoder.encode(original, "utf-8"); //fixed: to comply with RFC-3986 return URLEncoder.encode(original, "utf-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); } catch(UnsupportedEncodingException e) { // Logger.e(e.toString()); } return null; } /** * * @param encoded * @return null if fails */ public static String urldecode(String encoded) { try { return URLDecoder.decode(encoded, "utf-8"); } catch(UnsupportedEncodingException e) { // Logger.e(e.toString()); } return null; } /** * * @param original * @param key * @return null if fails */ public static String hmacSha1Digest(String original, String key) { return hmacSha1Digest(original.getBytes(), key.getBytes()); } /** * * @param original * @param key * @return null if fails */ public static String hmacSha1Digest(byte[] original, byte[] key) { try { Mac mac = Mac.getInstance("HmacSHA1"); mac.init(new SecretKeySpec(key, "HmacSHA1")); byte[] rawHmac = mac.doFinal(original); return new String(Base64Coder.encode(rawHmac)); } catch (Exception e) { // Logger.e(e.toString()); } return null; } /** * * @param original * @return null if fails */ public static String md5sum(byte[] original) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(original, 0, original.length); StringBuffer md5sum = new StringBuffer(new BigInteger(1, md.digest()).toString(16)); while(md5sum.length() < 32) md5sum.insert(0, "0"); return md5sum.toString(); } catch(NoSuchAlgorithmException e) { //Logger.e(e.toString()); } return null; } /** * * @param original * @return null if fails */ public static String md5sum(String original) { return md5sum(original.getBytes()); } /** * AES encrypt function * * @param original * @param key 16, 24, 32 bytes available * @param iv initial vector (16 bytes) - if null: ECB mode, otherwise: CBC mode * @return */ public static byte[] aesEncrypt(byte[] original, byte[] key, byte[] iv) { if(key == null || (key.length != 16 && key.length != 24 && key.length != 32)) { // Logger.e("key's bit length is not 128/192/256"); return null; } if(iv != null && iv.length != 16) { // Logger.e("iv's bit length is not 16"); return null; } try { SecretKeySpec keySpec = null; Cipher cipher = null; if(iv != null) { keySpec = new SecretKeySpec(key, "AES/CBC/PKCS7Padding"); cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); } else //if(iv == null) { keySpec = new SecretKeySpec(key, "AES/ECB/PKCS7Padding"); cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); } return cipher.doFinal(original); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * AES decrypt function * * @param encrypted * @param key 16, 24, 32 bytes available * @param iv initial vector (16 bytes) - if null: ECB mode, otherwise: CBC mode * @return */ public static byte[] aesDecrypt(byte[] encrypted, byte[] key, byte[] iv) { if(key == null || (key.length != 16 && key.length != 24 && key.length != 32)) { // Logger.e("key's bit length is not 128/192/256"); return null; } if(iv != null && iv.length != 16) { // Logger.e("iv's bit length is not 16"); return null; } try { SecretKeySpec keySpec = null; Cipher cipher = null; if(iv != null) { keySpec = new SecretKeySpec(key, "AES/CBC/PKCS7Padding"); cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv)); } else //if(iv == null) { keySpec = new SecretKeySpec(key, "AES/ECB/PKCS7Padding"); cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec); } return cipher.doFinal(encrypted); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * generates RSA key pair * * @param keySize * @param publicExponent public exponent value (can be RSAKeyGenParameterSpec.F0 or F4) * @return */ public static KeyPair generateRsaKeyPair(int keySize, BigInteger publicExponent) { KeyPair keys = null; try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(keySize, publicExponent); keyGen.initialize(spec); keys = keyGen.generateKeyPair(); } catch(Exception e) { // Logger.e(e.toString()); } return keys; } /** * generates a RSA public key with given modulus and public exponent * * @param modulus (must be positive? don't know exactly) * @param publicExponent * @return */ public static PublicKey generateRsaPublicKey(BigInteger modulus, BigInteger publicExponent) { try { return KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, publicExponent)); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * generates a RSA private key with given modulus and private exponent * * @param modulus (must be positive? don't know exactly) * @param privateExponent * @return */ public static PrivateKey generateRsaPrivateKey(BigInteger modulus, BigInteger privateExponent) { try { return KeyFactory.getInstance("RSA").generatePrivate(new RSAPrivateKeySpec(modulus, privateExponent)); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * RSA encrypt function (RSA / ECB / PKCS1-Padding) * * @param original * @param key * @return */ public static byte[] rsaEncrypt(byte[] original, PublicKey key) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(original); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * RSA decrypt function (RSA / ECB / PKCS1-Padding) * * @param encrypted * @param key * @return */ public static byte[] rsaDecrypt(byte[] encrypted, PrivateKey key) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(encrypted); } catch(Exception e) { // Logger.e(e.toString()); } return null; } /** * converts given byte array to a hex string * * @param bytes * @return */ public static String byteArrayToHexString(byte[] bytes) { StringBuffer buffer = new StringBuffer(); for(int i=0; i<bytes.length; i++) { if(((int)bytes[i] & 0xff) < 0x10) buffer.append("0"); buffer.append(Long.toString((int) bytes[i] & 0xff, 16)); } return buffer.toString(); } /** * converts given hex string to a byte array * (ex: "0D0A" => {0x0D, 0x0A,}) * * @param str * @return */ public static final byte[] hexStringToByteArray(String str) { int i = 0; byte[] results = new byte[str.length() / 2]; for (int k = 0; k < str.length();) { results[i] = (byte)(Character.digit(str.charAt(k++), 16) << 4); results[i] += (byte)(Character.digit(str.charAt(k++), 16)); i++; } return results; } } class Base64Coder { //Mapping table from 6-bit nibbles to Base64 characters. private static char[] map1 = new char[64]; static { int i=0; for (char c='A'; c<='Z'; c++) map1[i++] = c; for (char c='a'; c<='z'; c++) map1[i++] = c; for (char c='0'; c<='9'; c++) map1[i++] = c; map1[i++] = '+'; map1[i++] = '/'; } //Mapping table from Base64 characters to 6-bit nibbles. private static byte[] map2 = new byte[128]; static { for (int i=0; i<map2.length; i++) map2[i] = -1; for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; } /** * Encodes a string into Base64 format. * No blanks or line breaks are inserted. * @param s a String to be encoded. * @return A String with the Base64 encoded data. */ public static String encodeString (String s) { return new String(encode(s.getBytes())); } /** * Encodes a byte array into Base64 format. * No blanks or line breaks are inserted. * @param in an array containing the data bytes to be encoded. * @return A character array with the Base64 encoded data. */ public static char[] encode (byte[] in) { return encode(in,in.length); } /** * Encodes a byte array into Base64 format. * No blanks or line breaks are inserted. * @param in an array containing the data bytes to be encoded. * @param iLen number of bytes to process in <code>in</code>. * @return A character array with the Base64 encoded data. */ public static char[] encode (byte[] in, int iLen) { int oDataLen = (iLen*4+2)/3; // output length without padding int oLen = ((iLen+2)/3)*4; // output length including padding char[] out = new char[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++] & 0xff; int i1 = ip < iLen ? in[ip++] & 0xff : 0; int i2 = ip < iLen ? in[ip++] & 0xff : 0; int o0 = i0 >>> 2; int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : '='; op++; out[op] = op < oDataLen ? map1[o3] : '='; op++; } return out; } /** * Decodes a string from Base64 format. * @param s a Base64 String to be decoded. * @return A String containing the decoded data. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static String decodeString (String s) { return new String(decode(s)); } /** * Decodes a byte array from Base64 format. * @param s a Base64 String to be decoded. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static byte[] decode (String s) { return decode(s.toCharArray()); } /** * Decodes a byte array from Base64 format. * No blanks or line breaks are allowed within the Base64 encoded data. * @param in a character array containing the Base64 encoded data. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static byte[] decode (char[] in) { int iLen = in.length; if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); while (iLen > 0 && in[iLen-1] == '=') iLen--; int oLen = (iLen*3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : 'A'; int i3 = ip < iLen ? in[ip++] : 'A'; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int b0 = map2[i0]; int b1 = map2[i1]; int b2 = map2[i2]; int b3 = map2[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); int o0 = ( b0 <<2) | (b1>>>4); int o1 = ((b1 & 0xf)<<4) | (b2>>>2); int o2 = ((b2 & 3)<<6) | b3; out[op++] = (byte)o0; if (op<oLen) out[op++] = (byte)o1; if (op<oLen) out[op++] = (byte)o2; } return out; } //Dummy constructor. private Base64Coder() {} } // end class Base64Coder
encrypt/decrypt AES, encrypt/decrypt PBE
//package com.login.encryption; import java.security.AlgorithmParameters; import java.security.SecureRandom; import java.security.spec.KeySpec; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; class SecurityUtils { private static final byte[] salt = { (byte) 0xA4, (byte) 0x0B, (byte) 0xC8, (byte) 0x34, (byte) 0xD6, (byte) 0x95, (byte) 0xF3, (byte) 0x13 }; private static int BLOCKS = 128; public static byte[] encryptAES(String seed, String cleartext) throws Exception { byte[] rawKey = getRawKey(seed.getBytes("UTF8")); SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); return cipher.doFinal(cleartext.getBytes("UTF8")); } public static byte[] decryptAES(String seed, byte[] data) throws Exception { byte[] rawKey = getRawKey(seed.getBytes("UTF8")); SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec); return cipher.doFinal(data); } private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(seed); kgen.init(BLOCKS, sr); // 192 and 256 bits may not be available SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } private static byte[] pad(byte[] seed) { byte[] nseed = new byte[BLOCKS / 8]; for (int i = 0; i < BLOCKS / 8; i++) nseed[i] = 0; for (int i = 0; i < seed.length; i++) nseed[i] = seed[i]; return nseed; } public static byte[] encryptPBE(String password, String cleartext) throws Exception { SecretKeyFactory factory = SecretKeyFactory .getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1024, 256); SecretKey tmp = factory.generateSecret(spec); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secret); AlgorithmParameters params = cipher.getParameters(); byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); return cipher.doFinal(cleartext.getBytes("UTF-8")); } public static String decryptPBE(SecretKey secret, String ciphertext, byte[] iv) throws Exception { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv)); return new String(cipher.doFinal(ciphertext.getBytes()), "UTF-8"); } }
AES Encryption
//package edu.gmu.tec.scout.utilities; import java.security.MessageDigest; import javax.crypto.*; import javax.crypto.spec.*; public class Encryption { private SecretKeySpec skeySpec; private Cipher cipher; public Encryption(byte [] keyraw) throws Exception{ if(keyraw == null){ byte[] bytesOfMessage = "".getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] bytes = md.digest(bytesOfMessage); skeySpec = new SecretKeySpec(bytes, "AES"); cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); } else{ skeySpec = new SecretKeySpec(keyraw, "AES"); cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); } } public Encryption(String passphrase) throws Exception{ byte[] bytesOfMessage = passphrase.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] thedigest = md.digest(bytesOfMessage); skeySpec = new SecretKeySpec(thedigest, "AES"); cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); } public Encryption() throws Exception{ byte[] bytesOfMessage = "".getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] thedigest = md.digest(bytesOfMessage); skeySpec = new SecretKeySpec(thedigest, "AES"); skeySpec = new SecretKeySpec(new byte[16], "AES"); cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); } public byte[] encrypt (byte[] plaintext) throws Exception{ //returns byte array encrypted with key cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] ciphertext = cipher.doFinal(plaintext); return ciphertext; } public byte[] decrypt (byte[] ciphertext) throws Exception{ //returns byte array decrypted with key cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] plaintext = cipher.doFinal(ciphertext); return plaintext; } public static void main(String[] args) throws Exception { String message="This is just an example"; Encryption encrypter = new Encryption(new byte[16]); byte[] encrypted = encrypter.encrypt(message.getBytes("UTF-8")); byte[] decrypted = encrypter.decrypt(encrypted); System.out.println(new String (decrypted, "UTF-8")); } }
Web authentication Confirmation
//package com.maxiujun.android.doudroid.test.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.CookiePolicy; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; /** * Type comments here. * * @author Xiujun Ma <maxj@adv.emcom.jp> * @version Jul 31, 2010 */ class OauthWebConfirm { private static HttpClient httpClient = new CHttpClient(); public static String email = ""; public static String pwd = ""; public static void confirm(String url) { httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); try { // login HttpPost loginpost = new HttpPost("http://www.douban.com/login"); String loginentity = "redir=&form_email=" + URLEncoder.encode(email, "UTF-8") + "&form_password=" + URLEncoder.encode(pwd, "UTF-8") +"&remember=on&user_login=%E8%BF%9B%E5%85%A5"; StringEntity reqEntity = new StringEntity(loginentity); reqEntity.setContentType("application/x-www-form-urlencoded"); loginpost.setEntity(reqEntity); loginpost.setHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8"); httpClient.execute(loginpost); // agree page HttpGet get = new HttpGet(url); get.setHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8"); HttpResponse res2 = httpClient.execute(get); String restring2 = convertStreamToString(res2.getEntity().getContent()); // agree action HttpPost agreepost = new HttpPost(url); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("oauth_token=").append(getFromValue(restring2, "oauth_token")); stringBuilder.append("&oauth_callback=").append(getFromValue(restring2, "oauth_callback")); stringBuilder.append("&ssid=").append(getFromValue(restring2, "ssid")); stringBuilder.append("&confirm=").append(getFromValue(restring2, "confirm")); StringEntity agreeEntity = new StringEntity(stringBuilder.toString()); agreeEntity.setContentType("application/x-www-form-urlencoded"); agreepost.setEntity(agreeEntity); agreepost.setHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8"); httpClient.execute(agreepost); // HttpResponse res3 = httpClient.execute(agreepost); // String restring3 = convertStreamToString(res3.getEntity().getContent()); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static String convertStreamToString(InputStream is) throws IOException { if (is != null) { StringBuilder sb = new StringBuilder(); String line; try { BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } } finally { is.close(); } return sb.toString(); } else { return ""; } } public static String getFromValue(String html, String name) { Pattern p = Pattern.compile("name=\\\"" + name + "\\\" value=\\\".+\\\""); Matcher m = p.matcher(html); String ex = ""; if(m.find()) ex = m.group(0); else return ""; String value = ""; try { value = URLEncoder.encode(ex.split("value=\"")[1].replace("\"", ""), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return value; } } class CHttpClient extends DefaultHttpClient { @Override protected ClientConnectionManager createClientConnectionManager() { SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); return new ThreadSafeClientConnManager(this.getParams(), registry); } }
Provides symmetric key cryptography and hashing.
//package com.hecticant.thinpass.security; import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import android.util.Log; public class CryptUtil { private static final String TAG = "CryptUtil"; private static final int KEYSIZE = 128; private static SecureRandom rd; static { try { rd = SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException e) { Log.e(TAG, e.getLocalizedMessage()); throw new RuntimeException("Certainly a random error", e); } } private static final byte[] defaultIV = { 127, 24, 123, 23, 93, 7, 15, 0, 9, 4, 8, 15, 16, 23, 42, 1}; public static SecretKey genMasterKey(char[] pwd, byte[] salt) { SecretKeyFactory kf; PBEKeySpec ks; SecretKey sk; try { kf = SecretKeyFactory.getInstance("PBEWITHSHAAND128BITAES-CBC-BC"); ks = new PBEKeySpec(pwd, salt, 1000, KEYSIZE); sk = kf.generateSecret(ks); ks.clearPassword(); } catch (GeneralSecurityException e) { Log.e(TAG, e.getLocalizedMessage()); throw new IllegalStateException("Error generating secret key", e); } return sk; } public static SecretKey genRandomKey() { KeyGenerator kg; try { kg = KeyGenerator.getInstance("AES"); kg.init(KEYSIZE, rd); } catch (GeneralSecurityException e) { Log.e(TAG, e.getLocalizedMessage()); throw new IllegalStateException("Error generating secret key", e); } return kg.generateKey(); } public static byte[] encrypt(byte[] key, byte[] clearText) { return encrypt(keyFromBytes(key), clearText); } public static byte[] decrypt(byte[] key, byte[] encryptedText) { return decrypt(keyFromBytes(key), encryptedText); } public static byte[] encrypt(SecretKey key, byte[] clearText) { return transform(Cipher.ENCRYPT_MODE, key, clearText); } public static byte[] decrypt(SecretKey key, byte[] encryptedText) { return transform(Cipher.DECRYPT_MODE, key, encryptedText); } protected static SecretKey keyFromBytes(byte[] keyBytes) { SecretKeySpec sks = new SecretKeySpec(keyBytes, "AES"); return sks; } private static byte[] transform(int mode, SecretKey key, byte[] text) { if (key == null || text == null) { throw new NullPointerException(); } byte[] transformedText = null; try { // CBC is used here because the implementation has some trouble // with ECB (thus the default IV). Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec sks = new SecretKeySpec(key.getEncoded(), "AES"); IvParameterSpec ivs = new IvParameterSpec(defaultIV); c.init(mode, sks, ivs, rd); transformedText = c.doFinal(text); } catch (GeneralSecurityException e) { Log.e(TAG, "transform: " + Log.getStackTraceString(e)); } return transformedText; } /** * Indispensable for reading slashdot. * * @return */ public static byte[] getSalt() { byte[] salt = new byte[16]; rd.nextBytes(salt); return salt; } public static byte[] hash(byte[] text, byte[] salt) { MessageDigest md = null; try { md = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e) { Log.e(TAG, "hash: " + e.getLocalizedMessage()); } md.update(text); md.update(salt); return md.digest(); } }
Returns permissions' name (human-readable label) by permission key
//package com.googlecode.securitywatch; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; import android.net.Uri; import android.os.Build; /** * Utility class */ class Utils { public static boolean hasPermission(String packageName, String permission, final PackageManager pkgmanager) { return PackageManager.PERMISSION_GRANTED == pkgmanager.checkPermission(permission, packageName); } /** * Returns permissions' name (human-readable label) by permission key */ static CharSequence getPermissionLabel(String permission, PackageManager packageManager) { try { PermissionInfo permissionInfo = packageManager.getPermissionInfo(permission, 0); return permissionInfo.loadLabel(packageManager); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return null; } private CharSequence getPermissionDescription(String permission, PackageManager packageManager) { try { PermissionInfo permissionInfo = packageManager.getPermissionInfo(permission, 0); return permissionInfo.loadDescription(packageManager); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return null; } }