/* * Copyright 2008-2009 MOPAS(Ministry of Public Administration and Security). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package egovframework.rte.fdl.crypto; import java.util.*; import java.io.*; import java.security.InvalidKeyException; import egovframework.rte.fdl.crypto.exception.UnsupportedException; class ARIAEngine { private static final char[] HEX_DIGITS = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; private static final int[][] KRK = { {0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0}, {0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0}, {0xdb92371d, 0x2126e970, 0x03249775, 0x04e8c90e} }; private static final byte[] S1 = new byte[256]; private static final byte[] S2 = new byte[256]; private static final byte[] X1 = new byte[256]; private static final byte[] X2 = new byte[256]; private static final int[] TS1 = new int[256]; private static final int[] TS2 = new int[256]; private static final int[] TX1 = new int[256]; private static final int[] TX2 = new int[256]; // Static initializer. For setting up the tables static { int[] exp = new int[256]; int[] log = new int[256]; exp[0] = 1; for (int i=1; i < 256; i++) { int j = (exp[i-1] << 1) ^ exp[i-1]; if ((j & 0x100) != 0) j ^= 0x11b; exp[i] = j; } for (int i=1; i < 255; i++) log[exp[i]] = i; int[][] A = { {1, 0, 0, 0, 1, 1, 1, 1}, {1, 1, 0, 0, 0, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 1, 1}, {1, 1, 1, 1, 0, 0, 0, 1}, {1, 1, 1, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 1, 1, 1, 1, 1} }; int[][] B = { {0, 1, 0, 1, 1, 1, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 1}, {1, 1, 0, 1, 0, 1, 1, 1}, {1, 0, 0, 1, 1, 1, 0, 1}, {0, 0, 1, 0, 1, 1, 0, 0}, {1, 0, 0, 0, 0, 0, 0, 1}, {0, 1, 0, 1, 1, 1, 0, 1}, {1, 1, 0, 1, 0, 0, 1, 1} }; for (int i=0; i<256; i++) { int t=0, p; if (i==0) p=0; else p=exp[255-log[i]]; for (int j=0; j<8; j++) { int s=0; for (int k=0; k<8; k++) { if (((p>>>(7-k))&0x01)!=0) s^=A[k][j]; } t=(t<<1)^s; } t^=0x63; S1[i]=(byte)t; X1[t]=(byte)i; } for (int i = 0; i < 256; i++) { int t = 0, p; if (i==0) p=0; else p=exp[(247*log[i])%255]; for (int j = 0; j < 8; j++) { int s = 0; for (int k = 0; k < 8; k++) { if (((p >>> k) & 0x01) != 0) s ^= B[7-j][k]; } t = (t << 1) ^ s; } t^=0xe2; S2[i] = (byte) t; X2[t] = (byte) i; } for (int i = 0; i < 256; i++) { TS1[i]=0x00010101*(S1[i]&0xff); TS2[i]=0x01000101*(S2[i]&0xff); TX1[i]=0x01010001*(X1[i]&0xff); TX2[i]=0x01010100*(X2[i]&0xff); } } private byte[] p_arr; static byte[] mk = new byte[32]; private int keySize=0; private int numberOfRounds=0; private byte[] masterKey=null; private int[] encRoundKeys=null, decRoundKeys=null; public ARIAEngine(int keySize) throws InvalidKeyException { setKeySize(keySize); } void reset() { this.keySize=0; this.numberOfRounds=0; this.masterKey=null; this.encRoundKeys=null; this.decRoundKeys=null; } int getKeySize() { return this.keySize; } void setKeySize(int keySize) throws InvalidKeyException { this.reset(); if (keySize!=128 && keySize!=192 && keySize!=256) throw new InvalidKeyException("keySize="+keySize); this.keySize = keySize; switch (keySize) { case 128: this.numberOfRounds = 12; break; case 192: this.numberOfRounds = 14; break; case 256: this.numberOfRounds = 16; } } void setKey(byte[] masterKey) throws InvalidKeyException { if (masterKey.length*8<keySize) throw new InvalidKeyException("masterKey size="+masterKey.length); this.decRoundKeys = null; this.encRoundKeys = null; this.masterKey = (byte[])masterKey.clone(); } void setupEncRoundKeys() throws InvalidKeyException { if (this.keySize==0) throw new InvalidKeyException("keySize"); if (this.masterKey==null) throw new InvalidKeyException("masterKey"); if (this.encRoundKeys==null) this.encRoundKeys = new int[4*(this.numberOfRounds+1)]; this.decRoundKeys = null; doEncKeySetup(this.masterKey, this.encRoundKeys, this.keySize); } void setupDecRoundKeys() throws InvalidKeyException { if (this.keySize==0) throw new InvalidKeyException("keySize"); if (this.encRoundKeys==null) if (this.masterKey==null) throw new InvalidKeyException("masterKey"); else setupEncRoundKeys(); this.decRoundKeys = (int[])encRoundKeys.clone(); doDecKeySetup(this.masterKey, this.decRoundKeys, this.keySize); } void setupRoundKeys() throws InvalidKeyException { setupDecRoundKeys(); } private static void doCrypt(byte[] i, int ioffset, int[] rk, int nr, byte[] o, int ooffset) { int t0, t1, t2, t3, j=0; t0 = toInt(i[ 0+ioffset], i[ 1+ioffset], i[ 2+ioffset], i[ 3+ioffset]); t1 = toInt(i[ 4+ioffset], i[ 5+ioffset], i[ 6+ioffset], i[ 7+ioffset]); t2 = toInt(i[ 8+ioffset], i[ 9+ioffset], i[10+ioffset], i[11+ioffset]); t3 = toInt(i[12+ioffset], i[13+ioffset], i[14+ioffset], i[15+ioffset]); for (int r=1; r<nr/2; r++) { t0^=rk[j++]; t1^=rk[j++]; t2^=rk[j++]; t3^=rk[j++]; t0=TS1[(t0>>>24)&0xff]^TS2[(t0>>>16)&0xff]^TX1[(t0>>>8)&0xff]^TX2[t0&0xff]; t1=TS1[(t1>>>24)&0xff]^TS2[(t1>>>16)&0xff]^TX1[(t1>>>8)&0xff]^TX2[t1&0xff]; t2=TS1[(t2>>>24)&0xff]^TS2[(t2>>>16)&0xff]^TX1[(t2>>>8)&0xff]^TX2[t2&0xff]; t3=TS1[(t3>>>24)&0xff]^TS2[(t3>>>16)&0xff]^TX1[(t3>>>8)&0xff]^TX2[t3&0xff]; t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t1=badc(t1); t2=cdab(t2); t3=dcba(t3); t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t0^=rk[j++]; t1^=rk[j++]; t2^=rk[j++]; t3^=rk[j++]; t0=TX1[(t0>>>24)&0xff]^TX2[(t0>>>16)&0xff]^TS1[(t0>>>8)&0xff]^TS2[t0&0xff]; t1=TX1[(t1>>>24)&0xff]^TX2[(t1>>>16)&0xff]^TS1[(t1>>>8)&0xff]^TS2[t1&0xff]; t2=TX1[(t2>>>24)&0xff]^TX2[(t2>>>16)&0xff]^TS1[(t2>>>8)&0xff]^TS2[t2&0xff]; t3=TX1[(t3>>>24)&0xff]^TX2[(t3>>>16)&0xff]^TS1[(t3>>>8)&0xff]^TS2[t3&0xff]; t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t3=badc(t3); t0=cdab(t0); t1=dcba(t1); t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; } t0^=rk[j++]; t1^=rk[j++]; t2^=rk[j++]; t3^=rk[j++]; t0=TS1[(t0>>>24)&0xff]^TS2[(t0>>>16)&0xff]^TX1[(t0>>>8)&0xff]^TX2[t0&0xff]; t1=TS1[(t1>>>24)&0xff]^TS2[(t1>>>16)&0xff]^TX1[(t1>>>8)&0xff]^TX2[t1&0xff]; t2=TS1[(t2>>>24)&0xff]^TS2[(t2>>>16)&0xff]^TX1[(t2>>>8)&0xff]^TX2[t2&0xff]; t3=TS1[(t3>>>24)&0xff]^TS2[(t3>>>16)&0xff]^TX1[(t3>>>8)&0xff]^TX2[t3&0xff]; t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t1=badc(t1); t2=cdab(t2); t3=dcba(t3); t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t0^=rk[j++]; t1^=rk[j++]; t2^=rk[j++]; t3^=rk[j++]; o[ 0+ooffset] = (byte)(X1[0xff&(t0>>>24)] ^ (rk[j ]>>>24)); o[ 1+ooffset] = (byte)(X2[0xff&(t0>>>16)] ^ (rk[j ]>>>16)); o[ 2+ooffset] = (byte)(S1[0xff&(t0>>> 8)] ^ (rk[j ]>>> 8)); o[ 3+ooffset] = (byte)(S2[0xff&(t0 )] ^ (rk[j ] )); o[ 4+ooffset] = (byte)(X1[0xff&(t1>>>24)] ^ (rk[j+1]>>>24)); o[ 5+ooffset] = (byte)(X2[0xff&(t1>>>16)] ^ (rk[j+1]>>>16)); o[ 6+ooffset] = (byte)(S1[0xff&(t1>>> 8)] ^ (rk[j+1]>>> 8)); o[ 7+ooffset] = (byte)(S2[0xff&(t1 )] ^ (rk[j+1] )); o[ 8+ooffset] = (byte)(X1[0xff&(t2>>>24)] ^ (rk[j+2]>>>24)); o[ 9+ooffset] = (byte)(X2[0xff&(t2>>>16)] ^ (rk[j+2]>>>16)); o[10+ooffset] = (byte)(S1[0xff&(t2>>> 8)] ^ (rk[j+2]>>> 8)); o[11+ooffset] = (byte)(S2[0xff&(t2 )] ^ (rk[j+2] )); o[12+ooffset] = (byte)(X1[0xff&(t3>>>24)] ^ (rk[j+3]>>>24)); o[13+ooffset] = (byte)(X2[0xff&(t3>>>16)] ^ (rk[j+3]>>>16)); o[14+ooffset] = (byte)(S1[0xff&(t3>>> 8)] ^ (rk[j+3]>>> 8)); o[15+ooffset] = (byte)(S2[0xff&(t3 )] ^ (rk[j+3] )); } void encrypt(byte[] i, int ioffset, byte[] o, int ooffset) throws InvalidKeyException { if (this.keySize==0) throw new InvalidKeyException("keySize"); if (this.encRoundKeys==null) if (this.masterKey==null) throw new InvalidKeyException("masterKey"); else setupEncRoundKeys(); doCrypt(i, ioffset, this.encRoundKeys, this.numberOfRounds, o, ooffset); } byte[] encrypt(byte[] i, int ioffset) throws InvalidKeyException { byte[] o = new byte[16]; this.encrypt(i, ioffset, o, 0); return o; } void decrypt(byte[] i, int ioffset, byte[] o, int ooffset) throws InvalidKeyException { if (this.keySize==0) throw new InvalidKeyException("keySize"); if (this.decRoundKeys==null) if (this.masterKey==null) throw new InvalidKeyException("masterKey"); else setupDecRoundKeys(); doCrypt(i, ioffset, this.decRoundKeys, this.numberOfRounds, o, ooffset); } byte[] decrypt(byte[] i, int ioffset) throws InvalidKeyException { byte[] o = new byte[16]; this.decrypt(i, ioffset, o, 0); return o; } private static void doEncKeySetup(byte[] mk, int[] rk, int keyBits) { int t0, t1, t2, t3, q, j=0; int[] w0 = new int[4]; int[] w1 = new int[4]; int[] w2 = new int[4]; int[] w3 = new int[4]; w0[0] = toInt(mk[ 0], mk[ 1], mk[ 2], mk[ 3]); w0[1] = toInt(mk[ 4], mk[ 5], mk[ 6], mk[ 7]); w0[2] = toInt(mk[ 8], mk[ 9], mk[10], mk[11]); w0[3] = toInt(mk[12], mk[13], mk[14], mk[15]); q = (keyBits - 128) / 64; t0=w0[0]^KRK[q][0]; t1=w0[1]^KRK[q][1]; t2=w0[2]^KRK[q][2]; t3=w0[3]^KRK[q][3]; t0=TS1[(t0>>>24)&0xff]^TS2[(t0>>>16)&0xff]^TX1[(t0>>>8)&0xff]^TX2[t0&0xff]; t1=TS1[(t1>>>24)&0xff]^TS2[(t1>>>16)&0xff]^TX1[(t1>>>8)&0xff]^TX2[t1&0xff]; t2=TS1[(t2>>>24)&0xff]^TS2[(t2>>>16)&0xff]^TX1[(t2>>>8)&0xff]^TX2[t2&0xff]; t3=TS1[(t3>>>24)&0xff]^TS2[(t3>>>16)&0xff]^TX1[(t3>>>8)&0xff]^TX2[t3&0xff]; t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t1=badc(t1); t2=cdab(t2); t3=dcba(t3); t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; if (keyBits > 128) { w1[0] = toInt(mk[16], mk[17], mk[18], mk[19]); w1[1] = toInt(mk[20], mk[21], mk[22], mk[23]); if (keyBits > 192) { w1[2] = toInt(mk[24], mk[25], mk[26], mk[27]); w1[3] = toInt(mk[28], mk[29], mk[30], mk[31]); } else { w1[2]=w1[3]=0; } } else { w1[0]=w1[1]=w1[2]=w1[3]=0; } w1[0]^=t0; w1[1]^=t1; w1[2]^=t2; w1[3]^=t3; t0=w1[0]; t1=w1[1]; t2=w1[2]; t3=w1[3]; q = (q==2)? 0 : (q+1); t0^=KRK[q][0]; t1^=KRK[q][1]; t2^=KRK[q][2]; t3^=KRK[q][3]; t0=TX1[(t0>>>24)&0xff]^TX2[(t0>>>16)&0xff]^TS1[(t0>>>8)&0xff]^TS2[t0&0xff]; t1=TX1[(t1>>>24)&0xff]^TX2[(t1>>>16)&0xff]^TS1[(t1>>>8)&0xff]^TS2[t1&0xff]; t2=TX1[(t2>>>24)&0xff]^TX2[(t2>>>16)&0xff]^TS1[(t2>>>8)&0xff]^TS2[t2&0xff]; t3=TX1[(t3>>>24)&0xff]^TX2[(t3>>>16)&0xff]^TS1[(t3>>>8)&0xff]^TS2[t3&0xff]; t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t3=badc(t3); t0=cdab(t0); t1=dcba(t1); t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t0^=w0[0]; t1^=w0[1]; t2^=w0[2]; t3^=w0[3]; w2[0]=t0; w2[1]=t1; w2[2]=t2; w2[3]=t3; q = (q==2)? 0 : (q+1); t0^=KRK[q][0]; t1^=KRK[q][1]; t2^=KRK[q][2]; t3^=KRK[q][3]; t0=TS1[(t0>>>24)&0xff]^TS2[(t0>>>16)&0xff]^TX1[(t0>>>8)&0xff]^TX2[t0&0xff]; t1=TS1[(t1>>>24)&0xff]^TS2[(t1>>>16)&0xff]^TX1[(t1>>>8)&0xff]^TX2[t1&0xff]; t2=TS1[(t2>>>24)&0xff]^TS2[(t2>>>16)&0xff]^TX1[(t2>>>8)&0xff]^TX2[t2&0xff]; t3=TS1[(t3>>>24)&0xff]^TS2[(t3>>>16)&0xff]^TX1[(t3>>>8)&0xff]^TX2[t3&0xff]; t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t1=badc(t1); t2=cdab(t2); t3=dcba(t3); t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; w3[0]=t0^w1[0]; w3[1]=t1^w1[1]; w3[2]=t2^w1[2]; w3[3]=t3^w1[3]; gsrk(w0, w1, 19, rk, j); j+=4; gsrk(w1, w2, 19, rk, j); j+=4; gsrk(w2, w3, 19, rk, j); j+=4; gsrk(w3, w0, 19, rk, j); j+=4; gsrk(w0, w1, 31, rk, j); j+=4; gsrk(w1, w2, 31, rk, j); j+=4; gsrk(w2, w3, 31, rk, j); j+=4; gsrk(w3, w0, 31, rk, j); j+=4; gsrk(w0, w1, 67, rk, j); j+=4; gsrk(w1, w2, 67, rk, j); j+=4; gsrk(w2, w3, 67, rk, j); j+=4; gsrk(w3, w0, 67, rk, j); j+=4; gsrk(w0, w1, 97, rk, j); j+=4; if (keyBits > 128) { gsrk(w1, w2, 97, rk, j); j+=4; gsrk(w2, w3, 97, rk, j); j+=4; } if (keyBits > 192) { gsrk(w3, w0, 97, rk, j); j+=4; gsrk(w0, w1, 109, rk, j); } } private static void doDecKeySetup(byte[] mk, int[] rk, int keyBits) { int a=0, z; int[] t = new int[4]; z=32+keyBits/8; swapBlocks(rk, 0, z); a+=4; z-=4; for (; a<z; a+=4, z-=4) swapAndDiffuse(rk, a, z, t); diff(rk, a, t, 0); rk[a]=t[0]; rk[a+1]=t[1]; rk[a+2]=t[2]; rk[a+3]=t[3]; } private static int toInt(byte b0, byte b1, byte b2, byte b3) { return (b0&0xff)<<24 ^ (b1&0xff)<<16 ^ (b2&0xff)<<8 ^ b3&0xff; } private static void toByteArray(int i, byte[] b, int offset) { b[offset ] = (byte)(i>>>24); b[offset+1] = (byte)(i>>>16); b[offset+2] = (byte)(i>>> 8); b[offset+3] = (byte)(i ); } private static int m(int t) { return 0x00010101*((t>>>24)&0xff) ^ 0x01000101*((t>>>16)&0xff) ^ 0x01010001*((t>>>8)&0xff) ^ 0x01010100*(t&0xff); } private static final int badc(int t) { return ((t<<8)&0xff00ff00) ^ ((t>>>8)&0x00ff00ff); } private static final int cdab(int t) { return ((t<<16)&0xffff0000) ^ ((t>>>16)&0x0000ffff); } private static final int dcba(int t) { return (t&0x000000ff)<<24 ^ (t&0x0000ff00)<<8 ^ (t&0x00ff0000)>>>8 ^ (t&0xff000000)>>>24; } private static final void gsrk(int[] x, int[] y, int rot, int[] rk, int offset) { int q=4-(rot/32), r=rot%32, s=32-r; rk[offset] = x[0] ^ y[(q )%4]>>>r ^ y[(q+3)%4]<<s; rk[offset+1] = x[1] ^ y[(q+1)%4]>>>r ^ y[(q )%4]<<s; rk[offset+2] = x[2] ^ y[(q+2)%4]>>>r ^ y[(q+1)%4]<<s; rk[offset+3] = x[3] ^ y[(q+3)%4]>>>r ^ y[(q+2)%4]<<s; } private static final void diff(int[] i, int offset1, int[] o, int offset2) { int t0, t1, t2, t3; t0=m(i[offset1]); t1=m(i[offset1+1]); t2=m(i[offset1+2]); t3=m(i[offset1+3]); t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; t1=badc(t1); t2=cdab(t2); t3=dcba(t3); t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; o[offset2]=t0; o[offset2+1]=t1; o[offset2+2]=t2; o[offset2+3]=t3; } private static final void swapBlocks(int[] arr, int offset1, int offset2) { int t; for (int i=0; i<4; i++) { t = arr[offset1+i]; arr[offset1+i] = arr[offset2+i]; arr[offset2+i] = t; } } private static final void swapAndDiffuse(int[] arr, int offset1, int offset2, int[] tmp) { diff(arr, offset1, tmp, 0); diff(arr, offset2, arr, offset1); arr[offset2]=tmp[0]; arr[offset2+1]=tmp[1]; arr[offset2+2]=tmp[2]; arr[offset2+3]=tmp[3]; } private static void printBlock(PrintStream out, byte[] b) { for (int i=0; i<4; i++) byteToHex(out, b[i]); out.print(" "); for (int i=4; i<8; i++) byteToHex(out, b[i]); out.print(" "); for (int i=8; i<12; i++) byteToHex(out, b[i]); out.print(" "); for (int i=12; i<16; i++) byteToHex(out, b[i]); } private static void printEn_Decrypt(PrintStream out, byte[] b) { out.print(new String(b)); } private static void printSBox(PrintStream out, byte[] box) { for (int i=0; i<16; i++) { for (int j=0; j<16; j++) { byteToHex(out, box[16*i+j]); out.print(" "); } out.println(); } } private static void byteToHex(PrintStream out, byte b) { char[] buf = { HEX_DIGITS[(b >>> 4) & 0x0F], HEX_DIGITS[ b & 0x0F] }; out.print(new String(buf)); } private static void intToHex(PrintStream out, int i) { byte[] b = new byte[4]; toByteArray(i, b, 0); byteToHex(out, b[0]); byteToHex(out, b[1]); byteToHex(out, b[2]); byteToHex(out, b[3]); } private static void printRoundKeys(PrintStream out, int[] roundKeys) { for (int i=0; i<roundKeys.length; ) { out.print("* "); intToHex(out, roundKeys[i++]); out.print(" "); intToHex(out, roundKeys[i++]); out.print(" "); intToHex(out, roundKeys[i++]); out.print(" "); intToHex(out, roundKeys[i++]); out.print(" \n"); } } public static byte[] ARIA_test(byte[] param) throws InvalidKeyException { byte[] p = new byte[16]; byte[] c = new byte[16]; byte[] mk = new byte[32]; boolean flag=false; PrintStream out=System.out; ARIAEngine instance = new ARIAEngine(256); for (int i=0; i<32; i++) mk[i]=0; for (int i=0; i<16; i++) p[i]=param[i]; instance.setKey(mk); instance.setupRoundKeys(); out.print("plaintext : "); printEn_Decrypt(out, p); out.println(); instance.encrypt(p, 0, c, 0); out.print("ciphertext: "); printBlock(out, c); out.println(); instance.decrypt(c, 0, p, 0); out.print("decrypted : "); printEn_Decrypt(out, p); out.println(); return p; } public static void setMK(byte[] mk1) { for (int i=0; i<32; i++) mk[i]=0; for (int rr=0 ; rr < mk1.length ; rr++) mk[rr]=mk1[rr]; } public static byte[] Encrypt(byte[] param) throws InvalidKeyException { byte[] p = new byte[16]; byte[] c = new byte[16]; //byte[] mk = new byte[32]; boolean flag=false; PrintStream out=System.out; ARIAEngine instance = new ARIAEngine(256); // for (int i=0; i<32; i++) // mk[i]=0; for (int i=0; i<16; i++) p[i]=param[i]; instance.setKey(mk); instance.setupRoundKeys(); instance.encrypt(p, 0, c, 0); out.print("ciphertext : "); printEn_Decrypt(out, c); out.println(); return c; } public static byte[] Decrypt(byte[] param) throws InvalidKeyException { byte[] p = new byte[16]; byte[] c = new byte[16]; //byte[] mk = new byte[32]; boolean flag=false; PrintStream out=System.out; ARIAEngine instance = new ARIAEngine(256); //for (int i=0; i<32; i++) // mk[i]=0; for (int i=0; i<16; i++) c[i]=param[i]; instance.setKey(mk); instance.setupRoundKeys(); instance.decrypt(c, 0, p, 0); out.print("decrypted : "); printEn_Decrypt(out, p); out.println(); return p; } } /** * ARIA 암호화 모듈를 이용할 수 있도록 기능 제공 * @author 개발프레임웍크 실행환경 개발팀 김종호 * @since 2009. 03.10 * @version 1.0 * @see <pre> * == 개정이력(Modification Information) == * * 수정일 수정자 수정내용 * --------- --------- ------------------------------- * 2009.03.10 김종호 최초생성 * 2010.11.23 한성곤 ARIA 알고리즘의 마스터키 크기가 32 byte 이상인 경우 오류 수정 * * </pre> */ public class EgovCipherService { /** 마스터 키 */ String mk_str = null; /** * 암호 설정 * @param mk_str 암호문자열 */ public void setPassword(String mk_str) { //------------------------------------- // 2010-11-23 //------------------------------------- mk_str = (mk_str.length() > 32 ? mk_str.substring(0, 32) : mk_str); ////----------------------------------- this.mk_str = mk_str; ARIAEngine.setMK(mk_str.getBytes()); } /** * 바이트 배열 리턴 암호화 * @param enString 암호화할 문자열 * @return 암호화된 바이트배열 */ public byte[] encrypt(String enString) { String pp = enString; byte[] rtn_byte = null; byte[] cipher = null; byte[] pp_arr = pp.getBytes(); int a_1 = pp_arr.length/16; int a_2 = pp_arr.length%16; int a_3 = 16 - a_2; byte[] a_tmp = null; if(a_2 != 0) a_tmp = new byte[pp_arr.length+a_3]; else a_tmp = new byte[pp_arr.length]; for(int q=0; q< a_tmp.length; q++) a_tmp[q]=0; for(int io=0; io< pp_arr.length; io++) a_tmp[io] = pp_arr[io]; if(a_2 > 0) a_1 +=1; byte[][] yu = new byte[a_1][16]; int gh=0; int jh=0; for(int y=0; y<a_tmp.length ; y++) { yu[gh][jh] = a_tmp[y]; jh++; if((y+1)%16 == 0) { gh++; jh = 0; } } try { byte[] p_tmp = new byte[a_tmp.length]; byte[] p_tmp_ = new byte[16]; int po = 0; for(int tt=0; tt<a_1; tt++) { byte[] tmp = yu[tt]; cipher = ARIAEngine.Encrypt(tmp); for(int y=0; y<cipher.length ; y++) { p_tmp[po] = cipher[y]; po++; } } rtn_byte = p_tmp; } catch(Exception e) {e.printStackTrace();} return rtn_byte; } /** * 바이트 배열 리턴 암호화 * @param bytearr 암호화할 바이트배열 * @return 암호화된 바이트배열 */ public byte[] encrypt(byte[] bytearr) { byte[] rtn_byte = null; byte[] cipher = null; byte[] pp_arr = bytearr; int a_1 = pp_arr.length/16; int a_2 = pp_arr.length%16; int a_3 = 16 - a_2; byte[] a_tmp = null; if(a_2 != 0) a_tmp = new byte[pp_arr.length+a_3]; else a_tmp = new byte[pp_arr.length]; for(int q=0; q< a_tmp.length; q++) a_tmp[q]=0; for(int io=0; io< pp_arr.length; io++) a_tmp[io] = pp_arr[io]; if(a_2 > 0) a_1 +=1; byte[][] yu = new byte[a_1][16]; int gh=0; int jh=0; for(int y=0; y<a_tmp.length ; y++) { yu[gh][jh] = a_tmp[y]; jh++; if((y+1)%16 == 0) { gh++; jh = 0; } } try { byte[] p_tmp = new byte[a_tmp.length]; byte[] p_tmp_ = new byte[16]; int po = 0; for(int tt=0; tt<a_1; tt++) { byte[] tmp = yu[tt]; cipher = ARIAEngine.Encrypt(tmp); for(int y=0; y<cipher.length ; y++) { p_tmp[po] = cipher[y]; po++; } } rtn_byte = p_tmp; } catch(Exception e) {e.printStackTrace();} return rtn_byte; } /** * 복호화 배열 리턴 암호화 * @param deString 복호화할 데이타 바이트배열 * @return 복호화된 바이트배열 */ public byte[] decrypt(byte[] deString) { String rtn_str = ""; byte[] cipher = null; byte[] rtn_arr = null; byte[] pp_arr = deString; int a_1 = pp_arr.length/16; int a_2 = pp_arr.length%16; int a_3 = 16 - a_2; byte[] a_tmp = null; int gcount = 0; if(a_2 != 0) a_tmp = new byte[pp_arr.length+a_3]; else a_tmp = new byte[pp_arr.length]; for(int q=0; q< a_tmp.length; q++) a_tmp[q]=0; for(int io=0; io< pp_arr.length; io++) a_tmp[io] = pp_arr[io]; if(a_2 > 0) a_1 +=1; byte[][] yu = new byte[a_1][16]; int gh=0; int jh=0; for(int y=0; y<a_tmp.length ; y++) { yu[gh][jh] = a_tmp[y]; jh++; if((y+1)%16 == 0) { gh++; jh = 0; } } try { byte[] p_tmp = new byte[a_tmp.length]; byte[] p_tmp_ = new byte[16]; int po = 0; for(int tt=0; tt<a_1; tt++) { byte[] tmp = yu[tt]; p_tmp_ = ARIAEngine.Decrypt(tmp); for(int y=0; y<p_tmp_.length ; y++) { p_tmp[po] = p_tmp_[y]; if(tt == (a_1-1) && p_tmp[po]==0 ) { gcount++; } po++; } } rtn_arr = new byte[p_tmp.length-gcount]; for(int qq=0; qq < rtn_arr.length; qq++) rtn_arr[qq] = p_tmp[qq]; } catch(Exception e) {e.printStackTrace();} return rtn_arr; } }