<CS지식>보안, 암호_대칭키, 공개키 암호, SHA-256, AES-256

Google 아니고 Joogle·2022년 4월 13일
0

CS 지식

목록 보기
1/22

1. 대칭키 암호

  • 하나의 비밀키를 양쪽 (Serer & Client)가 모두 같이 사용
  • 암호화와 복호화에 사용하는 키가 같은 암호화 알고리즘
  • 계산 속도가 빠름
  • 비밀키 하나만 알아내면 암호화된 내용을 해독 가능
  • 대칭키 암호는 암호화하는 단위에 따라 스트림암호, 블록암호로 나눌 수 있음
  • 스트림 암호: 연속적인 비트/바이트를 계속해서 입력받아, 그에 대응하는 암호화 비트/마이트를 생성하는 방식
  • 블록 암호: 정해진 한 단위(블록)을 입력받아 그에 대응하는 암호화 블록을 생성하는 방식
  • 블록 암호의 경우 적절한 운용모드를 조합하면 블록 단위보다 더 큰 입력을 처리할 수 있음. 또한 스트림 암호와 유사하게 지속적인 입력에 대해 동작할 수 있음
  • DES, 3-DES, AES, SEED, ARIA, MASK

2. 공개키 암호

  • 비밀키 하나만 가지는 대칭키 암호 방법과 달리, 공개키, 비밀키 두 개가 존재
  • 공개키 암호를 구성하는 알고리즘을 대칭키 암호 방식과 비교하여 비대칭 암호라고 불림
  • 암호화와 복호화에 사용하는 키가 서로 다름
  • 암호화할 때는 공개키 (public key), 복호화할 때는 개인키 (private key)
  • 공개키는 누구나 알 수 있지만 그에 대응하는 비밀키는 소유자만이 알 수 있어서 특정한 비밀키를 가지는 사용자만이 내용을 열어볼 수 있도록 하는 방식
    e.g. 송신자는 수신자의 공개키를 받아 데이터를 암호화하여 네트워크를 통해 원격지에 저달
    수신자는 공개키로 암호화된 데이터를 자신의 개인키로 데이터를 복호화하여 평문을 복원
  • 공개키로 암호화한 메시지는 수신자의 개인키로만 해독할 수 있으므로 안전하게 상대방에게 메시지를 전달해줄 수 있음
  • 대칭키 알고리즘에 비하여 속도가 느리다 (약 1000배)
  • 속도가 느리기 때문에 긴문서의 암호화보다 대칭키 알고리즘 키값에 대한 암호에 사용
  • 대표적인 공개키 알고리즘으로 RSA, Elgamal

3. SHA-256

  • SHA-256 해시 함수는 어떤 길이의 값을 입력하더라도 256비트의 고정된 결과값을 출력
  • 일반적으로 입력값이 조금만 변동하여도 출력값이 완전히 달라지기 때문에 출력값을 토대로 입력값을 유추하는 것은 거의 불가능
  • 아주 작은 확률로 입력값이 다름에도 불구하고 출력값이 같은 경우가 발생하는데 이것을 충돌이라고 하며, 충돌 발생 확률이 낮을수록 좋은 함수
  • 현재 블록체인에서 가장 많이 채택하여 사용되고 있는 암호 방식
  • 출력 속도가 빠르다는 장점을 가짐
  • 단방향성의 성질을 띄고 있는 암호화 방법으로 복호화가 불가능
  • 큰 단점이 발견되지 않았고, 속도가 빠르기 때문에 인증서, 블록체인 등에 많이 사용됨

C 코드

#include "KISA_SHA256.h"
 
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
 
int main(int argc, char** argv)
{
 
    //변수 초기화.
    FILE *fp = NULL;
    unsigned char buffer[2048] = { 0, };
    unsigned char result[32] = { 0, };
    int read = 0;
    int loop_number = 0;
 
    //SHA256 변수 초기화.
    SHA256_INFO sha256_info;
 
    SHA256_Init(&sha256_info);
 
    //파일 읽기.
    //fp = fopen("Test.txt", "rb"); Visual Studio 옛버전을 사용할 경우, 이 구문 사용. Visual Studio에서 안전성 문제로 인한 함수 개선
    fopen_s(&fp, "Text.txt", "rb");
 
    if (fp == NULL)
    {
        printf("Error : File not find.\n");
        system("pause");
        return -1;
    }
 
    while ((read = fread(buffer, 2048, 1, fp)) != 0)
    {
        SHA256_Process(&sha256_info, buffer, read);
    }
 
    SHA256_Close(&sha256_info, result);
 
    for (loop_number = 0; loop_number < 32; loop_number++)
    {
        printf("%02x", result[loop_number]);
    }
 
    system("pause");
    return 0;  
}[7]

JAVA 코드

package com.tistory.needjarvis;
 
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
 
public class main {
    public static void main(String[] args) throws Exception {
        System.out.println(sha256("needjarvis"));        
    }
  
    /**
     * SHA-256으로 해싱하는 메소드
     * 
     * @param bytes
     * @return
     * @throws NoSuchAlgorithmException 
     */
    public static String sha256(String msg) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(msg.getBytes());
        
        return bytesToHex1(md.digest());
    }
   
    /**
     * 바이트를 헥스값으로 변환한다.
     * 
     * @param bytes
     * @return
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        for (byte b: bytes) {
          builder.append(String.format("%02x", b));
        }
        return builder.toString();
    }
}[8]

4. AES-256

  • 암호화 및 복호화 시 동일한 키를 사용하는 대칭키 알고리즘
  • 높은 안정성과 빠른 속도
mport java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AES256 {

    public static String alg = "AES/CBC/PKCS5Padding";
    private final String key = "01234567890123456789012345678901";
    private final String iv = key.substring(0, 16); // 16byte

    public String encrypt(String text) throws Exception {
        Cipher cipher = Cipher.getInstance(alg);
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParamSpec);

        byte[] encrypted = cipher.doFinal(text.getBytes("UTF-8"));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    public String decrypt(String cipherText) throws Exception {
        Cipher cipher = Cipher.getInstance(alg);
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParamSpec);

        byte[] decodedBytes = Base64.getDecoder().decode(cipherText);
        byte[] decrypted = cipher.doFinal(decodedBytes);
        return new String(decrypted, "UTF-8");
    }

}
profile
Backend 개발자 지망생

0개의 댓글