728x90
2가지 타입의 암호화 기술
- 복호화 가능
- symmetric (대칭키)
보내는 사람과 받는 사람이 같은 key를 가져야 한다.
속도가 빠르다.
key가 어느쪽이든 탈취당할 경우 위험하다. - asymmetric (비대칭키)
public key와 private key가 존재한다.
두 key는 수학적으로 연관이 된 key다.
public key는 누구나 사용 가능하고 private key는 메세지를 해독하는 수신자만 가지고 있는다.
- symmetric (대칭키)
- 복호화 불가능
- hashing
데이터마다 고유한 해시를 생성한다.
암호화된 데이터는 복원할 수 없다.
그렇기 때문에 이전과 같은 데이터 였는지 검증하는 용도로만 사용할 수 있다.
SHA, HMAC 등은 해시를 생성하는 방법들이다.
- hashing
대표적인 암호화 기술
- AES
symmetric이다.
세계적으로 가장 많이 사용되는 symmetric 암호화 알고리즘이다.
미국과 다양한 단체에서 사용한다.
128bit의 data를 암호화 한다.
key는 128-bit 가 가장 효율적이지만 192, 256bit의 key도 사용된다
(data와 key를 혼동하면 안된다) - Triple DES
symmetric이다.
산업 현장에서 가장 많이 쓰였던 symmetric 였다.
56-bit key를 사용한다.
UNIX 비밀번호와 ATM PIN 등에 보통 사용된다.
현재 일부는 더 안전한 AES로 전환되고 있는 추세이다. - RSA
asymmetric 이다.
인터넷 전송 데이터 암호화의 표준이다.
대용량 데이터를 암호화 하는 경우 속도가 느려진다.
개인정보 암호화를 위한 기술 선택
- AES 사용
단일 application 에서 사용하므로 private key를 사용할 이유가 없다.
symmetric 방법 중 Triple DES 보다 보안이 뛰어난 AES를 사용 - 256bit key
AES 의 128bit과 256bit key 사용 중 당연히 256bit더 안전하지만 둘다 충분히 안전하기 때문에 속도가 더 빠른 128bit을 사용할 것을 권장한다.
256bit 가 128bit 보다 40% 시간이 더 소요된다.
ex) 128bit 가 1초 걸린다면, 256bit 는 1.4초 소모
하지만 좀더 안전한 256bit을 사용하는 것이 좋을 것 같다. (심리적 안정감 ㅎㅎ) - AES-CBC
첫 128bit 단위 데이터는 IV와 xor 한다
두번째 128bit 단위 데이터부터는 이전 데이터를 사용해서 xor한다
결과적으로 데이터를 복호화 하려면 이전 128bit 단위 데이터를 알아야만 한다.
이런 방법으로 128bit보다 큰 데이터를 함께 암호화할 수 있다.
이렇게 128bit 한계를 뛰어넘어 블록들을 연계시켜 더 큰 데이터를 암호화 하는 것을 Block cipher mode of operation
라고 하며 CBC 는 그 중 한 방법이다. - AES-GCM vs AES-CBC
암호화 과정을 이해하진 못했지만 GCM이 더 안전하고 CBC와 다르게 데이터 병렬 암호화 처리가 가능하여 빠르다고 한다.
- Initialization vector(IV) 의 재사용 X
재사용 하지 말아야함. unique해야 함 - Initialization vector(IV)를 저장하는 방법
IV와 Key가 있어야 복호화가 가능하므로 IV도 함께 저장해야 한다. IV는 노출되어도 된다.
[IV][ciphertext] 방식으로 저장한다.
IV : 1234
ciphertext : 5678
DB : 12345678 - AES-GCM의 IV 길이
96bit를 권장한다.
추가적인 계산이 필요없는 길이 중 가장 긴 길이이기 때문이다. - Initialization vector(IV) 를 random 으로 사용해도 되는가?
랜덤을 사용해도 되지만, 중복 가능성이 매우 낮은 랜덤을 사용해야 한다.
The primary purpose of the IV is to be a nonce, that is, to be distinct for each invocation of the encryption operation for a fixed key. It is acceptable for the IV to be generated randomly, as long as the distinctness of the IV values for each key is highly likely - GCM Tag 길이
128bit 이 선호 된다
아래는 Java Spring 구현코드
import jakarta.annotation.PostConstruct;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
@Component
public class EncryptionUtil {
// @Value("${encrypt.key}")
private String key = "v8y/B?E(H+MbQeThWmZq3t6w9z$C&F)J";
public static final int GCM_IV_LENGTH = 12;
public static final int GCM_TAG_LENGTH = 128;
private static final SecureRandom secureRandom = new SecureRandom();
private SecretKeySpec keySpec;
@PostConstruct
private void initializeKeySpec() {
this.keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
}
public String encrypt(String plainText) {
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
// Generate Random IV
byte[] IV = new byte[GCM_IV_LENGTH];
this.secureRandom.nextBytes(IV);
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, IV);
// Initialize Cipher for ENCRYPT_MODE
cipher.init(Cipher.ENCRYPT_MODE, this.keySpec, gcmParameterSpec);
// Perform Encryption
byte[] cipherText = cipher.doFinal(plainText.getBytes());
return Base64.encodeBase64String(combineBytes(IV, cipherText));
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
byte[] combineBytes(byte[] a, byte[] b) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(a);
outputStream.write(b);
byte[] result = outputStream.toByteArray();
return result;
}
public String decrypt(String encrypted) {
try {
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
// Separate IV and cipherText
byte[] IV = Base64.decodeBase64(encrypted.substring(0, 16));
byte[] cipherText = Base64.decodeBase64(encrypted.substring(16));
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, IV);
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, this.keySpec, gcmParameterSpec);
// Perform Decryption
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}
728x90
'Infra > 보안' 카테고리의 다른 글
Oauth 2.0 (feat. Oauth 1.0) (0) | 2023.05.21 |
---|---|
cookie vs localstorage (0) | 2023.02.01 |
SSL 이란? (0) | 2022.04.24 |
댓글