1. 개요
이 사용방법(예제)에서는 암호 해싱의 중요성에 대해 설명합니다.
우리는 그것이 무엇인지, 왜 중요한지, 그리고 자바에서 그것을 수행하는 몇 가지 안전하고 안전하지 않은 방법에 대해 간단히 살펴볼 것입니다.
2. 해싱이란 무엇입니까?
해싱 은 암호화 해시 함수 로 알려진 수학적 함수를 사용하여 주어진 메시지 에서 문자열 또는 해시 를 생성하는 프로세스입니다 .
여러 해시 기능이 있지만 해싱 암호에 맞게 조정 된 기능은 Security을 유지하기 위해 4 가지 주요 속성을 가져야합니다.
- 결정적 이어야합니다 . 동일한 해시 함수로 처리 된 동일한 메시지는 항상 동일한 해시를 생성 해야합니다.
- 되돌릴 수 없습니다 . 해시 에서 메시지 를 생성하는 것은 비현실적입니다.
- 엔트로피 가 높음 : 메시지 를 조금만 변경 하면 매우 다른 해시 가 생성됩니다.
- 그리고 충돌에 저항합니다 . 두 개의 다른 메시지 가 동일한 해시를 생성해서는 안됩니다.
네 가지 속성을 모두 포함하는 해시 함수는 함께 해시에서 암호를 리버스 엔지니어링하는 데 어려움을 극적으로 증가시키기 때문에 암호 해싱에 대한 강력한 후보입니다.
또한 암호 해싱 기능은 느려 야합니다 . 빠른 알고리즘은 해커가 초당 수십억 개 ( 또는 수조 개 )의 잠재적 암호 를 해싱하고 비교하여 암호를 추측하는 무차별 대입 공격 을 지원 합니다.
이러한 모든 기준을 충족하는 몇 가지 훌륭한 해시 함수는 PBKDF2, BCrypt 및 SCrypt입니다. 하지만 먼저 오래된 알고리즘과 더 이상 권장되지 않는 이유를 살펴 보겠습니다.
3. 권장하지 않음 : MD5
첫 번째 해시 함수는 1992 년에 개발 된 MD5 메시지 다이제스트 알고리즘입니다.
Java의 MessageDigest를 사용하면이를 쉽게 계산할 수 있으며 다른 상황에서도 유용 할 수 있습니다.
그러나 지난 몇 년 동안 MD5는 충돌 생성이 계산적으로 쉬워 졌다는 점에서 네 번째 암호 해싱 속성 에 실패한 것으로 밝혀졌습니다 . 게다가 MD5는 빠른 알고리즘이므로 무차별 대입 공격에 대해 쓸모가 없습니다.
이 때문에 MD5는 권장되지 않습니다.
4. 권장하지 않음 : SHA-512
다음으로 1993 년에 SHA-0으로 시작된 제품군 인 Secure Hash Algorithm 제품군의 일부인 SHA-512를 살펴 보겠습니다.
4.1. 왜 SHA-512입니까?
컴퓨터의 성능이 향상되고 새로운 취약점이 발견되면 연구원은 새로운 버전의 SHA를 도출합니다. 최신 버전은 점진적으로 더 긴 길이를 갖거나 때로는 연구원이 새로운 버전의 기본 알고리즘을 게시합니다.
SHA-512는 알고리즘의 3 세대에서 가장 긴 키를 나타냅니다.
하지만 지금은 SHA의 더 안전한 버전이 , SHA-512은 자바로 구현되는 강력한입니다 .
4.2. 자바로 구현
이제 Java에서 SHA-512 해싱 알고리즘을 구현하는 방법을 살펴 보겠습니다.
먼저 소금 의 개념을 이해해야합니다 . 간단히 말해서, 이것은 각각의 새로운 해시에 대해 생성되는 랜덤의 시퀀스입니다 .
이 임의성을 도입함으로써 해시의 엔트로피를 증가시키고 레인보우 테이블 로 알려진 사전 컴파일 된 해시 List으로부터 데이터베이스를 보호합니다 .
새로운 해시 함수는 대략 다음과 같습니다.
salt <- generate-salt;
hash <- salt + ':' + sha512(salt + password)
4.3. 소금 생성
솔트를 소개하기 위해 java.security 의 SecureRandom 클래스를 사용할 것입니다 .
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
그런 다음 MessageDigest 클래스를 사용하여 솔트로 SHA-512 해시 함수 를 구성합니다 .
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(salt);
그리고이를 추가하여 이제 다이제스트 메서드를 사용하여 해시 된 암호를 생성 할 수 있습니다 .
byte[] hashedPassword = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
4.4. 권장되지 않는 이유는 무엇입니까?
소금과 함께 사용하는 경우, SHA-512은 여전히 공정한 옵션입니다 , 하지만 거기 강하고 느린 옵션이 있습니다 .
또한 우리가 다룰 나머지 옵션에는 구성 가능한 강도라는 중요한 기능이 있습니다.
5. PBKDF2, BCrypt 및 SCrypt
PBKDF2, BCrypt 및 SCrypt는 세 가지 권장 알고리즘입니다.
5.1. 권장되는 이유는 무엇입니까?
이들 각각은 느리고 각각 구성 가능한 강도를 갖는 뛰어난 기능을 가지고 있습니다.
이것은 컴퓨터의 강도가 증가함에 따라 입력을 변경하여 알고리즘을 늦출 수 있음을 의미합니다 .
5.2. 자바에서 PBKDF2 구현
이제 솔트는 암호 해싱의 기본 원칙 이므로 PBKDF2에도 솔트가 필요합니다.
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
다음으로 PBKDF2WithHmacSHA1 알고리즘을 사용하여 인스턴스화 할 PBEKeySpec 및 SecretKeyFactory 를 생성 합니다.
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
세 번째 매개 변수 ( 65536 )는 사실상 강도 매개 변수입니다. 이 알고리즘이 실행되는 반복 횟수를 나타내므로 해시를 생성하는 데 걸리는 시간이 늘어납니다.
마지막으로 SecretKeyFactory 를 사용하여 해시를 생성 할 수 있습니다 .
byte[] hash = factory.generateSecret(spec).getEncoded();
5.3. Java에서 BCrypt 및 SCrypt 구현
따라서 일부 Java 라이브러리에서 지원하지만 BCrypt 및 SCrypt 지원은 아직 Java와 함께 제공되지 않습니다 .
이러한 라이브러리 중 하나는 Spring Security입니다.
6. 스프링 Security으로 암호 해싱
Java는 기본적으로 PBKDF2 및 SHA 해싱 알고리즘을 모두 지원하지만 BCrypt 및 SCrypt 알고리즘은 지원하지 않습니다.
다행스럽게도 Spring Security는 PasswordEncoder 인터페이스 를 통해 이러한 모든 권장 알고리즘에 대한 지원을 제공합니다.
- MessageDigestPasswordEncoder 는 MD5 및 SHA-512를 제공합니다.
- Pbkdf2PasswordEncoder 는 PBKDF2를 제공합니다.
- BCryptPasswordEncoder 는 BCrypt를 제공하고
- SCryptPasswordEncoder 는 우리에게 SCrypt를 제공합니다.
PBKDF2, BCrypt 및 SCrypt 용 암호 인코더는 모두 원하는 암호 해시 강도를 구성 할 수 있도록 지원합니다.
Spring Security 기반 애플리케이션이 없어도 이러한 인코더를 직접 사용할 수 있습니다. 또는 Spring Security로 사이트를 보호하는 경우 DSL 또는 의존성 주입을 통해 원하는 암호 인코더를 구성 할 수 있습니다 .
그리고 위의 예와 달리 이러한 암호화 알고리즘은 내부적으로 우리를 위해 솔트를 생성합니다 . 알고리즘은 나중에 암호 유효성 검사에 사용하기 위해 출력 해시 내에 솔트를 저장합니다.
7. 결론
그래서 우리는 암호 해싱에 대해 심층적으로 살펴 보았습니다. 개념과 그 용도를 탐구합니다.
그리고 우리는 Java로 코딩하기 전에 일부 역사적인 해시 함수와 현재 구현 된 일부 함수를 살펴 보았습니다.
마지막으로, Spring Security는 다양한 해시 함수 배열을 구현하는 암호 암호화 클래스와 함께 제공됩니다.
항상 그렇듯이 코드는 GitHub에서 사용할 수 있습니다.