오늘은 SHA-256 해시 알고리즘을 다뤄보려고 한다.
암호화에 대한 기본 개념은 이전 글을 참고 바랍니다.
암호화
서비스를 제작할 때 암호화 알고리즘을 사용하는 경우는 많이 있다. 누구나 접근 가능한 서버와 통신을 하는 경우 통신 과정에서 데이터를 노출하지 않도록 암호화를 한다. 또 로그 파일이나 DB
corinprodo.tistory.com
아래 사이트를 참고했다.
http://wiki.hash.kr/index.php/SHA256
SHA256 - 해시넷
SHA-256은 SHA(Secure Hash Algorithm) 알고리즘의 한 종류로서 256비트로 구성되며 64자리 문자열을 반환한다. SHA-256은 미국의 국립표준기술연구소(NIST; National Institute of Standards and Technology)에 의해 공표된
wiki.hash.kr
SHA-256
Secure Hash Algorithm의 약자로 256비트로 구성되어 이 알고리즘을 통해 암호화를 하면 총 2의 256승 만큼의 경우의수를 표현할 수 있다. 문자열로는 64자리 문자열을 나타낸다. 미국 국립표준기술연구소(NIST; National Institute of Standards and Technology)에 의해 공표된 표준 해시 알고리즘인 SHA-2 계열 중 하나이며, 최근에는 블록체인 기술에서도 심심찮게 접할 수 있는 알고리즘이다.
이제 중요한 특성을 간략하게 정리해 보겠다.
특성
- 단방향 알고리즘이다. (복호화가 되지 않는다.)
- 위와 같은 특성 때문에 서비스에서는 복호화할 필요가 없는 개인정보에 주로 사용한다.
- 같은 입력값에 대해 같은 출력값을 제공한다.
- 다른 입력값에 대해 출력값이 같은 경우를 충돌이라고 하는데, 이는 발생할 확률이 지극히 낮고, 현재까지 안전성 문제에서도 큰 단점이 발견되지 않았다.
- 따라서, 데이터의 변경 여부를 파악하는데 사용한다.
- 연산 속도가 빠르다
- 암호화된 값을 찾는데도 연산이 빠르기 때문에 검증 횟수를 제한하는 등의 조치가 필요하다.
- 안전성이 높다.
- 구글 클라우드 서버 기반으로 연구한 사례로 900경의 해시 연산을 통해 충돌이 발견된 경험이 있다고 한다.
- 양자 컴퓨터가 출시되지 않는 한 최소 10년은 안전하다고 판단할 수 있다고 한다.
Java 예제
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SHATest{
public static void main(String[] args) throws Exception {
public static String encrypt(String plainText) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(plainText.getBytes(StandardCharsets.UTF-8));
StringBuilder sb = new StringBuilder();
byte[] bytes = md.digest();
for(byte b : bytes) {
builder.append(String.format("%02x", b));
}
return sb.toString();
}
}
}
java.security 패키지의 MessageDigest 클래스를 이용해 SHA-256 암호화를 할 수 있다.
String.format 함수를 이용해서 byte를 hex 문자열로 표현하는 것이다. 이 때 x를 대문자 X로 쓰면 hex도 대문자로 출력된다.
다만 위 예시에서 문제될 수 있는 점은 평문의 길이가 짧거나 예상 가능한 경우 이미 원본에 대한 해시값이 1:1로 매핑된 데이터베이스가 있다면 위험할 수 있다는 것이다. 이를 레인보우 테이블이라고 한다.
이를 보완하는 방법이 평문에 salt를 합친 문자열을 암호화 하는 것이 있다.
salt는 해시 함수에서 digest를 생성할 때 추가되는 임의의 문자열이다. 원본에 추가해서 암호화하기 때문에 위에서 말한 레인보우 테이블에 포함될 가능성이 줄어들고 안전해진다.
예를 들어 비밀번호를 평문이라고 한다면, 랜덤한 문자열 salt를 만들고 합하여 암호화한 뒤 DB에 저장하는 것이다. 이때 생성한 salt도 다른 곳에 저장해야 다시 비밀번호 일치여부를 확인할 때 암호화하여 DB에 저장된 것과 일치하는지 확인할 수 있다.
아래는 salt를 적용한 예시이다.
Salt 포함 예제
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SHATest{
public static void main(String[] args) throws Exception {
public static String encrypt(String plainText) throws NoSuchAlgorithmException {
SecureRandom random = new SecureRandom();
byte[] saltBytes = new byte[16]
random.nextBytes(saltBytes);
StringBuilder saltSb = new StringBuilder();
for(byte b : saltBytes) {
saltSb.append(String.format("%02x", b));
}
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(saltSb.append(plainText).toString().getBytes(StandardCharsets.UTF-8));
StringBuilder sb = new StringBuilder();
byte[] bytes = md.digest();
for(byte b : bytes) {
builder.append(String.format("%02x", b));
}
return sb.toString();
}
}
}
오늘은 이만 끝!
'알고리즘' 카테고리의 다른 글
[암호화] SEED 암호화 (0) | 2022.12.11 |
---|---|
암호화 (0) | 2022.11.28 |