1 / 32

JAVA Cryptography

JAVA Cryptography. 10 장 SafeTalk 시스템 소프트웨어 연구실 성순화 이재일. 목차. Using SafeTalk Under the Hood SafeTalk 구조 Session SessionServer Receiver SafeTalk. SafeTalk. SafeTalk: 유닉스 talk 유틸리티의 자바 애플리케이션으로 대화의 각 끝에 인증을 제공하거나 대화 그 자체를 암호화함으로써 안전한 talk 을 주고 받을 수 있도록 한다 .

phyre
Télécharger la présentation

JAVA Cryptography

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. JAVA Cryptography 10장 SafeTalk 시스템 소프트웨어 연구실 성순화 이재일

  2. 목차 Using SafeTalk Under the Hood SafeTalk 구조 Session SessionServer Receiver SafeTalk

  3. SafeTalk SafeTalk: 유닉스 talk 유틸리티의 자바 애플리케이션으로 대화의 각 끝에 인증을 제공하거나 대화 그 자체를 암호화함으로써 안전한 talk을 주고 받을 수 있도록 한다. 대화를 시작하기 위한 client와 incoming 대화를 받아들이는 server로 되어 있다. 대칭과 비대칭 암호를 합친 hybrid system 대화의 양끝 사이의 session key 교환-> EIGamal(비대칭)암 호 사용 대화의 나머지->DES(대칭)암호와 session key로 암호

  4. SafeTalk v1.0 I got the stuff. We’ll meet in the usual place. 대화를 보내는 text Good. Where can we meet? 대화를 받는 text Disconnect Jonathan 172.16.0.2 Import key... Export key... Connected to Jonathan Using SafeTalk <그림 10-1 The SafeTalk window>

  5. Using SafeTalk First-Time Setup 1. Key file 생성: 각 이름을 선택하여 key pair 생성 2. 인증하기 위해 Safetalk class: - key pair사용 - session key 교환 - EIGamal key의 Keys.ser을 얻는다. <예>512bit keys를 가진 Jonathan을 위한 key file 생성 C: \ java oreilly.jonathan. security.KeyManager -c Keys.ser Jonathan EIGamal 512 keyfile signer algorithm strength Initializing the KeyPairGenerator… Generating the keypair… Done

  6. Using SafeTalk Exporting a Key Keyfile을 생성하면 대화하기를 원하는 모든 사람에게 public key를 분배하기 위해 combobox에 당신의 이름을 선택한 후 Export key버튼을 누른다. Importing a Key 대화하기를 원하는 사람의 public key를 필요로 할 때 Import key를 눌러 public key를 얻어 key를 포함한 파일을 선택하면 public key와 일치하는 이름이 combo box에 나타난다. SafeTalk에서 사용한 exported key만이 import될 수 있다.

  7. Using SafeTalk Starting a Conversation 대화를 시작하려면 combo box의 수신자를 선택하여 combo box 옆 text field에 IP address가 채워진 후 Connect버튼을 누르면 된다. Receiving a Conversation 대화는 incoming calls을 받을 때 자동적으로 받아들여진다. Loopback Testing 같은 기계에서 2개 이상의 SafeTalk일경우 다음과 같은 어려움으로 올바르게 작동하지 않을 것이다.

  8. Using SafeTalk Loopback Testing 각 SafeTalk마다 다른 KeyManager를 필요로 하여 각 다른 identity를 나타내는 2개의 다른 keyfile을 생성해야 한다. Default로 SafeTalk은 port 7999에 대화를 listen하여 같은 port에 대화를 초기화한다. <해결책> Safetalk이 무슨 keyfile과 port number를 사용할 것인지 command-line argument를 사용할 수 있다. 물론 대화 시작 전에 적절한 public key를 사용할 수 있다. C:\ java SafeTalk Keys.ser 7999 8001 Key.ser 8001 7999 keyfile connect port listen port listen portkeyfile connect port

  9. SafeTalk 구조 SafeTalk 구조 Session: 떨어져 있는 SafeTalk 애플리케이션을 연결 관리한다. SessionServer: incoming socket 연결을 알아보고 연결을 받아들였는지 Session에게 통보한다. Receiver:대화중일 때 사용되며 자신의 쓰레드에 incoming data를 알아보고 Session에게 통보한다. Session은 SafeTalk에게 통보하여 incoming data가 SafeTalk window의 lower text area에 보여진다. SafeTalk:SafeTalk class 그 자체가 GUI이며 Frame의 Subclass이다. KeyManager:수신자의 public key 뿐만 아니라 사용자의 key pair를 관리한다. Session은 대화 시작에서 Session key를 교환할 때 KeyManager를 사용하며 SafeTalk은 key를 import.export할때 KeyManager를 사용한다.

  10. KeyManager Import/export keys Public/ private keys Start/ end a session Session data SafeTalk (GUI) Receiver Session Session data Respond to incoming session SessionServer SafeTalk 구조 <그림 10-2 SafeTalk 구조>

  11. Session Session Session class:session key 교환과 socket 연결을 관리 Session class의 연결 관리를 위한 사용방법 connect( ) : 대화를 시작 disconnect( ) : 대화를 중단 isConnected( ) : 대화 중일때 대화 중 data 교환을 위해 사용 send( ) : 대화의 다른 끝에 data를 보내기 위해 사용 Session’s receiverData( ) : Receiver object는 대화의 다른 끝으로부터 data를 받으며 받은 data를 callback방법으로 call한다.

  12. Session Session Key 교환에 사용 initiateConnection( ): 다른 SafeTalk과 대화를 시작하는 key 교환을 다룬다. Connect( )이라고도 불린다. Session’s respond-ToConnection: 연결이 SessionServer에 의해 받아질때 concatenate( )와 SetupCipherStream( ): initiateConnection( )과 respondToConnection( )에 의해 사용된다. <프로그램 1>  KeyManager class를 사용하여 Session은 SafeTalk 애플리케이션 다른 부분을 기억하기 위해 member 변수를 사용한다.  사용자는 연결을 위해 어느 port Session을 사용할 것인지 지적하여 Session은 mListenPort를 알아 mConnectPort에 대한 outgoing calls을 초기화 하여 default에 의해 7999ports가 set된다.

  13. Session <프로그램1>  Session은 연결을 나타내는 Socket을 기억하기 위해 mSocket member 변수를 사용한다. 관련된 member 변수 mOut은 mSocket에 data를 write하는 OutputStream이다.  Session이 먼저 생성되어 SafeTalk와 KeyManager의 future reference를 저장하여 incoming 연결을 listen하는 SessionServer를 생성한다.  import iava.io.*; import iava.net.*; import iava .security.*; import iava. security.spec.*; import iavax.crypto.*;

  14. Session <프로그램1> import iavax.crypto.spec.*; import oreilly.jonathan.security.KeyManager; public class Session  protected SafeTalk mSafeTalk; protected KeyManager mKeyManager; protected SessionServer mServer; protected Receiver mReceiver=null; protected int mListenPort; protected int mConnectPort;

  15. Session <프로그램1>  protected Socket mSocket=null; protected Write mOut=null;  public Session(SafeTalk s, KeyManager KeyManager, int listenport, int connectPort) { mSafeTalk=s; mKeyManager=KeyManager; mConnectPort=connectPort; mServer=new SessionServer(mListenPort, this); }

  16. Session <프로그램2>  connect( )는 IP주소의 사용자와 대화를 시작하기 위해 IP address string은 InetAddress로 전환하고 socket연결을 주어진 주소에 생성한다. 만약 성공적이라면 connect( )은 session key를 교환하기 위해 initiateConnection( )을 call한다.  disconnect( )는 대화를 중단하며 zero byte를 보냄으로써 다른쪽 대화끝에 통보한다. 또한 SafeTalk object에 sessionDisconnect( )를 call함으로써 disconnection을 GUI에 통보한다.  isConnected( )는 self-explanatory이다.  SafeTalk window에서 text를 type할 때 keystrokes를 다른 대화끝에 전달하기 위해 Session의 send( )를 사용한다.  Receiver는 다른 대화끝으로부터 data를 받을 때 Session의 receiverData( )를 call하여 GUI에 이 data를 통과시켜 mSafeTalk에 의해 나타난다.

  17. Session <프로그램2>  public void connect(String user, String addressName) throws Exception{ InetAddress address=InetAddress.getByName(addressName); Socket client=new Socket(address, mConnectPort); initiateConnection(client, user);  public synchronized void disconnect ( ) { try { if (mSocket !=null) { mOut.write (0); mOut.flush( ); mSocket.close( ); }

  18. Session <프로그램2> mSocket=null; mOut=null; } catch (IOException ioe) {} mSafeTalk.sessionDisconnect( ); }  public boolean isConnected( ) {return mSocket !=null; }  public void send(char c) { try {mOut.write( c); mOut . flush ( ); } catch (IOException ioe ) {} }

  19. Session <프로그램2>  public void receiverData(String message) { mSafeTalk. sessionData(message) ; } SafeTalk의 session key 교환은 다음과 같이 수행된다. 1. Client 는 세션 암호에 필요한 IV와 DES 세션키 반을 생성 한다. 2. Client는 server(수신자)의 public key를 사용하는 IV와 key half 를 암호화한다. 수신자의 private key를 가진 사람만이 이정보를 복호화할 수 있다. 3. Client는 이름을 보내어 step2에서 server까지 data를 암호화한다. 4. Server는 private key로 data를 복호화한다.

  20. Session 5. Server는 session key의 두번째 half를 생성한다. 6. Server는 client의 public key를 사용하여 IV와 두번째 key half를 암호화한다. 7. Server는 step6 에서 client까지 암호화된 data를 보낸다. 8. Client는 private key를 사용하여 data를 복호화한다. - > client와 server는 key의 반을 각각 가지므로 이를 모아서 session key로 사용

  21. Session <프로그램 3>  client는 session key의 처음 반과 SecureRandom을 사용하여 IV를 생성한 data를 KeyManager로부터 server의 public key로 암호화하고 concatenate( )는 2 바이트 정렬을 함께 연결시켜 그 결과를 return한다.  우리의 이름과 암호화된 data가 server에 보내져 server는 session key 반과 IV를 복호화한다. 그리고 session key 두번째 반을 generate하여 암호화하며 client의 public key를 가진 IV도 암호화하여 그들 data를 client에 다시 보낸다. Private key로 복호화하여 session key 두번째 반의 복호화된 data를 얻는다.

  22. Session <프로그램 3>  setupCipherStream( )은 키반으로 부터 DES key를 생성하여 대화의 암호화와 복호화를 위해 사용되는 DES CFB암호를 설정한다. Stream이 설정된 후 GUI는 sessionConnect( )를 call하여 대화가 시작되었다는 것을 통보받는다. public void initiateConnection(Socket s, String remoteName) throws Exception { mSocket = s; byte[ ] firstHalf=new byte[4]; SecureRandom sr=new SecureRandom( ); sr.nextBytes (firstHalf);

  23. Session <프로그램 3> byte[ ] iv=new byte[8]; sr.nextBytes (iv); Cipher cipher=Cipher.getInstance(“EIGamal”) ; cipher.init(Cipher.ENCRYPT-MODE, mKeyManager.getPublicKey(remoteName) ) ; byte[ ] ciphertext=cipher.doFinal(concatenate (firstHalf, iv) ) ; DataOutputStream out= new DataOutputStream (mSocket.getOutputStream( ) ); out.writeUTF(mKeyManager.getName ( ) ); out.writeInt(ciphertext.length); out.write (ciphertext);

  24. Session <프로그램 3> DataInputStream in=new DataInputStream(mSocket.getInputStream( ) ); byte[ ] remoteEncrypted=new byte[in.readInt( )]; in.read(remoteEncrypted); cipher.init(Cipher.DECRYPT_MODE, mKeyManager.getPrivateKey( )); byte[ ] decrypted=cipher.doFinal(remoteEncrypted); byte[ ] secondHalf=new byte[4]; System.arraycopy(decrypted, 0, secondHalf, 0,secondHalf.length); setupCipherStreams(firstHalf, secondHalf, iv); mSafeTalk.sessionConnect(remoteName); }

  25. Session <프로그램 4> SessionServer는 incoming connection을 알아보는 것으로 하나가 들어오고 있다면 respondToConnection( )을 call한다. 대화가 진행중이면 incoming connection이 무시된다. client로부터 첫번째 받은 것은 client name이며 server는 data를 얻어 public key로 암호화한다. 그 data는 server의 private key로 복호화된다. server는 session key의 처음 반과 이 data의 IV를 끌어낸다. Session key의 두번째 반은 임의로 generate되며 이것과 IV를 합한 것은 KeyManager로부터 온 client’s public key로 암호화된다.

  26. Session <프로그램 4> server는 암호문을 다시 client로 보낸다. Client는 session key의 반을 가지게 되어 talk을 시작할 준비가 되어 GUI는 sessionRespond( )을 call하여 새로운 대화의 통보를 받는다. Concatenate( )방법은 2 byte 정렬을 간단히 하나의 큰 정렬로 한다. public void respondToConnection(Socket s) throws Exception { // If we’re already connected, dump the incoming call.// if (isConnected ( ) ) { s.close ( );

  27. Session <프로그램 4> return; } mSocket=s; DataInputStream in=new DataInputStream(mSocket.getInputStream( )); String remoteName=in.readUTF( ); byte[ ] remoteEncrypted=new byte[in.readInt( )]; in.readFully(remoteEncrypted); Cipher cipher=Cipher.getInstance(“EIGamal”); cipher .init(Cipher.DECRYPT-MODE, mKeyManager.getPrivateKey( )); byte[ ] decrypted=cipher.doFinal(remoteEncrypted);

  28. Session <프로그램 4> byte[ ] firstHalf= new byte[4]; System.arraycopy(decrypted, 0 , firstHalf, 0 , 4); byte[ ] iv=new byte[8]; System.arraycopy(decrypted, 4, iv , 0 , 8); byte[ ] sencondHalf=new byte[4]; new SecureRandom( ).nextBytes(secondHalf); cipher.init(Cipher.ENCRYPT-MODE, mKeyManager.getPublickey(remoteName)); byte[ ] ciphertext=cipher.doFinal(concatenate(secondHalf, iv));

  29. Session <프로그램 4> DataOutputStream out=new DataOutputStream(mSocket.getOutputStream( )); out.writeInt(ciphertext.length); out. Write(ciphertext); setupCipherStreams(firstHalf, secondHalf, iv); mSafeTalk.sessionRespond(remoteName); } protected byte[ ] concatenate(byte[ ] a, byte[ ]b) { byte[ ] r= new byte[a.length+b.length]; System.arraycopy(a,0,r,0,a.length); System.arraycopy(b,0,r, a.length, b.length); return r; }

  30. Session <프로그램5>  Session의 마지막 단계로 client와 server가 session key의 각 반을 가질 때 대화의 나머지를 설정하기 위해 initiateConnection( )과 respondToConnection( )은 setupCipherStream( )을 call한다. SecretKeyFactory를 사용하여 공급된 key halves로부터 키를 생성한다.  암호화된 입.출력 streams를 생성하기 위해 CipherInputStream과 CipherOutputStream class를 사용하여(DES in CFBmode) 하나는 incoming data를 복호화하고 하나는 outgoing data를 암호화한다.  OutputStream은 output stream을 보호하고 우리는 inputstream주위의 Receiver를 보호하므로 Receiver는 incoming data의 socket을 알아 볼 수 있다.

  31. Session <프로그램5> protected void setupCipherStream(byte[ ] firstHalf, byte[ ] secondHalf, byte[ ] iv) throws Exception { byte[ ] keyBytes=concatenate(firstHalf, secondHalf); SecretKeyFactory skf=SecretKeyFactory.getInstance(“DES”) ; DESKeySpec desSpec=new DESKeySpec(keyBytes); SecretKey sessionKey=skf.generateSecret(desSpec) ;  IvParameterSpec spec=new IvParameterSpec(iv) ; Cipher encrypter=Cipher.getInstance(“DES/CFB8/NoPadding”); encrypter.init(Cipher.ENCRYPT-MODE, sessionKey, spec); Cipher decrypter=Cipher.getInstance(“DES/CFB8/NoPadding”); decrypter.init(Cipher.DECRYPT-MODE, sessionKey,spec) ;

  32. Session <프로그램5>  CipherOutputStream out=new CipherOutputStream( mSocket.getOutputStream( ), encrypter) ; CipherInputStream in=new CipherInputStream( mSocket.getInputStream( ), decrypter ; mOut=new OutputStreamWriter(out, “UTF8”) ; mReceiver=new Receiver(in, this) ; } }

More Related