암호화 알고리즘

국산 블럭암호 ARIA 기술

긋대디 2016. 11. 17. 12:51

한국인터넷진흥원(KISA)에서는 국산 블럭암호 ARIA 기술을 개발 아래와 같이 보급하여 있으며 웹암호화 전송시 사용가능


□ 포함 국산암호 알고리즘
o 블록암호 알고리즘 : ARIA
o 블록암호 알고리즘 운영모드 : ECB, CBC, CTR, CFB-128, CFB-64, CFB-16, CFB-8, OFB-128, OFB-64, OFB-16, OFB-8

□ 첨부파일 소개
o 1. ARIA.zip
- Aria.java
- ARIA-reference-050117.c
- aria050117.c
- ARIA-specification.pdf
- ARIA-testvector.pdf


ARIA.zip



//

//  ARIA.java

//  

//  A pure Java implementation of ARIA 

//  following the official ARIA specification at

//  http://www.nsri.re.kr/ARIA/

//

//  

//  Created by Aaram Yun on 2005. 11. 30.

//  Copyright 2005 NSRI. All rights reserved.

//


package kr.re.nsri.aria;


import java.util.*;

import java.io.PrintStream;

import java.security.InvalidKeyException;


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 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);

  }

  

  /**

    * Resets the class so that it can be reused for another master key.

   */

  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);

    }

  }

  

  /**

    * Main bulk of the decryption key setup method.  Here we assume that

   * the int array rk already contains the encryption round keys.

   * @param mk the master key

   * @param rk the array which contains the encryption round keys at the

   * beginning of the method execution.  At the end of method execution

   * this will hold the decryption round keys.

   * @param keyBits the length of the master key

   * @return

   */

  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 ms(int t) {

  //    return TS1[(t>>>24)&0xff]^TS2[(t>>>16)&0xff]^TX1[(t>>>8)&0xff]^TX2[t&0xff];

  //  }

  //  private static final int mx(int t) {

  //    return TX1[(t>>>24)&0xff]^TX2[(t>>>16)&0xff]^TS1[(t>>>8)&0xff]^TS2[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 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 void ARIA_test() 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]=0;

    

    out.println("BEGIN testing the roundtrip...");

    out.println("For key size of 256 bits, starting with "+

                "the zero plaintext and the zero key, let's see if "+

                "we may recover the plaintext by decrypting the "+

                "encrypted ciphertext.");

    instance.setKey(mk);

    instance.setupRoundKeys();

    

    out.print("plaintext : "); printBlock(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 : "); printBlock(out, p); out.println();

    flag=false;

    for (int i=0; i<16; i++)

      if (p[i]!=0)

        flag=true;

    if (flag)

      out.println("The result is incorrect!");

    else

      out.println("Okay.  The result is correct.");

    out.println("END   testing the roundtrip.\n");

    

    int TEST_NUM = 0x800000;

    out.println("BEGIN speed measurement...");

    

    for (int i = 0; i < 16; i++) mk[i] = (byte)i;

    out.println("  First, EncKeySetup():");

    out.print("  masterkey: "); printBlock(out, mk); out.println();

    instance.reset(); instance.setKeySize(128);

    instance.setKey(mk);

    for (int i = 0 ; i < 1000; i++) instance.setupEncRoundKeys();  // allow the CPU to settle down

    Date start = new Date();

    for (int i=0; i< TEST_NUM; i++) instance.setupEncRoundKeys();

    Date fin = new Date();

    float lapse = (float)(fin.getTime()-start.getTime())/1000;

    out.print("  time lapsed: "); out.print(lapse); out.println(" sec.");

    out.print("  speed      : "); out.print(TEST_NUM*128/(lapse*1024*1024)); out.println(" megabits/sec.\n");

    

    out.println("  Next, Crypt():");

    for (int i = 0; i < 16; i++) p[i] = (byte) ((i << 4) ^ i);

    out.print("  plaintext : "); printBlock(out, p); out.println();

    for (int i=0; i<1000; i++) instance.encrypt(p, 0, c, 0);

    start = new Date();

    for (int i=0; i< TEST_NUM; i++) instance.encrypt(p, 0, c, 0);

    fin = new Date();

    out.print("  ciphertext: "); printBlock(out, c); out.println();

    lapse = (float)(fin.getTime()-start.getTime())/1000;    

    out.print("  time lapsed: "); out.print(lapse); out.println(" sec.");

    out.print("  speed      : "); out.print(TEST_NUM*128/(lapse*1024*1024)); out.println(" megabits/sec.\n");

    

    out.println("  Finally, DecKeySetup():");

    for (int i = 0 ; i < 1000; i++) instance.setupDecRoundKeys();  // allow the CPU to settle down

    start = new Date();

    for (int i=0; i< TEST_NUM; i++) instance.setupDecRoundKeys();

    fin = new Date();

    lapse = (float)(fin.getTime()-start.getTime())/1000;

    out.print("  time lapsed: "); out.print(lapse); out.println(" sec.");

    out.print("  speed      : "); out.print(TEST_NUM*128/(lapse*1024*1024)); out.println(" megabits/sec.");    

    out.println("END   speed measurement.");

  }

}


/*

 * Frontend class ARIA

 * Currently, it provides only a simple text.*/

 

public class ARIA {

  public static void main (String args[]) {

    try {

      ARIAEngine.ARIA_test();

    } catch(Exception e) {}

  }

}


'암호화 알고리즘' 카테고리의 다른 글

쉽게보는 ARIA 알고리즘 - 라운드  (0) 2018.12.26
(3-DES) 간단한 대칭 알고리즘 예제  (0) 2018.12.26
DES 알고리즘 C  (0) 2018.12.26
SHA1withRSA, SHA1withDSA 완성  (0) 2018.12.26
DB암호화 방식 비교  (0) 2018.12.26