홈페이지가 일반에 많이 보급되고 막 사용되기 시작할 무렵에는 회원가입시 패스워드를

그냥 데이터베이스 필드로 저장했다.

비밀번호를 잊은 사용자에게 바로 찾아줄 수 있는 편리함이 있었지만 해킹당할 경우

패스워드가 그대로 노출된다는 치명적인 단점이 있었다.

그래서 시간이 지나자 프로그래머들은 패스워드를 암호화(정확히는 해쉬)하여 저장하기 시작했다.

그리고 로그인시에 사용자가 입력한 값을 똑같이 해쉬화 한 후 위의 저장된 비밀번호 해쉬 값과 대조해

같으면 인증되는 방식이었다. 안전하다 생각하여 지금도 많이 쓰이고 있지만 여기에도 한 가지 단점이 있다.

바로 비밀번호가 같은 사용자는 해쉬 값도 같다는 것이다. 만약 이런 레코드가 많으면 많아질수록 해당 계정은

비밀번호를 유추해 낼 수 있다는 것이다.


그래서 나온것이 Password Salt 생각보다 어려운 개념이 아니다.

같은 비밀번호를 해쉬할 경우 같은 해쉬값이 나온다. 간단하게 비밀번호를 다르게 해주면 된다.

그렇다고 사용자가 입력한 비밀번호를 바꿀 순 없다.

대신 랜덤으로 생성한 코드를 비밀번호와 섞어서 해쉬화를 하는 것이다. 이 때 사용되는 랜덤으로 생성한 코드를 Password Salt 라 부른다.

아래는 Salt를 생성하는 VB 코드 샘플이다. MSDN 참조


Private Shared Function CreateSalt(size As Integer) As String
    Dim rng As New RNGCryptoServiceProvider
    Dim buff(size) As Byte
    rng.GetBytes(buff)

    Return Convert.ToBase64String(buff)
End Function

먼저 아래와 같이 테이블을 생성한다.

CREATE TABLE [dbo].[Membership](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Email] [nvarchar](256) NULL,
	[Password] [nvarchar](128) NULL,
	[PasswordSalt] [nvarchar](128) NULL,
	[CreateDate] [smalldatetime] NULL,
	[LastLoginDate] [smalldatetime] NULL
)

그리고 회원가입시 Password Salt를 생성하고 사용자가 입력한 비밀번호를 아래의 함수를 통해 해쉬해서

INSERT 한다.

Private Shared Function CreatePasswordHash(pwd As String, salt As String)
    Dim saltAndPwd As String = String.Concat(pwd, salt)
    Dim hashedPwd As String = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPwd, "sha1")
    Return hashedPwd
End Function

유저 쿼리는 아래와 같이 처리하면 된다.

SELECT * 
FROM dbo.Membership 
WHERE Email = @email AND
	[Password] = CONVERT(NVARCHAR(128), 
	HASHBYTES('SHA1', CONVERT(VARCHAR, @pwd) + (SELECT PasswordSalt FROM Membership WHERE Email = @email)),
	2)

예제는 단순히 비밀번호 뒤에 Salt를 붙여서 해쉬를 하고 있지만 조금 더 복잡한 패턴을 만들어 적용시키면 강력한 패스워드 시스템을 만들 수 있다.