2011년 6월 13일 월요일

자바을 이용한 암호학(자바보안 개정판:대칭키) - 4

Chapter 2 SymetricKey(대칭키)


PLT 2.1 대칭키 ?
대칭키 방식은 어떤 키로 암호화한 것은 같은 키로 복호화 할수 있는 방식이다. 같은 키를 사용하기 때문 복호화는 암호화 과정의 역으로 해석할 수 있다. 대칭 키 알고리즘은 비대칭 키 알고리즘보다 훨씬 빠른 경향이 있다. 게다가 비대칭키 암호화는 암호화될 수 있는 텍스트의 사이즈가 공개 키와 비밀 키를 생성할 때 사용되었던 두 개의 소인수 곱의 크기에 의해 좌우된다. 하지만 대칭 키 알고리즘을 사용하면 암호화하고자 하는 대상의 전체 크기에 전혀 제한을 받지 않는다. 대칭 암호 알고리즘(symmetric cipher algorithms)의 종류에 따라 다르지만, 전제 입력 사이즈는 블록 사이즈의 배수여야하고 패딩(padding)이 요구될 수도 있다. 대칭 키와 관련한 문제는 이 키들이 암호화나 복호화에 관련된 파티내에서는 공유되어야만 한다는 데에 있다. 그렇기 때문에 차단이 되거나 공인되지 않은 사용자가 공유하는 등의 문제가 생길 수 있다.
Padding : 데이터를 일정크기(64비트)로 나눈 후 마지막 불완전한 블록을 보정하는 것 일반적으로 PKCS#5를 일반적으로 사용한다.


PLT 2.2 대칭키 생성
package com.crypto;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.KeyGenerator;
public class CryptoKeyBuilder{
/**
* Main 메서드
* @param args 생성파일명
* @exception Exception
*/
public static void main(String[] args)
throws Exception
{
if(args.length < 1)
{
System.out.println("사용예 : java com.crypto.CryptoKeyBuilder [fileName]");
return;
}
for(int i=0; i<args.length; i++) {
KeyGenerator generator = KeyGenerator.getInstance("DES");
generator.init(new SecureRandom());
Key key = generator.generateKey();
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream(
new File(".",args[i])));
out.writeObject(key);
out.close();
}
}
}


대칭키 생성
KeyGenerator generator = KeyGenerator.getInstance("DES");
generator.init(new SecureRandom());
Key key = generator.generateKey();
위 코드부분은 DES 알고리즘을 사용하여 대칭키을 생성하는 부분이다. 알고리즘은 DES, DESede, PBEWithMD5AndDES 을 사용할 수 있다.

PLT 2.3 대칭키 암호화 복호화
package com.crypto;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class Crypto{
/**
* 파일암호화에 쓰이는 버퍼 크기 지정
*/
public static final int kBufferSize = 8192;
/**
* 지정된 비밀키를 가지고 오는 메서드
* @return Key 비밀키 클래스
* @exception Exception
*/
private static Key getKey()
throws Exception{
String FileURL = "SymetricKey.key";
Key key;
ObjectInputStream in = new ObjectInputStream(new FileInputStream(FileURL));
key = (Key)in.readObject();
in.close();
return key;
}
/**
* 문자열 대칭 암호화
* @param ID 비밀키 암호화를 희망하는 문자열
* @return String 암호화된 ID
* @exception Exception
*/
public static String encrypt(String ID)
throws Exception{
if ( ID == null || ID.length() == 0 ) return "";
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,getKey());
String amalgam = ID;
byte[] inputBytes1 = amalgam.getBytes("UTF8");
byte[] outputBytes1 = cipher.doFinal(inputBytes1);
BASE64Encoder encoder = new BASE64Encoder();
String outputStr1 = encoder.encode(outputBytes1);
return outputStr1;
}
/**
* 문자열 대칭 복호화
* @param codedID 비밀키 복호화를 희망하는 문자열
* @return String 복호화된 ID
* @exception Exception
*/
public static String decrypt(String codedID)
throws Exception{
if ( codedID == null || codedID.length() == 0 ) return "";
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, getKey());
BASE64Decoder decoder = new BASE64Decoder();
byte[] inputBytes1 = decoder.decodeBuffer(codedID);
byte[] outputBytes2 = cipher.doFinal(inputBytes1);
String strResult = new String(outputBytes2,"UTF8");
return strResult;
}
/**
* 파일 대칭 암호화
* @param infile 암호화을 희망하는 파일명
* @param outfile 암호화된 파일명
* @exception Exception
*/
public static void encryptFile(String infile, String outfile)
throws Exception{
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,getKey());
FileInputStream in = new FileInputStream(infile);
FileOutputStream fileOut = new FileOutputStream(outfile);
CipherOutputStream out = new CipherOutputStream(fileOut, cipher);
byte[] buffer = new byte[kBufferSize];
int length;
while((length = in.read(buffer)) != -1)
out.write(buffer,0,length);
in.close();
out.close();
}
/**
* 파일 대칭 복호화
* @param infile 복호화을 희망하는 파일명
* @param outfile 복호화된 파일명
* @exception Exception
*/
public static void decryptFile(String infile, String outfile)
throws Exception{
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE,getKey());
FileInputStream in = new FileInputStream(infile);
FileOutputStream fileOut = new FileOutputStream(outfile);
CipherOutputStream out = new CipherOutputStream(fileOut, cipher);
byte[] buffer = new byte[kBufferSize];
int length;
while((length = in.read(buffer)) != -1)
out.write(buffer,0,length);
in.close();
out.close();
}
public static void main(String[] ars)
throws Exception {
if(ars.length < 2) {
System.out.println("USE : java com.crypto.Crypto [-d | -e | -fd | -fe] [text | inputfilename outputfilename]");
System.exit(0);
}
if(ars[0].equals("-d"))
System.out.println(Crypto.decrypt(ars[1]));
if(ars[0].equals("-e"))
System.out.println(Crypto.encrypt(ars[1]));
if(ars[0].equals("-fd"))
Crypto.decryptFile(ars[1], ars[2]);
if(ars[0].equals("-fe"))
Crypto.encryptFile(ars[1], ars[2]);
}
}


String FileURL = "SymetricKey.key";
Key key;
ObjectInputStream in = new ObjectInputStream(new FileInputStream(FileURL));
key = (Key)in.readObject();

위 코드는 대칭키 생성기에서 생성된 키를 로딩하는 부분이다. SymetricKey.key 파일이름은 해당 파일이름으로 변경해준다.

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,getKey());
위 코드는 암호화, 복호화 객체(Cipher)을 생성하는 부분이다. “DES/ECB/PKCS5Padding”은 “알고리즘/모드/패딩” 속성이다. 각 속성의 종류나 세부적인 내용은 JCERefGuide을 참조하길 바란다.
ENCRYPT_MODE, DECRYPT_MODE은 암호호, 복호화를 나타낸다.

BASE64Encoder encoder = new BASE64Encoder();
String outputStr1 = encoder.encode(outputBytes1);
암호회된 바이트를 문자열로 나타내기 위해 BASE64Encoder을 사용한다.

CipherOutputStream out = new CipherOutputStream(fileOut, cipher);
위의 코드는 outputStream객체을 암호화, 복호화 하는 부분이다.

댓글 없음:

댓글 쓰기

블록체인 개요 및 오픈소스 동향

블록체인(block chain) 블록체인은 공공 거래장부이며 가상 화폐로 거래할때 발생할때 발생할 수 있는 해킹을 막는 기술. 분산 데이터베이스의 한 형태로, 지속적으로 성장하는 데이터 기록 리스트로서 분산 노드의 운영자에 의한 임의 조작이 불가...