package seed.utils; import java.util.ArrayList; import java.util.Base64; import java.util.List; public class SeedKISA { private static final String CHARACTER_SET = "UTF-8"; //private static final String DEFAULT_IV = "1234567890123456"; private static final String DEFAULT_IV = "SeedSecretKISADefaultIv"; /** * seed로 암호화된 문자열을 복호화 * @param encVal - 암호화 대상 string * @param seedKey - encrypt할때 사용한 key * @return * @throws Exception */ public static String getSeedDecrypt(String encVal, int[] seedKey) throws Exception{ // 암호화문 byte 배열 리스트로 변환 List encByteList = getByteList(encVal, true); // System.out.println("복호화할 바이트 시작"); // for(int i=0; i decByteList = new ArrayList(); // IV를 저장하라 변수 선언 byte[] byteIV = DEFAULT_IV.getBytes(); for(int i=0; i byteList = getByteList(strVal, false); // System.out.println("원본 바이트 시작"); // for(int i=0; i encByteList = new ArrayList(); // IV를 저장하라 변수 선언 byte[] byteIV = DEFAULT_IV.getBytes(); for(int i=0; i getByteList(String nomal, boolean isDecode) throws Exception{ List byteList = new ArrayList(); byte[] tempByte = null; if(isDecode){ /*BASE64Decoder base64Dec = new BASE64Decoder();*/ /*tempByte = base64Dec.decodeBuffer(nomal);*/ Base64.Decoder base64Dec = Base64.getDecoder(); tempByte = base64Dec.decode(nomal); }else{ tempByte = nomal.getBytes(CHARACTER_SET); } // seed 암호화를 위해선 byte가 무조건 16byte씩 배열이 생성되어야 함으로 빈배열의 공간수를 계산 int needBlankLength = 0; if(tempByte.length % 16 != 0){ needBlankLength = 16 - (tempByte.length % 16); } // 위에서 구한 필요한 빈공간의 수를 더하여 다시 배열 생성 byte[] newTempByte = new byte[tempByte.length + needBlankLength]; for(int i=0; i byteList, boolean isEncode) throws Exception{ // List에 담긴 byte배열이 16으로 고정임으로 * 16 byte[] listByte = new byte[byteList.size() * 16]; // List에 담긴 byte배열을 하나의 배열(listByte)에 merge for(int i=0; i0; i--){ if(listByte[i - 1] == 0){ blankCnt++; }else{ break; } } // blank를 제외한 만큼의 데이터만 추출 byte[] resultByte = new byte[listByte.length - blankCnt]; for(int i=0; i>>8)); }; private static int GetB2(int A){ return (int)(0x000000ff&((A)>>>16)); }; private static int GetB3(int A){ return (int)(0x000000ff&((A)>>>24)); }; private static void EndianChange(int dws[]) { dws[0] = (dws[0]>>>24) | (dws[0]<<24) | ((dws[0]<<8)&0x00ff0000)|((dws[0]>>>8)&0x0000ff00); }; private static int EndianChange(int dws) { return (dws>>>24) | (dws<<24) | ((dws<<8)&0x00ff0000)|((dws>>>8)&0x0000ff00); }; /****************************** Seed 암호화를 위한 멤버필드 **********************/ private static final int pdwRoundKey[] = new int[32]; // User secret key - mynameisheesungy private static final byte pbUserKey[] = {(byte)0x6d, (byte)0x79, (byte)0x6e, (byte)0x61, (byte)0x6d, (byte)0x65, (byte)0x69, (byte)0x73, (byte)0x68, (byte)0x65, (byte)0x65, (byte)0x73, (byte)0x75, (byte)0x6e, (byte)0x67, (byte)0x79}; // 사용자 입력 문자열 저장 private static byte pbData[] = new byte[16]; // input plaintext to be encrypted private static byte pbCipher[] = new byte[16]; private static byte pbPlain[] = new byte[16]; /***************************** Static 초기화 ************************************/ static{ SeedRoundKey(pdwRoundKey, pbUserKey); } /***************************** SEED round function ****************************/ private static void SeedRound( int L0[], int L1[], // [in, out] left-side variable at each round int R0[], int R1[], // [in] right-side variable at each round int K[]){ // [in] round keys at each round int T0, T1; long T00=0, T11=0; // F-function T0 = R0[0] ^ K[0]; T1 = R1[0] ^ K[1]; T1 ^= T0; T00 = (T0<0) ? (long)(T0 & 0x7fffffff)|(long)(0x80000000) : (long)(T0); T1 = SS0[GetB0(T1)] ^ SS1[GetB1(T1)] ^ SS2[GetB2(T1)] ^ SS3[GetB3(T1)]; T11 = (T1<0) ? (long)(T1 & 0x7fffffff)|(long)(0x80000000) : (long)(T1); T00 += T11; T0 = SS0[GetB0((int)T00)] ^ SS1[GetB1((int)T00)] ^ SS2[GetB2((int)T00)] ^ SS3[GetB3((int)T00)]; T00 = (T0<0) ? (long)(T0 & 0x7fffffff)|(long)(0x80000000) : (long)(T0); T11 += T00; T1 = SS0[GetB0((int)T11)] ^ SS1[GetB1((int)T11)] ^ SS2[GetB2((int)T11)] ^ SS3[GetB3((int)T11)]; T11 = (T1<0) ? (long)(T1 & 0x7fffffff)|(long)(0x80000000) : (long)(T1); T00 += T11; //output of F function is added to left-side variable L0[0] ^= (int)T00; L1[0] ^= (int)T11; }; /************************** SEED encrtyption function *************************/ private static void SeedEncrypt( byte pbData[], // [in] data to be encrypted int pdwRoundKey[], // [in] round keys for encryption byte outData[]){ // [out] encrypted data int L0[] = new int[1]; int L1[] = new int[1]; int R0[] = new int[1]; int R1[] = new int[1]; L0[0] = 0x0; L1[0] = 0x0; R0[0] = 0x0; R1[0] = 0x0; int K[] = new int[2]; int nCount = 0; //Set up input values for encryption L0[0] = ((int)pbData[0]&0x000000ff); L0[0] = ((L0[0])<<8)^((int)pbData[1]&0x000000ff); L0[0] = ((L0[0])<<8)^((int)pbData[2]&0x000000ff); L0[0] = ((L0[0])<<8)^((int)pbData[3]&0x000000ff); L1[0] = ((int)pbData[4]&0x000000ff); L1[0] = ((L1[0])<<8)^((int)pbData[5]&0x000000ff); L1[0] = ((L1[0])<<8)^((int)pbData[6]&0x000000ff); L1[0] = ((L1[0])<<8)^((int)pbData[7]&0x000000ff); R0[0] = ((int)pbData[8]&0x000000ff); R0[0] = ((R0[0])<<8)^((int)pbData[9]&0x000000ff); R0[0] = ((R0[0])<<8)^((int)pbData[10]&0x000000ff); R0[0] = ((R0[0])<<8)^((int)pbData[11]&0x000000ff); R1[0] = ((int)pbData[12]&0x000000ff); R1[0] = ((R1[0])<<8)^((int)pbData[13]&0x000000ff); R1[0] = ((R1[0])<<8)^((int)pbData[14]&0x000000ff); R1[0] = ((R1[0])<<8)^((int)pbData[15]&0x000000ff); //Reorder for little endian //Because java virtual machine use big endian order in default if (!ENDIAN) {EndianChange(L0); EndianChange(L1); EndianChange(R0); EndianChange(R1);}; K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(L0, L1, R0, R1, K); /* 1 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(R0, R1, L0, L1, K); /* 2 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(L0, L1, R0, R1, K); /* 3 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(R0, R1, L0, L1, K); /* 4 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(L0, L1, R0, R1, K); /* 5 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(R0, R1, L0, L1, K); /* 6 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(L0, L1, R0, R1, K); /* 7 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(R0, R1, L0, L1, K); /* 8 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(L0, L1, R0, R1, K); /* 9 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(R0, R1, L0, L1, K); /* 10 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(L0, L1, R0, R1, K); /* 11 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(R0, R1, L0, L1, K); /* 12 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(L0, L1, R0, R1, K); /* 13 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(R0, R1, L0, L1, K); /* 14 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(L0, L1, R0, R1, K); /* 15 */ K[0] = pdwRoundKey[nCount++]; K[1] = pdwRoundKey[nCount++]; SeedRound(R0, R1, L0, L1, K); /* 16 */ if (!ENDIAN) {EndianChange(L0); EndianChange(L1); EndianChange(R0); EndianChange(R1);}; //Copying output values from last round to outData for (int i=0; i<4; i++){ outData[i ] = (byte)(((R0[0])>>>(8*(3-i)))&0xff); outData[4+i ] = (byte)(((R1[0])>>>(8*(3-i)))&0xff); outData[8+i ] = (byte)(((L0[0])>>>(8*(3-i)))&0xff); outData[12+i] = (byte)(((L1[0])>>>(8*(3-i)))&0xff); } } /************************** SEED decrtyption function *************************/ // Same as encrypt, except that round keys are applied in reverse order private static void SeedDecrypt( byte pbData[], // [in] encrypted data int pdwRoundKey[], // [in] round keys for decryption byte outData[]){ // [out] data to be encrypted int L0[] = new int[1]; int L1[] = new int[1]; int R0[] = new int[1]; int R1[] = new int[1]; int K[] = new int[2]; L0[0] = 0x0; L1[0] = 0x0; R0[0] = 0x0; R1[0] = 0x0; int nCount = 31; // Set up input values for decryption L0[0] = ((int)pbData[0]&0x000000ff); L0[0] = ((L0[0])<<8)^((int)pbData[1]&0x000000ff); L0[0] = ((L0[0])<<8)^((int)pbData[2]&0x000000ff); L0[0] = ((L0[0])<<8)^((int)pbData[3]&0x000000ff); L1[0] = ((int)pbData[4]&0x000000ff); L1[0] = ((L1[0])<<8)^((int)pbData[5]&0x000000ff); L1[0] = ((L1[0])<<8)^((int)pbData[6]&0x000000ff); L1[0] = ((L1[0])<<8)^((int)pbData[7]&0x000000ff); R0[0] = ((int)pbData[8]&0x000000ff); R0[0] = ((R0[0])<<8)^((int)pbData[9]&0x000000ff); R0[0] = ((R0[0])<<8)^((int)pbData[10]&0x000000ff); R0[0] = ((R0[0])<<8)^((int)pbData[11]&0x000000ff); R1[0] = ((int)pbData[12]&0x000000ff); R1[0] = ((R1[0])<<8)^((int)pbData[13]&0x000000ff); R1[0] = ((R1[0])<<8)^((int)pbData[14]&0x000000ff); R1[0] = ((R1[0])<<8)^((int)pbData[15]&0x000000ff); // Reorder for little endian if (!ENDIAN) {EndianChange(L0); EndianChange(L1); EndianChange(R0); EndianChange(R1);}; K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(L0, L1, R0, R1, K); /* 1 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(R0, R1, L0, L1, K); /* 2 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(L0, L1, R0, R1, K); /* 3 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(R0, R1, L0, L1, K); /* 4 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(L0, L1, R0, R1, K); /* 5 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(R0, R1, L0, L1, K); /* 6 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(L0, L1, R0, R1, K); /* 7 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(R0, R1, L0, L1, K); /* 8 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(L0, L1, R0, R1, K); /* 9 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(R0, R1, L0, L1, K); /* 10 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(L0, L1, R0, R1, K); /* 11 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(R0, R1, L0, L1, K); /* 12 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(L0, L1, R0, R1, K); /* 13 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(R0, R1, L0, L1, K); /* 14 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount--]; SeedRound(L0, L1, R0, R1, K); /* 15 */ K[1] = pdwRoundKey[nCount--]; K[0] = pdwRoundKey[nCount]; SeedRound(R0, R1, L0, L1, K); /* 16 */ if (!ENDIAN) {EndianChange(L0); EndianChange(L1); EndianChange(R0); EndianChange(R1);}; // Copy output values from last round to outData for (int i=0; i<4; i++) { outData[i ] = (byte)(((R0[0])>>>(8*(3-i)))&0xff); outData[4+i ] = (byte)(((R1[0])>>>(8*(3-i)))&0xff); outData[8+i ] = (byte)(((L0[0])>>>(8*(3-i)))&0xff); outData[12+i] = (byte)(((L1[0])>>>(8*(3-i)))&0xff); } } /************************ Functions for Key schedule **************************/ private static void EncRoundKeyUpdate0(int K[], int A[], int B[], int C[], int D[], int Z){ //int T0, T1; int T0; int T00, T11; T0 = A[0]; A[0] = (A[0]>>>8) ^ (B[0]<<24); B[0] = (B[0]>>>8) ^ (T0<<24); T00 = (int)A[0] + (int)C[0] - (int)KC[Z]; T11 = (int)B[0] + (int)KC[Z] - (int)D[0]; K[0] = SS0[GetB0((int)T00)] ^ SS1[GetB1((int)T00)] ^ SS2[GetB2((int)T00)] ^ SS3[GetB3((int)T00)]; K[1] = SS0[GetB0((int)T11)] ^ SS1[GetB1((int)T11)] ^ SS2[GetB2((int)T11)] ^ SS3[GetB3((int)T11)]; } private static void EncRoundKeyUpdate1(int K[], int A[], int B[], int C[], int D[], int Z){ //int T0, T1; int T0; int T00, T11; T0 = C[0]; C[0] = (C[0]<<8) ^ (D[0]>>>24); D[0] = (D[0]<<8) ^ (T0>>>24); T00 = (int)A[0] + (int)C[0] - (int)KC[Z]; T11 = (int)B[0] + (int)KC[Z] - (int)D[0]; K[0] = SS0[GetB0((int)T00)] ^ SS1[GetB1((int)T00)] ^ SS2[GetB2((int)T00)] ^ SS3[GetB3((int)T00)]; K[1] = SS0[GetB0((int)T11)] ^ SS1[GetB1((int)T11)] ^ SS2[GetB2((int)T11)] ^ SS3[GetB3((int)T11)]; } /******************************** Key Schedule ********************************/ private static void SeedRoundKey( int pdwRoundKey[], // [out] round keys for encryption or decryption byte pbUserKey[]){ // [in] secret user key int A[] = new int[1]; int B[] = new int[1]; int C[] = new int[1]; int D[] = new int[1]; int K[] = new int[2]; int T0, T1; int nCount = 2; // Set up input values for Key Schedule A[0] = ((int)pbUserKey[0]&0x000000ff); A[0] = (A[0]<<8)^((int)pbUserKey[1]&0x000000ff); A[0] = (A[0]<<8)^((int)pbUserKey[2]&0x000000ff); A[0] = (A[0]<<8)^((int)pbUserKey[3]&0x000000ff); B[0] = ((int)pbUserKey[4]&0x000000ff); B[0] = (B[0]<<8)^((int)pbUserKey[5]&0x000000ff); B[0] = (B[0]<<8)^((int)pbUserKey[6]&0x000000ff); B[0] = (B[0]<<8)^((int)pbUserKey[7]&0x000000ff); C[0] = ((int)pbUserKey[8]&0x000000ff); C[0] = (C[0]<<8)^((int)pbUserKey[9]&0x000000ff); C[0] = (C[0]<<8)^((int)pbUserKey[10]&0x000000ff); C[0] = (C[0]<<8)^((int)pbUserKey[11]&0x000000ff); D[0] = ((int)pbUserKey[12]&0x000000ff); D[0] = (D[0]<<8)^((int)pbUserKey[13]&0x000000ff); D[0] = (D[0]<<8)^((int)pbUserKey[14]&0x000000ff); D[0] = (D[0]<<8)^((int)pbUserKey[15]&0x000000ff); // reorder for little endian if (!ENDIAN) {A[0]=EndianChange(A[0]); B[0]=EndianChange(B[0]); C[0]=EndianChange(C[0]); D[0]=EndianChange(D[0]);}; T0 = (int)A[0] + (int)C[0] - (int)KC[0]; T1 = (int)B[0] - (int)D[0] + (int)KC[0]; pdwRoundKey[0] = SS0[GetB0((int)T0)] ^ SS1[GetB1((int)T0)] ^ SS2[GetB2((int)T0)] ^ SS3[GetB3((int)T0)]; pdwRoundKey[1] = SS0[GetB0((int)T1)] ^ SS1[GetB1((int)T1)] ^ SS2[GetB2((int)T1)] ^ SS3[GetB3((int)T1)]; EncRoundKeyUpdate0(K, A, B, C, D, 1 ); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate1(K, A, B, C, D, 2 ); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate0(K, A, B, C, D, 3 ); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate1(K, A, B, C, D, 4 ); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate0(K, A, B, C, D, 5 ); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate1(K, A, B, C, D, 6 ); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate0(K, A, B, C, D, 7 ); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate1(K, A, B, C, D, 8 ); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate0(K, A, B, C, D, 9 ); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate1(K, A, B, C, D, 10); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate0(K, A, B, C, D, 11); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate1(K, A, B, C, D, 12); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate0(K, A, B, C, D, 13); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate1(K, A, B, C, D, 14); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; EncRoundKeyUpdate0(K, A, B, C, D, 15); pdwRoundKey[nCount++] = K[0]; pdwRoundKey[nCount++] = K[1]; } /****************************** 사용자 정의 함수 *******************************/ // 암호화 함수 public static String getPbCipher(String str){ padding(str); // 16 자가 되지 않으면 (byte)0x00 으로 채워준다. SeedEncrypt(pbData, pdwRoundKey, pbCipher); return toString(pbCipher); } // 복호화 함수 public static String getPbPlain(String str){ pbCipher = toByte(str); // String을 byte[]로 변환 SeedDecrypt(pbCipher, pdwRoundKey, pbPlain); return toString(pbPlain); } /************** 형변환 함수! * ( byte 값에 음수 값이 있어서 str.getBytes(), byte.toString()이 * 제데로 동작하지 않아서 만들어 준 함수 ) * ***************/ // Byte[]을 받아서 String 을 리턴한다. public static String toString(byte[] b){ StringBuffer sb = new StringBuffer(); for(int i=0; i pbData.length){ pbData = null; return; } for(int i=0; i