2011년 6월 9일 목요일

자바보안과 암호화 - 3

Chapter 3 키관리
Key 인터페이스
1. java.security.Key 인터페이스( 암호화 키를 캡슐화 )
- public String getAlgorithm() : 키가 사용된 암호 알고리즘 이름을 리턴
- public byte[] getEncoded() : 키의 암호화 값을 구할 있다.
- public String getFormat() : 암호화 하는데 사용된 포맷의 이름을 리턴한다.
- 자식 인터페이스 : java.security.PublicKey, java.security.PrivateKey,
javax.crypto.SecretKey(JCE)
2 java.security.KeyPair 클래스( 공개키와 개인키 )
- publicKeyPair(PublicKey publicKey, PrivateKey, privateKey) : 주어진 공개키와 개인키로 KeyPair를 생성한다.
- public PublicKey getPublic() : 공개키를 리턴한다.
- public PrivateKey getPrivate() : 개인키를 리턴한다.

생성기
1. java.security.KeyPairGenerator( 비대칭 방식 JDK에 포함 )
- public KeyPair generateKeyPair () : 열쇠 페어를 생성합니다.
- public final KeyPair genKeyPair () : 열쇠 페어를 생성합니다.
- public String getAlgorithm () : 열쇠 페어 제네레이터의 알고리즘의 표준명을 돌려줍니다.
- public static KeyPairGenerator getInstance (String algorithm) : 지정된 다이제스트 알고리즘을 구현하는 KeyPairGenerator 오브젝트를 작성합니다.
- public static KeyPairGenerator getInstance (String algorithm, String provider) : 지정된 프로바이더로부터 지정된 알고리즘이 사용 가능한 경우에, 프로바이더가 제공한 알고리즘을 구현하는 KeyPairGenerator 오브젝트를 작성합니다.
- public final Provider getProvider () : 열쇠 페어 제네레이터 오브젝트의 프로바이더를 돌려줍니다.
- pubic void initialize (AlgorithmParameterSpec params) : 제공된 파라미터를 사용하여 KeyPairGenerator를 초기화 한다.
- public void initialize (AlgorithmParameterSpec params, SecureRandom random) : 제공된 파라미터를 사용하여 KeyPairGenerator를 초기화 한다.
- public void initialize (int keysize) : 랜덤 비트의 소스 역할을 하는 새로운 SecureRandom을 생성하는 것을 제외하고 임의의 사이즈에 대하여 열쇠 페어 제네리이터를 초기화합니다.
- pubic void initialize (int keysize, SecureRandom random) : 제공된 랜덤 비트 소스를 사용하여 임의의 사이즈 대하는 열쇠 페어 제네레이터를 초기화합니다.
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair pair = kpg.getKeyPair();


2. javax.crypto.KeyGenerator( 대칭 방식 JCE에 포함 )
- public final SecretKey generateKey() : 새로운 랜덤 SecretKey를 생성한다.
- public String getAlgorithm() : KeyGenerator 객체에 사용된 알고리즘의 이름을 리턴합니다.
- public static KeyGenerator getInstance(.String algorithm) : 주어진 알고리즘으로 인스턴스 생성
- pubic static KeyGenerator getInstance(String algorithm, String provider) : 주어진 알고리즘과 프로바이터로 인스턴스 생성
- pubic Provider getProvider() : 사용된 프로바이터 리턴
- public void init(AlgorithmParameterSpec params) : 제공된 파라미터를 사용하여 초기화 한다.
- public void init(AlgorithmParameterSpec params, SecureRandom random) : 제공된 파라미터를 사용하여 초기화 한다.
- public void init(int keysize) : 주어진 크기로 키를 생성하기 위하여 초기화한다.
- public void init(int keysize, SecureRandom random) : 주어진 키와 랜덤소스로 초기화 한다.
- public void init(java.security.SecureRandom random) : 주어진 랜덤소스로 초기화 한다.
KeyGenerator kg = KeyGenerator.getInstance("DES");
kg.init(new SecureRandom());
SecretKey key = kg.generateKey()


해석기
키를 저장하는 방법중 하나는 키를 직렬화 하여 저장하는것과 단순히 바이트의 배열과 같이 키를 저장하거나 전송하는 방법이 있다. 객체를 바이트로 또는 역으로 변환하는 방법이 다음의 클래스에 정의 되어있다.

1. javax.crypto.spec.SecretKeySpec( 바이트 배열을 비밀키로 변환하는 가장 간단한 방법 )
- SecretKeySpec(byte[] key, int offset, int len, String algorithm) : offset과 제공된 바이트의 배열의 len 바이트를 사용하여 SecretKeySpec을 생성한다. 키는 제공된 알고리즘을 따른다.
- SecretKeySpec(byte[] key, String algorithm) : 제공된 바이트 배열을 사용하여 SecretKeySpec을 생성한다. 키는 제공된 알고리즘을 따른다.
SecureRandom sr = new SecureRandom();
byte[] keyBytes = new byte[20];
sr.nextBytes(keyBytes);
SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA1");


2. javax.crypto.SecretKeyFactory
- public static final SecretKeyFactory getInstance(String algorithm) : 주어진 알고리즘에 대하여 새로운 SecretKeyFactory를 생성한다 알고리즘은DES"와 같은 대칭 암호 알고리즘이다.
- pubic static final SecretKeyFactory getInstance(String algorithm, String provider) : 주어진 프로바이더로 SecretKeyFActory를 생성한다.
- public final SecretKey generateSecret(KeySpec keySpec) : KeySpec를 SecretKey로 변환하기 위하여 사용된다.
public SecertKey makeDESKey(byte[] input, int offset)
throws NoSuchAlgorithmException, InvalidkeyException, InvalidkeySpecException{
SecretKeyFactory desFactory = SecretKeyFactory.getInstance("DES");
KeySpec spec = new DESKeySpec(input, offset);
return desFactory.generateSecret(spec);
}


- public final KeySpec getKeySpec(SecretKey key, java.lang.Class keySpec) : 주어진 SecretKey로부터 KeySpec을 생성한다.
public byte[] makeBytesFromDESKey (SecretKey key)
throw NoSuchAlgorithmException, InvaildKeySpecException {
SecretKeyFactory desFactory = SecretKeyFactory.getInstance("DES");
DESKeySpec spec =
(DESKeySpec)desFactory.getKeySpec(Key, DESKeySpec.class);
return spec.getKey();
}


3. java.security.KeyFactory
- public static final KeyFactory getInstance (String algorithm) : 지정된 다이제스트 알고리즘을 구현하는 KeyFactory 오브젝트를 작성합니다. 알고리즘 이름은 비대칭 암호 알고리즘 이름이거나DSA"와 같은 서명 알고리즘 이어야 합니다.
- public static final KeyFactory getInstance (String algorithm, String provider) : 지정된 프로바이더로부터, 지정된 알고리즘의 KeyFactory 오브젝트를 작성합니다.
- public final PrivateKey generatePrivate (KeySpec keySpec) : 지정된 열쇠 사양 (열쇠 데이터)으로부터 개인키를 생성하는데 사용
- public final PublicKey generatePublic (KeySpec keySpec) : 지정된 열쇠 사양 (열쇠 데이터)으로부터 공개키를 생성하는데 사용
- public final KeySpec getKeySpec (Key key, Class keySpec) : 주어진 키로부터 스펙을 생성한다.

교환 프로토콜
1. javax.crypto.KeyAgreement
- public static final KeyAgreement getInstance(String algorithm) : 주어진 알고리즘을 사용하여 새로운 KeyAgreement를 생성한다. 이름은DH"와 같은 키교환 알고리즘이어야 한다.
- public static final KeyAgreement getInstance(String algorithm, String provider) : 주어진 알고리즘과 프로바이더로 새로운 KeyAgreement를 생성한다.
- public final void init(Key key) : 제공된 키를 사용하는 KeyAgreement를 초기화 한다.
- public final void init(Key key, AlgorithmParameterSpec params) : 주어진 키와 알고리즘 지정 파라미터를 사용하여 KeyAgreement를 초기화 한다.
- public final void init(.Key key, AlgorithmParameterSpec params, SecureRandom random) : 주어진 키와 알고리즘 지정 파라미터 그리고 랜덤 소스를 사용해서 KeyAgreement를 초기화 한다.
- public final void init(Key key, SecureRandom random)
- public final Key doPhase(Key key, boolean lastPhase)
- public final byte[] generateSecret()
- public final int generateSecret(byte[] sharedSecret, int offset)
- public final SecretKey generateSecret(java.lang.String algorithm)
- public final String getAlgorithm()
- public final Provider getProvider()
// --< Skip Server >
package test.crypto.part5;
import java.security.*;
import java.net.*;
import java.io.*;
import java.security.spec.*;
import javax.crypto.*;
import sun.misc.*;
public class SkipServer {
public SkipServer() {
}
public void exec(int port) throws Exception {
//Diffie-Hellman 생성
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
kpg.initialize(Skip.sDHParameterSpec);
KeyPair keypair = kpg.genKeyPair();
// 연결을 기다린다.
ServerSocket ss = new ServerSocket(port);
System.out.println("요청을 기다리고 있습니다.... port : "+port);
Socket s = ss.accept();
DataOutputStream out = new DataOutputStream(s.getOutputStream());
DataInputStream in = new DataInputStream(s.getInputStream());
/**
* 첫번째 클라이언트는 서버에 바이트 배열의 코드화된
* Difie-Hellman공개키를 보낸다.
* KeyFactory가 키를 재구성하기 위해 사용된다.
*/
// 공개키를 받는다.
byte[] keyBytes = new byte[in.readInt()];
in.readFully(keyBytes);
KeyFactory kf = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(keyBytes);
PublicKey theirPublicKey = kf.generatePublic(x509Spec);
// 우리의 키를 클라이언트에게 보낸다.
keyBytes = keypair.getPublic().getEncoded();
out.writeInt(keyBytes.length);
out.write(keyBytes);
/**
* 이제 개인키와 클라이언트의 공개키를 사용해서 보안값을 계산할수 있다.
* 보안 값은 Diffie-Hellman 키를 생성
* 하기 위해 사용된 계수만큼 길다. 경우 보안값은
* 1024비트 길이를 가진다.
*/
KeyAgreement ka = KeyAgreement.getInstance("DH");
ka.init(keypair.getPrivate());
ka.doPhase(theirPublicKey,true);
byte[] secret = ka.generateSecret();
out.close();
in.close();
BASE64Encoder encoder = new BASE64Encoder();
System.out.println(encoder.encode(secret));
}
public static void main(String[] args) throws Exception {
if(args.length < 1) {
System.out.println("포트 번호를 입력해주셔야 합니다...");
System.exit(0);
}
SkipServer skipServer = new SkipServer();
skipServer.exec(Integer.parseInt(args[0]));
}
}

//--- < Skip Client >
package test.crypto.part5;
import java.security.*;
import java.net.*;
import java.io.*;
import java.security.spec.*;
import javax.crypto.*;
import sun.misc.*;
public class SkipClient {
public SkipClient() {
}
public void exec(String ip, int port) throws Exception {
//Diffie-Hellman 생성
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
kpg.initialize(Skip.sDHParameterSpec);
KeyPair keypair = kpg.genKeyPair();
// 네트워크 연결
Socket s = new Socket(ip, port);
DataOutputStream out = new DataOutputStream(s.getOutputStream());
DataInputStream in = new DataInputStream(s.getInputStream());
// 공개키 전송
byte[] keyBytes = keypair.getPublic().getEncoded();
out.writeInt(keyBytes.length);
out.write(keyBytes);
// 공개키 수신
keyBytes = new byte[in.readInt()];
in.readFully(keyBytes);
KeyFactory kf = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(keyBytes);
PublicKey theirPublicKey = kf.generatePublic(x509Spec);
/**
* 이제 개인키와 클라이언트의 공개키를 사용해서 보안값을 계산할수 있다. 보안 값은 Diffie-Hellman 키를 생성
* 하기 위해 사용된 계수만큼 길다. 경우 보안값은 1024비트 길이를 가진다.
*/
KeyAgreement ka = KeyAgreement.getInstance("DH");
ka.init(keypair.getPrivate());
ka.doPhase(theirPublicKey,true);
byte[] secret = ka.generateSecret();
out.close();
in.close();
BASE64Encoder encoder = new BASE64Encoder();
System.out.println(encoder.encode(secret));
}
public static void main(String[] args) throws Exception {
if(args.length < 2) {
System.out.println("서버 아이피와 포트 번호를 입력해주셔야 합니다...");
System.exit(0);
}
SkipClient skipClient = new SkipClient();
skipClient.exec(args[0], Integer.parseInt(args[1]));
}
}


KeyStore 클래스의 관리 패러다임
1. 인스턴스 생성
- public static final KeyStore getInstance (String type) : 지정된 타입의 스토어 오브젝트를 작성합니다. KeyStore ks = KeyStore.getInstance("JKS");
- public static final KeyStore getInstance (String type, String provider) : 지정된 프로바이더로부터, 지정된 스토어 타입의 스토어 오브젝트를 작성합니다. KeyStore ks = KeyStore.getInstance("JKS", "SUN");

2. 로딩과 저장
- public final void load (InputStream stream, char[] password) : 지정된 입력 Stream로부터 스토어를 로드합니다.
- public final void store (OutputStream stream, char[] password) : 지정된 출력 Stream에 스토어를 격납 해, 지정된 패스워드로 완전성을 보호합니다

댓글 없음:

댓글 쓰기

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

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