2014-02-17 6 views
1

내 구현의 Salting 및 SHA-512 해싱 암호가 정확하고 안전합니까?내 Salting 및 SHA-512 해싱 암호의 구현이 정확하고 안전합니까?

소금에 절인 암호에서 알고리즘을 두 번 반복해야한다는 것을 알고 있습니다. 그 외에도 내가 보안을 강화하기 위해 구현해야하는 것은 무엇입니까? 아니면 이것으로 충분합니까?

 public static String[] SHA512(String password) 
{ 
    //Generates the salt 
    SecureRandom saltRandomizer = new SecureRandom(); 
    byte[] salt = new byte[64]; //The same size as the output of SHA-512 (512 bits = 64 bytes) 
    saltRandomizer.nextBytes(salt); 
    String encodedSalt = Base64.encodeToString(salt, Base64.DEFAULT); 


    //Prepends the salt to the password 
    String saltedPassword = encodedSalt + password; 

    //Hashed the salted password using SHA-512 
    MessageDigest digester; 
    byte[] digest = null; 
    try { 
     digester = MessageDigest.getInstance("SHA-512"); 
     digester.reset(); 
     digester.update(saltedPassword.getBytes()); 
     digest = digester.digest(); 
    } catch (NoSuchAlgorithmException e) { 
     System.out.println("No such algorithm"); 
     e.printStackTrace(); 
    } 

    String[] passwordPlusSalt = new String[2]; 
    passwordPlusSalt[0] = Base64.encodeToString(digest, Base64.DEFAULT); 
    passwordPlusSalt[1] = encodedSalt; 
    return passwordPlusSalt; 
} 

미리 감사

+0

나쁘지 보이지 않는 - 난 그냥 사용하는 것이 정직 [jBCrypt] (HTTP ://www.mindrot.org/projects/jBCrypt/). 그것은 소금으로 해싱, 소금 저장 및 검증을 다룹니다. 모든 코드를 직접 작성하는 것은 화재로 노는 것과 같습니다. –

+1

반복의 부족은 큰 결함입니다. "한 쌍"만 아니라 10000 번 반복해야합니다. (당신이 * slight * understatements의 팬이 아니라면). – CodesInChaos

답변

6

아니요. 안전하지 않습니다. 다음 라인을 살펴보십시오.

SecureRandom saltRandomizer = new SecureRandom(); 

PRNG 또는 제공 업체를 지정하지 않았 음을 확인합니다. 나는 전문가는 아니지만 SUN CSP 기본값이 Solaris 및 Linux에서 sun.security.provider.NativePRNG를 사용한다는 것을 이해합니다. Solaris 및 Linux에서는 단순히/dev/urandom의 출력을 제공하므로 사용자의 요구에 적합 할 수도 있고 그렇지 않을 수도 있습니다 (예를 들어 암호 키를 생성하는 것은 권장되지 않습니다. 다음과 같이

그것은 따라서 항상 PRNG와 공급자를 지정하는 것이 좋습니다 :

주기적으로
  • 기존 java.security.SecureRandom의 인스턴스를 던져 : 또한

    SecureRandom.getInstance("SHA1PRNG", "SUN"); 
    

    , 그것은하는 것이 좋습니다 새로운 것을 만들 수 있습니다. 그러면 새로운 시드로 새 인스턴스가 생성됩니다.

  • java.security.SecureRandom.setSeed (java.security.SecureRandom.generateSeed (int))를 호출하여 주기적으로 PRNG 시드에 새 무작위 재료를 추가합니다.

내가 만들고있는 요점은 보안이 잘못 될 수있는 복잡한 주제라는 것입니다.해결책을 시도하고 자발적으로 시도하지 마십시오. 기존 라이브러리를 사용하십시오. Thomas Pornin의 훌륭한 대답을 인용하십시오.

복잡성이 좋지 않습니다. 집에서 만드는 것이 나쁘다. 새로운 것은 나쁘다.

출처 :

+2

'/ dev/urandom'은 일반적으로 암호화 키를 생성하는 데 적합합니다. 다시 시드하는 것도 그다지 중요하지 않지만 OP가 각 호출에 대해 새로운 인스턴스를 생성하기 때문에 확실히 다시 시드됩니다. – CodesInChaos

+0

@CodesInChaos - 위키 백과에서 '/ dev/urandom ... 장기 암호화 키를 생성하는 것은 바람직하지 않습니다.' – hoipolloi

+0

그는 소금에 사용하고 있습니다. 그래서 나는 암호의 무작위성이 필요하다고 생각하지 않습니다. 지옥, 소금은 해시가 유출 될 것으로 예상됩니다. –

2

에서 나는 소금 응용 프로그램을 확보하고 높은 보안 수준을 액세스하기위한 좋은 단계로 조치를 취하는 것은 암호를 해시 생각합니다. 그러나 구현에 문제가 있습니다 :

  • 난수 바이트 생성을위한 씨앗을 사용하지
  • 알고리즘을 추가하지 않습니다 문자열 연결을 사용하여 암호 확인
  • 을 위해 그들을 사용하기 위해 생성 된 난수 바이트를 추적하지 복잡하지만 보안이 중요한 환경에서는 비효율적 인 것으로 입증 된 모호함으로 보입니다.

대신 HMAC 표준 알고리즘을 사용하십시오. Java 7에서 지원하는 알고리즘 목록은 here입니다. PBKDF2WithHmacSHA1은 좋은 선택입니다. 그것은 단순히 다음과 같이 사용할 수 있습니다

PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8); 
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
byte[] secretPassword = skf.generateSecret(spec).getEncoded(); 

전체 작업 코드

here를 찾을 수 있습니다. 암호 데이터베이스가 잘못 처리되는 경우 무차별 공격/사전 공격의 영향을 제한해야합니다.

소금은 중요한 고리입니다. 보안 요구 사항에 따라 별도의 파일 시스템에 저장하거나 서버를 시작할 때 입력하거나로드 할 수 있습니다. 심지어 안전성을 유지할 수있는 전문화 된 (일반적으로 비싼) 하드웨어 보안 모듈이있을 수 있습니다.

+0

미래에 링크가 무효화 될 경우에 대비하여 인용 소스에서 중요한 부분을 추출 할 수 있다면 좋을 것입니다. 링크 만 공유하려면 댓글로 대신 게시하십시오. – dst

+0

당신이 말하는 부분에 좀 더 구체적으로 설명해 주시겠습니까? 감사합니다 – Aurum

+0

@dst 당신 말이 맞아요. 내 대답을 편집하여 세부 정보를 추가하고 코드 스 니펫을 포함했습니다. –