2015-01-08 2 views
1

암호 해시 저장을 시뮬레이션하고 로그인 프로세스에서 유효성을 검사합니다.소금으로 해시 된 암호 저장 및 유효화

나는 hashPassword(String password)이라는 메서드를 사용하여 문자열 암호를 가져오고 소금 추가로 해시를 반환합니다. 이 두 값이 아닌 이유

what stores in DB: [[email protected] 
Users hashed password: [[email protected] 
Incorrect 

:

나는 소금에게 정적 값을 선택하고이 예제에서는 암호 (hello123)

public class T1 { 

public static void main(String[] args) { 
    String userDefinedPassword = "hello123"; 
    String hashedPassToStoreInDB = String.valueOf(hashPassword(userDefinedPassword)); 
    System.out.println("what stores in DB: " + hashedPassToStoreInDB); 
    // store in database 

    //Password Verify 
    String inputPassword = "hello123"; 
    String hashedInputPassword = String.valueOf(hashPassword(inputPassword)); 
    System.out.println("Users hashed password: " + hashedInputPassword); 

    if (hashedPassToStoreInDB.equals(hashedInputPassword)) { 
     System.out.println("Correct"); 
    } else { 
     System.out.println("Incorrect"); 
    } 
} 

private static byte[] hashPassword(String password) { 
    byte[] salt = new byte[16]; 
    byte[] hash = null; 
    for (int i = 0; i < 16; i++) { 
     salt[i] = (byte) i; 
    } 
    try { 
     KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128); 
     SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
     hash = f.generateSecret(spec).getEncoded(); 

    } catch (NoSuchAlgorithmException nsale) { 
     nsale.printStackTrace(); 

    } catch (InvalidKeySpecException ikse) { 
     ikse.printStackTrace(); 
    } 
    return hash; 
} 
} 

에 대한 동일한 값을 선택하지만 결과는 같은?

내 코드가 잘못되었습니다.

+0

: 당신은 문자열 대신 문자 배열로 암호를 처리해야 그런 다음, 단지 문자열을 결합하여 작업 결과에 hashCode()를 사용하여 기본 소금을 얻을 수 있습니다 : 참조 [여기] (http://stackoverflow.com/questions/8881291/why-is-char-preferred-over-string-for-passwords) – jHilscher

답변

2

문제는 여기에 있습니다 : 여기

String hashedPassToStoreInDB = String.valueOf(hashPassword(userDefinedPassword)); 

과 :

String hashedInputPassword = String.valueOf(hashPassword(inputPassword)); 

당신은 hashPassword 방법에서 반환 된 byte[]에서 String를 작성하지만 잘못된 방법을 사용하고 있습니다. 에 대한 과부하는 String#valueOf 메서드이므로 내부적으로 Object#toString을 사용하는 String#valueOf(Object obj) 호출을 종료하며 배열 자체의 문자열 표현은 의미가 없습니다.

대신 new String(byte[] byteArray)을 사용하십시오.

String hashedPassToStoreInDB = new String(hashPassword(userDefinedPassword)); 
//... 
String hashedInputPassword = new String(hashPassword(inputPassword)); 
+0

예, '정답'메시지가 나타나지만 콘솔에' ; {O | . = "'why? –

+1

@ user3808021}이 표시됩니다. 일부'byte'는 적절한'char' 값으로 표현 될 수 없기 때문입니다 콘솔이나 텍스트 파일 (예 : 0에서 32 사이의 'byte'값)에 저장하십시오. –

+0

음,이 해시 된 암호를'String' 또는'byte'로 데이터베이스에 저장하는 것이 더 좋습니까? –

0

Object.toString 다음에 String 표현이 오는 byte[] 배열의 두 개의 다른 인스턴스를 생성 중입니다.

그러므로 두 개의 byte[]의 해시가 다릅니다.

대신 Arrays.equals(yourSaltedPassword, yourOtherSaltedPassword)을 사용해보십시오. 예를 들어

: 당신이 String들로 byte[]의를 저장해야하는 경우 Arrays.toString(myByteArray)와 (동일 byte[] 초 동안) 동등하게 그들을 대표 할 수

false 
false 
true 

byte[] foo = {1,2}; 
byte[] bar = {1,2}; 
System.out.println(foo == bar); 
System.out.println(String.valueOf(foo).equals(String.valueOf(bar))); 
System.out.println(Arrays.equals(foo, bar)); 

출력.

두 개의 동일한 암호 간의 비교는 String과 같습니다.

+0

그래서, 데이터베이스에'바이트'사용자 해시 비밀 번호를 저장해야합니다, 'String'이 아니라 올바른가? –

+1

@ user3808021 아니요, ['new String (byte [])'] (http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#String-byte)을 사용해야합니다. : A-) 생성자 대신에'String # valueOf (byte [])'를 사용합니다. –

+0

@ user3808021 테스트/학습용으로 가정하면 (즉, 실제 보안이 범위를 벗어남) 'Arrays.toString (yourByteArray)'를 저장할 수 있습니다. 그런 다음 비교는 동일하게 반환됩니다. – Mena

0

자바 배열이 toString을 재정의하지 않는다는 사실을 발견했습니다.

버그를 사용하는 이유 배열 : 보조 노트에

int hash = (password + salt).hashCode();