'RSA'에 해당되는 글 3건

  1. 2015.11.05 전자서명
  2. 2015.11.05 RSA 암호화
  3. 2015.11.05 대칭 비대칭 암호화

전자서명

UP! 2015. 11. 5. 11:00

전자서명

 

     내용

가)    개인 키와 함께 생성된 메시지 다이제스트

나)    서명

 

다)    서명 검증

 

 

     목적

가)    무결성

     데이터에 대해서 바뀌지 않았다는 것을 증명

     데이터와 메시지 다이제스트 두 개를 다 바꿀 수 있음

     다이제스트를 개인키로 서명하면 이것은 불가능해 짐

나)    인증

     개인 키의 소유자만이 데이터에 서명할 수 있음

     키가 안전하다면 사용자가 실제로 서명했다는 것을 확신할 수 있음

 

     활용

가)    계약서에 서명

     1999 7월부터 전자서명법이 발효됨

     기존의 일반 종이문서에 사용되는 인감이나 서명과 같은 법적 효력을 갖게 됨

나)    이메일 서명

     S/MIME PGP를 사용해서 개인 키로 이메일을 서명할 수 있음

다)    타임서버 생성

     타임 스탬프는 데이터에 시간과 함께 서명해서 어떤 특정 시간에 정보가 존재했는지를 증명

라)    서버 승인

     요청에 서명을 하면 사용자가 서버가 특정한 개인 키를 가졌는지 확인 가능

 

     RSA vs. DSA

가)    RSA

     서명을 검증하는데 빠름

 

나)    DSA(Digital Signature Algorithm)

     RSA에서 서명하는 것과 비슷하지만 암호화 기능은 없음

     서명을 만드는데 빠름

 

     자바의 전자 서명

가)    java.security.Signature

     getInstance() : 알고리즘 이름을 인자로 해서 객체의 인스턴스 획득

     initSign() : 개인 키를 인자로 서명

     initVerify() : 공개 키를 인자로 검증

     update() : 데이터를 전달하여 서명/검증을 수행

     sign() : 전자서명을 반환

     verify() : 전자서명의 유효성을 반환

 

     간단한 전자서명 예제

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.Signature;

import java.security.SignatureException;

 

import com.Ostermiller.util.Base64;

 

public class SignatureExample {

 

       public static void main(String[] args) throws Exception{

             //RSA 생성

             System.out.println("RSA 생성...");

             KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");

             kpg.initialize(1024);

             KeyPair keyPair = kpg.genKeyPair();

             System.out.println("RSA 생성 완료");

            

             // 서명할 데이터

             byte[] data = "i love you.".getBytes("UTF-8");

            

             // 서명을 위해 Signatrue 객체 생성 개인 키로 초기화

             Signature sig = Signature.getInstance("MD5WithRSA");

             sig.initSign(keyPair.getPrivate());

             sig.update(data);

             // 실제 서명

             byte[] signaturedBytes = sig.sign();

             System.out.println("전자서명된 데이타 : " + Base64.encode(signaturedBytes));

            

             // 전자서명 검증

             sig.initVerify(keyPair.getPublic());

             sig.update(data);

             boolean verified = false;

             try {

                    verified = sig.verify(signaturedBytes);

             } catch (SignatureException e) {

                    verified = false;

                    System.out.println("전자서명 형식에 문제가 발생하였습니다.");

                    e.printStackTrace();

             }

            

             if(verified)

                    System.out.println("전자서명 검증 성공");

             else

                    System.out.println("전자서명 검증 실패");

 

       }

 

}

 

     전자 서명의 한계

가)    검증을 위해서 공개 키가 필요

나)    공개 키의 소유자를 확신하기가 힘듬

다)    전자 인증서로 문제 해결

 

Posted by 으랏차
,

RSA 암호화

카테고리 없음 2015. 11. 5. 10:57

RSA 파일 암호화

 

     RSA 키 쌍 생성

 

     공개 키로 파일을 암호화

가)    RSA 키의 인코딩

     X.509를 사용하여 인코딩 사용(공개 키와 인증서를 전달할 때 사용하는 공개 형식)

     개인 키는 PKCS#8로 인코딩

     공개/개인 키든 getEncoded()를 호출하면 자동으로 인코딩 됨

나)    RSA 키의 디코딩

     인코딩된 키의 스펙 객체를 생성

     KeyFactory를 사용하여 적절한 키 타입의 인스턴스를 활성화

     공개 키 디코딩

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);

PublicKey publicKey = keyFactory.generatePublic(keySpec);

 

     개인 키의 디코딩

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);

PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

 

다)    암호화된 파일 형식

     포맷

키의 길이

암호화된 키

초기화백터(16바이트)

암호문서

 

라)    예제

private static void createKey(String password) throws Exception {

             // RSA 생성

             KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");

             keyPairGenerator.initialize(1024);

             KeyPair keyPair = keyPairGenerator.genKeyPair();

            

             //공개키를 파일에 쓴다.

             byte[] publicKeyBytes = keyPair.getPublic().getEncoded();

             FileOutputStream fos = new FileOutputStream("c:\\publicKey");

             fos.write(publicKeyBytes);

             fos.close();

            

             // 개인 키를 암호화한 후에 파일에 쓴다.

             byte[] privateKeyBytes = passwordEncrypt(password.toCharArray(), keyPair.getPrivate().getEncoded());

             fos = new FileOutputStream("c:\\privateKey");

             fos.write(publicKeyBytes);

             fos.close();

       }

      

       private static byte[] passwordEncrypt(char[] password, byte[] plaintext) throws Exception {

             // salt 생성

             byte[] salt = new byte[9];

             Random random = new Random();

             random.nextBytes(salt);

            

             // PBE 키와 사이퍼 생성

             PBEKeySpec keySpec = new PBEKeySpec(password);

             SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwofish-CBC");

             SecretKey key = keyFactory.generateSecret(keySpec);

             PBEParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS);

            

             Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");

             cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);

            

             byte[] cipherText = cipher.doFinal(plaintext);

            

             ByteArrayOutputStream baos = new ByteArrayOutputStream();

             baos.write(salt);

             baos.write(cipherText);

            

            

             return baos.toByteArray();

       }

      

       private static void encrypt(String fileInput) throws Exception {

             String publicKeyFileName = "c:\\publicKey";

             // 공개 키가 저장된 파일로부터 keyByte 바이트 배열을 생성한다.

             FileInputStream fis = new FileInputStream(publicKeyFileName);

             ByteArrayOutputStream baos = new ByteArrayOutputStream();

            

             int theByte = 0;

             while((theByte = fis.read()) != -1)

                    baos.writeTo(baos);

             fis.close();

            

             byte[] keyBytes = baos.toByteArray();

             baos.close();

            

             // 인코딩된 키를 RSA 공개 키의 인스턴스로 바꾼다.

             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

             KeyFactory keyFactory = KeyFactory.getInstance("RSA");

             PublicKey publicKey = keyFactory.generatePublic(keySpec);

            

             String fileOutput = fileInput + ENCRYPTED_FILENAME_SUFFIX;

             DataOutputStream output = new DataOutputStream(new FileOutputStream(fileOutput));

            

             // RSA 공개 키를 이용하여 세션 키를 암호화할 사이퍼를 생성한다.

             Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

             rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);

            

             // 세션 생성

             KeyGenerator rijndaelKeyGenerator = KeyGenerator.getInstance("Rijndael");

             rijndaelKeyGenerator.init(256);

             Key rijndaelKey = rijndaelKeyGenerator.generateKey();

            

             // RSA 사이퍼를 이용하여 세션 키를 암호화 하고 파일에 저장한다.

             // 키의 길이, 인코딩된 세션 형식이다.

             byte[] encodedKeyBytes = rsaCipher.doFinal(rijndaelKey.getEncoded());

             output.writeInt(encodedKeyBytes.length);

             output.write(encodedKeyBytes);

            

             // 초기화 벡터

             SecureRandom random = new SecureRandom();

             byte[] iv = new byte[16];

             random.nextBytes(iv);

            

             //IV 파일에 쓴다

             output.write(iv);

            

             //IV 생성한 세션 키를 이용하여 파일의 내용을 암호화한다.

             IvParameterSpec spec = new IvParameterSpec(iv);

             Cipher symmetricCipher = Cipher.getInstance("Rijndael/CBC/PKCS5Padding");

             symmetricCipher.init(Cipher.ENCRYPT_MODE, rijndaelKey, spec);

             CipherOutputStream cos = new CipherOutputStream(output, symmetricCipher);

            

             FileInputStream input = new FileInputStream(fileInput);

             theByte = 0;

             while((theByte = input.read()) != -1)

                    cos.write(theByte);

            

             input.close();

             cos.close();

             return;

       }

 

     개인 키로 복호화

가)    예제

private static byte[] passwordDecrypt(char[] password, byte[] ciphertext) throws Exception {

             // salt 읽는다. 개인키는 8byte salt 사용했다.

             byte[] salt = new byte[8];

             ByteArrayInputStream bais = new ByteArrayInputStream(ciphertext);

             bais.read(salt, 0 ,8);

            

             byte[] remainingCiphertext = new byte[ciphertext.length-8];

             bais.read(remainingCiphertext, 0, ciphertext.length-8);

            

             //PBE 사이퍼를 생성하여 세션 키를 복원한다.

             PBEKeySpec keySpec = new PBEKeySpec(password);

             SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwofish-CBC");

             SecretKey key = keyFactory.generateSecret(keySpec);

             PBEParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS);

             Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");

            

             // 복호화

             cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

             return cipher.doFinal(remainingCiphertext);

       }

      

       private static void decrypt(String password, String fileInput) throws Exception {

             String privateKeyFilename = "c:\\privateKey";

             // 파일로부터 개인 키를 읽어들인다.

             FileInputStream fis = new FileInputStream(privateKeyFilename);

             ByteArrayOutputStream baos = new ByteArrayOutputStream();

            

             int theByte = 0;

             while((theByte = fis.read()) != -1)

                    baos.write(theByte);

             fis.close();

             byte[] keyByte = baos.toByteArray();

             baos.close();

            

              // 암호화된 개인 바이트를 복원한다.

             keyByte = passwordDecrypt(password.toCharArray(), keyByte);

            

             // RSA 개인 키를 복원한다.

             PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyByte);

             KeyFactory keyFactory = KeyFactory.getInstance("RSA");

             PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

            

             // 개인 키를 이용하여 사이퍼를 생성하고 세션 키를 복호화한다

             Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

             DataInputStream dis = new DataInputStream(new FileInputStream(fileInput));

             byte[] encryptedKeyBytes = new byte[dis.readInt()];

             dis.readFully(encryptedKeyBytes);

            

             rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);

             byte[] rijndaelKeyByte = rsaCipher.doFinal(encryptedKeyBytes);

            

             SecretKey rijndaelKey = new SecretKeySpec(rijndaelKeyByte, "Rijndael");

            

             byte[] iv = new byte[16];

             dis.readFully(iv);

             IvParameterSpec spec = new IvParameterSpec(iv);

            

             Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS5padding");

             cipher.init(Cipher.DECRYPT_MODE, rijndaelKey, spec);

             CipherInputStream cis = new CipherInputStream(dis, cipher);

            

             FileOutputStream fos = new FileOutputStream(fileInput + DECRYPTED_FILENAME_SUFFIX);

            

             theByte = 0;

             while((theByte = cis.read()) != -1)

                    fos.write(theByte);

            

             cis.close();

             fos.close();

            

             return;     

       }

 

나)    복호화 과정

 

     세션 키 암호화를 사용해야 하는 이유

가)    해킹에 대비해, 개인 키를 저장할 때 암호화할 필요가 있다.

나)    세션 키를 사용하면 속도가 훨씬 빨라진다.

다)    RSA는 특정 메시지에 대해서 매우 취약하다.

 

Posted by 으랏차
,
 

암호화(Encryption) : 메시지를 숨겨 그 메시지의 수신자 외에는 아무도 못 읽게 하는 것.

인증(Authentication) : 메시지가 바뀌지 않았는지, 혹은 발신자, 수신자가 맞는지 확인하는 것

JCA : Java Cryptography Architecture

JCE : Java Cryptography Extension

 

대칭 암호화 알고리즘

 

     블록암호와 스트림 암호

가)    블록암호화 방식

     한번에 정해진 크기의 데이터를 암호화 하는 방식

     64bit or 128 bit 크기 단위로 적용

나)    스트림 암호화 방식

     1bit or 1btye의 데이터를 암호화 하는 방식

     소켓 같은 정보의 일정한 스트림을 암호화할 때 적당

 

     대칭 암호화 깨는 방법에 대해

가)    단문 무식하게 모든 가능한 키를 시도

나)    키 스페이스 : 후보 키들의 집합이며  만큼의 후보 키가 존재한다.

 

     대칭 암호화에 사용되는 알고리즘

가)    DES(Data Encryption Standard)

     가장 널리 알려진 대칭 암호화 기법

     56bit 키 사용

     DES의 변형으로 TripleDES(DESede)가 고안됨.

나)    TripleDES(DESede)

     DES를 다른 키에 세 번 적용시키는 방식

     암호화 / 복호화 / 또 다른 암호화 -> ede(encryption, decryption, encryption)

     키는 2개 또는 3개가 사용될 수 있음

다)    Blowfish

     DES보다 더 빠르고 안전한 블록 암호

     448비트 키 사용 가능

라)    RC4(Rivest’s Code 4)

     스트림 암호의 일종으로 SSL 구현에 많이 사용됨

     40bit or 128bit

마)    AES(Advanced Encryption Standard)

     Rijndael 알고리즘 사용

     128, 192, 256 bit 사용 가능

 

     대칭 암호화의 한계

가)    암호화 복호화에 같은 키가 적용됨

나)    ·수신자 모두 동일한 키를 가지고 있어야 함

다)    키를 안전하게 전달할 수 있는 방법은 무엇인가?

 

 

비대칭 암호화

 

     기능

가)    암호화에 쓰이는 공개 키와 복호화에 쓰이는 개인 키 2개를 사용

 

     비대칭 암호화 알고리즘

가)    RSA

     키 교체가 가능 즉, 개인키로 암호화하면 공개키로 복호화 가능

나)    EIGamal

     PGP SSL에 사용

 

     약점

가)    개인 키가 쉽게 공격 받을 수 있다.

     공개 키를 다른 사람의 것으로 바꿔치기 하는 방법에 허점이 발생

     공개 키에 대한 증명서를 첨부해서 해결함

나)    속도가 느리다.

     대칭 암호화에 비해 1000배 느림

 

     세션 키 암호화

가)    세션 키를 암호화 하는데 사용하고 세션 키는 공개 키를 이용하여 암호화 함

나)    세션 키는 대칭 암호화 방법을 사용

다)    생성한 세션 키를 상대방에게 전달해야 함

라)    PGP : 이메일을 암호화하는데 사용됨

마)    S/MIME : 안전한 이메일 전송을 위해 RSA가 고안한 방법

바)    SSL/TLS : Secure Socket Layer Transport Layer Security TCP/IP 트래픽을 보안하기 위해 만들어짐

 

     키 일치(Key Agreement)

가)    상대방의 공개 키와 자신의 개인 키를 이용하여 암호화를 위한 키 생성

나)    공유 비밀 키(shared secret key)를 만들어 암호화와 복호화에 사용

다)    상대방에게 공유 비밀 키를 전달할 필요 없음

라)    Diffie-Hellman 키 일치 알고리즘

     공개-개인 키 쌍을 이용한 첫번째 알고리즘

  

암호화 알고리즘 요약

  

     암호화 알고리즘 요약

가)    알고리즘의 능력 판단 기준

     알고리즘 종류 및 키의 크기

 

나)    대칭 암호화

알고리즘

종류 

키의 크기 

참고 

 DES

블록 

56 

 가장 많이 사용되지만 너무 취약함

 TripleDES

블록

 158(유효 112)

 DES의 강화버전

 Blowfish

블록

 488까지 임의 길이

 훌륭한 보안 제공

 RC4

스트림

 보통 40 또는 128

 빠른 스트림 암호화, 대부분의 SSL 구현에 사용됨

 AES

블록

 128, 192, 256

 DES 대용의 비교적 최근 암호화 기법

 

다) 비대칭 암호화

 알고리즘

종류 

키의 크기 

참고 

 RSA

블록 

512, 1024, 2048 

가장 많이 사용되는 공개 키 알고리즘

2000년도 특허 만료 

 EL Gamal

 블록

512, 1024, 2048 

 PGP 같은 프로토콜에 널리 사용됨

 

라) 키 일치 알고리즘

 알고리즘

종류 

키의 크기 

참고 

 Diffie-Hellman

키 일치 

보통 512, 1024 

최초의 공개 키 암호 작성 알고리즘 

 

 

출처 : http://blog.naver.com/xxrcn11?Redirect=Log&logNo=20134786143

'UP! > Crypto' 카테고리의 다른 글

패스워드 기반 암호화  (0) 2015.11.05
JCA, JCE  (0) 2015.11.05
인증, 전자서명  (0) 2015.11.05
블록 Padding  (0) 2015.11.05
base64 인코딩, 디코딩의 원리  (0) 2015.11.05
Posted by 으랏차
,