안드로이드에서 IV와 함께 쓰는 Rijndael 256 암호/복호화 안드로이드 노트


이거 참 큰 작업은 아니지만 문서도 얼마 없고 골치아파서....

AES-256과 다름이 없다 라고 하는 사람도 있는 모양인데, 저언혀 그렇지가 않더라. AES나 SHA는 자바와 아파치 정도 선에서 대응이 가능하지만 Rijndael은 따로 라이브러리가 필요하다.

자바에서는 BouncyCastle이라는 라이브러리를 이용하지만, 안드로이드에서 쓰라고 만든 것은 아닌지라 라이브러리 적용에 귀찮은 부분이 꽤 있어서 SpongyCastle이라는 것까지 만들어져 있다.

여기에서 JAR를 다운받고 다른 JAR와 다름 없이 dependency 적용을 시켜주면 됨.

그리고 아래 클래스만 만들어 주면 편리하게 써먹을 수 있다.

import org.spongycastle.crypto.CipherParameters;
import org.spongycastle.crypto.engines.RijndaelEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.paddings.ZeroBytePadding;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import org.spongycastle.util.encoders.Base64;

import java.nio.charset.Charset;
import java.security.Security;

public class RijndaelCrypto {

private static final String KEY = "0123456789zxcv0123456789zxcv0123"; // 256비트이므로 32바이트 문자열이 필요

private static final String IV = "0123456789abcd0123456789abcd0123"; // 256비트이므로 32바이트 문자열이 필요

static {
Security.insertProviderAt( new org.spongycastle.jce.provider.BouncyCastleProvider(), 1 );
}

public static String getEncrypted( String data ) {
try {
RijndaelEngine rijndael = new RijndaelEngine( 256 ); // Rijndael 128이라면 blockbits를 주지 않으면 됨
CBCBlockCipher cbc_rijndael = new CBCBlockCipher( rijndael );
ZeroBytePadding c = new ZeroBytePadding();
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher( cbc_rijndael, c );
CipherParameters keyWithIV = new ParametersWithIV( new KeyParameter( KEY.getBytes() ), IV.getBytes() );
cipher.init( true, keyWithIV );
byte[] plaintext = data.getBytes( Charset.forName( "UTF-8" ) );
byte[] ciphertext = new byte[cipher.getOutputSize( plaintext.length )];
int offset = 0;
offset += cipher.processBytes( plaintext, 0, plaintext.length, ciphertext, offset );
cipher.doFinal( ciphertext, offset );
String new_text = new String( new Base64().encode( ciphertext ), Charset.forName( "UTF-8" ) );
return new_text;
} catch ( Exception e ) {
e.printStackTrace();
return "error";
}
}

public static String getDecrypted( String data ) {
try {
byte[] ciphertext = Base64.decode( data.trim() );
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher( new CBCBlockCipher( new RijndaelEngine( 256 ) ), new ZeroBytePadding() );
CipherParameters ivAndKey = new ParametersWithIV( new KeyParameter( KEY.getBytes() ), IV.getBytes() );
cipher.init( false, ivAndKey );
int minSize = cipher.getOutputSize( ciphertext.length );
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes( ciphertext, 0, ciphertext.length, outBuf, 0 );
int length2 = cipher.doFinal( outBuf, length1 );
int actualLength = length1 + length2;
byte[] cipherArray = new byte[actualLength];
for ( int x = 0; x < actualLength; x++ ) {
cipherArray[x] = outBuf[x];
}
return new String( cipherArray );
} catch ( Exception e ) {
e.printStackTrace();
return "error";
}
}
}

key와 iv는 자릿수만 맞춰서 합의된 값을 지정해 준다. 안드로이드하고 데이터 주고받을 데라봐야 php나 jsp인데 거기는 잘 돼 있으니까 서버 담당자만 잘 해 주면 별 문제 없다.

덧글

댓글 입력 영역