RSA java 구현

Development/Java 2012. 12. 26. 15:06


RSA(Rivest Shamir Adleman)는 현재 공개키 암호화방식으로 가장 널리쓰이는 알고리즘이다. 1977년에 Rivest, Shami,r Adleman이라는 세 명의 수학자들에 의해 제안됭 방식이다.
이 알고리즘은 두 개의 큰 소수를 이용한다.  이 수들의 추가(?) 연산을 통해 공개키와 개인키를 구성해서 사용하는 방식이다.
밀러-라빈 판정법, 유클리드 알고리즘, 빠른 법-지수 연산 알고리즘만 알고 있으면 간단히 구현이 가능하지만 귀찮아서 그냥 제공해주는것을 사용하겠다. (BigInteger 클래스를 사용하면 아주 간단히(?) 구현이 될지도....)

01package test.cipher;
02 
03import java.security.InvalidKeyException;
04 
05public class RsaTest {
06 
07    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
08        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
09        KeyPair keyPair = generator.generateKeyPair();
10        PublicKey publicKey = keyPair.getPublic();
11        PrivateKey privateKey = keyPair.getPrivate();
12         
13        Cipher cipher = Cipher.getInstance("RSA");
14        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
15        String text = "아~ 인생은 나그네길~";
16        byte[] t0 = text.getBytes();
17        System.out.println("P : " + ByteUtils.toHexString(t0));
18        byte[] b0 = cipher.doFinal(t0);
19        System.out.println("E : " + ByteUtils.toHexString(b0));
20         
21        cipher.init(Cipher.DECRYPT_MODE, privateKey);
22        byte[] b1 = cipher.doFinal(b0);
23         
24        System.out.println("D : " + ByteUtils.toHexString(b1));
25        System.out.println(new String(b1));
26    }
27}


 기존에 사용한 DES/AES와 다르게 키가 공개키(PublicKey)와 개인키(PrivateKey)로 구성되어있다. 암호화할때 공개키를 복호화할때 개인키를 사용하고 있다.
 A와 B가 원거리에서 비밀 얘기를 하고 싶어한다고 하자. 암호화를 해서 데이터를 보내면 될것이다. 그런데, 암호화에 사용할 키(key)를 상대편에게 건내주는 문제가 발생한것이다. 달려가서 직접 건네줘도 되지만 원거리라서 아마 서로 귀찮아할것이다.
그래서 만들어진것인 공개키 방식의 암호화알고리즘이다. A가 공개키와 비밀키를 생성한다음, B에게 공개키를 보낸다. (C라는 낯선 사람이 이 공개키를 볼 수도 있지만 문제가 되지 않는다. 공개(?)키니까 ^^;) B는 받은 공개키를 가지고 블럭암호화에 사용할 키를 암호화해서 A에게 전달한다. A는 B로 부터 받은 암호화된 키를, 자신의 비밀키를 이용해서 복호화한다. 이제 A도 블럭암호화에 사용할 키를 가지게 되었으므로, 그 키를 가지고 암호화해서 B에서 데이터를 전송하면 되는것이다. (메시지 변조등 어려운것은 일단 넘어가도록 하자 ^^;)
 즉, 암호화에 사용할 키(key)를 RSA를 이용해서 분배한것이다. 
 그렇다면 왜 두가지 방식의 암호화 알고리즘을 사용한것일까? 다른 블럭 암호화 알고리즘을 사용하지 않아도, RSA만으로 서로 안전한 통신이 가능하지 않은가? 그 이유는 RSA가 다른 블럭암호화에 비해 소요되는 비용이 많기 때문이다. (믿거나 말거나)
 
----------------------------------------------------------------------------------
  원래 계획은 RSA를 직접 구현해보고, SEED도 직접 구현해보는 글을 작성할려고 했는데, 이사 준비와 게으름병이 도진 관계로 얼렁뚱땅 자바 암호화에 대해 마무리를 하겠다.
----------------------------------------------------------------------------------

  자바에서는 암호(Cryptography) 처리를 위해 JCA(Java Cryptography Architecture)와 JCE(Java Cryptography Extension)을 정의하고 있다. 
 JCA는 java.security 패키지에 선언되어 있는데, 암호화 처리를 위한 구조를 정의하고 있다.
 이 세상에는 다양한 암호화 알고리즘이 있다. 자바는 사용자가 사용할 알고리즘을 알 수가 없고, 또한 모든 알고리즘을 제공할 수 없다. 그래서 JCA는 SPI(Spervice Provider Inteface)등 통해서 사용자가 사용할 암호화 방식을 선택할 수 있는 틀을 제공한다고 보면된다.
 JCE는 JCA의 확장으로서 java.crypto 패키지에 선언되어 있는데, Cipher, MAC, KeyGenerator등으로 구성되어있다. 즉, 실제적인 암호화 처리를 제공한다.
 보다 유용하고 재미있는 정보를 원한다면 아래 사이트에 가보시길 권하는바이다.
http://java.sun.com/javase/6/docs/technotes/guides/security/


출처 - http://blog.kangwoo.kr/47





'Development > Java' 카테고리의 다른 글

java - CRC32 클래스  (0) 2013.01.31
serialVersionUID  (0) 2013.01.01
javax.crypto.BadPaddingException: Given final block not properly padded  (0) 2012.12.24
proguard  (0) 2012.12.09
java - war 파일 생성 및 풀기  (0) 2012.12.06
Posted by linuxism
,


자바스크립트에서는 Math.random() 함수(메서드)로 무작위의 숫자를 출력할 수 있습니다.

그런데 Math.random()은 0~1까지의 "0.8794235627233815" 이런 실수를 반환하기에, 큰 숫자가 나오게끔 곱하기를 한 후, Math.floor() 를 사용하여 정수화시켜야 합니다.


자바스크립트: 1에서 10까지 랜덤 정수 출력 예제


<script type="text/javascript">

  var result = Math.floor(Math.random() * 10) + 1;
  document.write(result);

</script>


Math.floor(Math.random() * 100) + 1;
이렇게 하면, 1에서 100까지 나오고

Math.floor(Math.random() * 10);
이렇게 하면, 0에서 9까지 나오게 됩니다.




Math.floor() 대신 Math.round()를 사용하여 정수화하면 안됩니다. Math.round()를 사용하면 1~10까지 나오는 것이 아니라 1~11까지 나오게 됩니다.


출처 - http://mwultong.blogspot.com/2006/11/random-javascript.html



'Development > JavaScript' 카테고리의 다른 글

comet  (0) 2012.12.28
자바스크립트 이벤트 핸들링  (0) 2012.12.27
socket.io configure  (0) 2012.12.18
javascript - 클로저(Closure)  (0) 2012.12.01
javascript - Event 버블링 및 캡쳐링 해결방법  (0) 2012.11.01
Posted by linuxism
,


java에서 일반적인 byte[] -> string ->  byte[] 는 문제가 없으나
암호화된 값을 변형할 때는 원복되지 않는 버그가 있다고 한다..(확실치 않음)
해서 헥사 코드 값을 db에 저장해서 다시 불러와 복호화 하려하면
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
Exception 발생.
이럴 땐 헥사 코드값을 저장해서 다시 복호화하려 하지 말고 아래와 같이 BASE64로 인코딩하고 디코딩해서
복호화 하는 방법을 쓴다.
 
 
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class Test{
 private static final String key = "AES";
 private static Cipher cipher;
 private static SecretKeySpec skeySpec;
 
 static{
  try{
   KeyGenerator kgen = KeyGenerator.getInstance( key );
   kgen.init(128); // 192 and 256 bits may not be available
   SecretKey skey = kgen.generateKey();
   byte[] raw = skey.getEncoded();
   skeySpec = new SecretKeySpec(raw, "AES");
     
   cipher = Cipher.getInstance( key );
  }catch( Exception e){
   e.printStackTrace();
  }
 }
 
 
 public static void main(String [] args){
  try{
   
   //원문
   String str = "This sample program demonstrates how to use strong cryptography, which is available by default in most installations. ";
   byte[] encrypted = Encrypt(str, skeySpec, cipher);
   String sBase =  new BASE64Encoder().encode(encrypted);
     
   System.out.println("base64 Encoded 암호문 : " + sBase);
   byte[] decrypted = Decrypt(new BASE64Decoder().decodeBuffer(sBase), skeySpec, cipher);
   System.out.println("decrypt된 원문 : " + new String(decrypted));
  }catch(Exception e){
   e.printStackTrace();
  }finally{
  }
 }
 
 public static byte[] Encrypt(String data, SecretKeySpec keySpec, Cipher cipher) throws Exception{
  // 암호화
  cipher.init(Cipher.ENCRYPT_MODE, keySpec); // 암호화 모드로 지정
  byte[] encrypted = cipher.doFinal(data.getBytes());
  return encrypted;
  }
 
 public static byte[] Decrypt(byte[] encrypted_data, SecretKeySpec keySpec, Cipher cipher) throws Exception{
  //복호화
  cipher.init(Cipher.DECRYPT_MODE, keySpec); // 복호화 모드로 지정
  byte[] decrypted = cipher.doFinal(encrypted_data);
  return decrypted;
 }
 
}

출처 - http://blog.naver.com/PostView.nhn?blogId=singing4u&logNo=30100166662





'Development > Java' 카테고리의 다른 글

serialVersionUID  (0) 2013.01.01
RSA java 구현  (0) 2012.12.26
proguard  (0) 2012.12.09
java - war 파일 생성 및 풀기  (0) 2012.12.06
java.lang.NoSuchMethodError  (0) 2012.11.22
Posted by linuxism
,