달달한 스토리

728x90
반응형

 

안녕하세요. 이제

 

금연 설루션 그만 앱 프로젝트에 막바지가 왔습니다.

 

애드몹 광고를 달고 진작해야 했던,

 

데이터베이스에 비밀번호를

 

해시화하는 작업이 필요했다.

 

어려울 것이라고 고민했다.

 

서버단은 서로 통신하는 법만 간단히 알고 있지,

 

비밀번호를 보안성 있게 해시화하는 법은 아마 어렵지 않을까 생각이 들었다.

 

여러 방법들이 있겠지만,

 

내가 찾은 방법은 

 

SHA-2이다.

 

SHA-2는 Secure Hash Algorithm의 약자이다.

 

해시 알고리즘은 값을 입력받아, 고정된 길이의 해시값(64, 128) 등등으로 해시값을

 

출력하는 알고리즘이다.

 

암호 알고리즘에는 키가 사용되고,

 

알고리즘 함수는 키를 사용하지 않습니다.

 

그래서 같은 입력에 대해 항상 같은 출력이 나오게 된다.

 

이 알고리즘을 쓰는 이유는 동일한 값을 살피고,

 

비밀번호 등의 위조를 감지할 수 있는 무결성을 갖기 위함이다.

 

해시함수가 출력하는 압축된 문장을 다이제스트라고 합니다.

 

이 SHA-2가 생성하는 출력하는 다이제스트의 출력 길이는

 

224, 256, 384, 512비트입니다.

 

SHA-2의 256bit 버전을 SHA-256이라고 부르고,

 

SHA-2 512bit 버전을 SHA-512라고 부릅니다.

 

오늘 제가 사용한 것은 512bit 버전입니다.

 

현재 256 버전은 Collision Attack (충돌 공격) 공격에 41~64라운드를 통과하면 공격에 안전한 것으로 간주하고,

 

512 버전은 46~ 80라운드를 통과해야 공격으로부터 안전한다고 판단한다고 한다.

 

출처  :  https://interconnection.tistory.com/118

 

그래서 나는 더 안전하다는 512를 선택했다.

 

우선 안드로이드에서 Volley로 통신하였으며,

 

php구문을 통해 데이터 베이스에 값을 전달해보자.


해시화

public class SHA516_Hash_InCode {

    public String SHA516_Hash_InCode(String pwd) {
        try{
            String hexSapassword = pwd;
            String mixPassword = hexSapassword;
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
            messageDigest.reset();
            messageDigest.update(mixPassword.getBytes("utf8"));
            String enPassword = String.format("%0128x", new BigInteger(1, messageDigest.digest()));
            //출력
            return enPassword;
        } catch(Exception ex){
            throw new RuntimeException(ex);
        }
    }
}

 

우선 해시화가 되는 클래스를 만들어 준다.

 

이것은 512지만, 혹시나 256 버전을 쓰는 사람을 256 버전도 올려놓겠다.

 

// 해싱에 사용할 값
String mixPassword = hexSaltTime + password;

// 해싱을 하기 위해서는 MessageDigest Class를 사용합니다.
// MessageDigest Algorithm은 MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512 을 사용가능합니다.
// 여기서는 SHA-256 Algorithm을 사용합니다.
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");

// 값을 해싱하기 전에 reset을 통해서 해싱 인스턴스를 초기화합니다.
messageDigest.reset();

// utf8 character set으로 해싱에 사용할 값을 바이트코드로 변환하여 해싱 인스턴스에 업데이트합니다.
messageDigest.update(mixPassword.getBytes("utf8"));

// 위 과정에서 셋팅된 값을 최종적으로 digest() 함수를 통해서 해싱값을 생성합니다.
// 그리고 %064x에서 x는 16진수이고, 총 64자리의 16진수에서 값이 들어가지 못한 자리는 0으로 채워지게 됩니다.
// 최종적으로 SHA-256 해싱된 값이 16진수로 64바이트로 나오게됩니다.
// enPassword가 최종적으로 나온 해싱 결과값입니다.
String enPassword = String.format("%064x", new BigInteger(1, messageDigest.digest()));

출처: https://interconnection.tistory.com/118 [라이언 서버]

 

 

자 그러면 저 512를 호출하여, 회원가입 시에 해시화를 우선 보겠다.

 

Resister.php

<?php 
    $con = mysqli_connect("서버아이피주소", "아이디", "비밀번호", "아이디");
    mysqli_query($con,'SET NAMES utf8');

    $num = $_POST["num"];
    $id = $_POST["id"];
    $pw = $_POST["pw"];
    $name = $_POST["name"];
    $email = $_POST["email"];
    $datetime = $_POST["datetime"];
    $cigacount = $_POST["cigacount"];
    $cigapay = $_POST["cigapay"];
    $goal = $_POST["goal"];
    $firstcheck = $_POST["firstcheck"];

    //먼저 비밀번호 솔팅 하기
    $salted = "sooyeolBestDeveloperEver".$pw."inyoungBestWomanIntheWorld";

    //비밀번호 해시처리하기
    $hashed = hash('sha512', $salted);
    

    $statement = mysqli_prepare($con, "INSERT INTO USER VALUES (?,?,?,?,?,?,?,?,?,?)");
    mysqli_stmt_bind_param($statement, "isssssiisi", $num, $id, $hashed, $name, $email, $datetime, $cigacount, $cigapay, $goal, $firstcheck);
    mysqli_stmt_execute($statement);

    $response = array();
    $response["success"] = true;


     echo json_encode($response);

     echo $hashed;

?>

 

우선 회원가입 php구문이다.

 

여기서 먼저 여러 회원정보를 불러들이지만,

 

비밀번호만 암호화를 하면 되기 때문에

 

비밀번호 양쪽에 솔팅을 해준다.

 

salting(솔팅) : 솔팅이란 소금을 뿌려준다는 의미이지만, 서버에서 보안을 위해

 

한 단계 더 강화하고자, 자신만의 암호를 한 번 더 둘러 싸주는 것이다.

 

[php에서는.(이 점이 java에서는 + 역할을 해주어 문자끼리 연결이 가능하다(append))]

 

$salted = "솔팅해줄 문자(원하는 거 아무거나)".$pw."솔팅해줄 문자(원하는 거 아무거나)";

 

//먼저 비밀번호 솔팅 하기
    $salted = "sooyeolBestDeveloperEver".$pw."inyoungBestWomanIntheWorld";

 

이런 식으로 말이다.

 

다르게 변형을 해서 넣으니 그 점은 본인의 취향대로 입력하길 바란다.

 

자 이제 이 솔팅된 암호를 512로 해시화 해보자.

 

//비밀번호 해시처리하기
    $hashed = hash('sha512', $salted);
    
    //SHA 256은  
    $hashed = hash('sha256', $salted);

이런 식으로 salted를 파라미터에 넣어주고,

 

512로 바꾸어준다.

 

256을 쓰는 분들은 아래처럼 바꾸어준다.

 

그리고, 위에 php 마지막 구문에 해쉬화 된

 

$hashed를  mysqli_stmt_bind_param의 파라미터에 $pw 대신 넣어준다.

 

그렇다면 이 열이 저장된 데이터 베이스를 한 번 보자.

 

 

보면 이런 식으로 해시 화가 되어있다.

 

이러면 누군가 이 문자를 해석하기 어렵다는 것이다.

 

말 그대로 복호화가 힘들게 만드는 것이다.

 

복호화란 : 암호가 인코딩 되기 전 상태로 돌리는 디코딩화를 말한다.

 

그러면 여기서 의문이 든다.

 

우리는 저 문자를 어떻게 읽으면 좋을까?

 

저 문자를 원래 상태로 되돌릴 순 없어도,

 

저 자체로 읽어서 비밀번호를 가져오면 되는 것이다.

 

회원가입을 할 때,

 

비밀번호에 솔팅을 하고 해시화를 했으니,

 

로그인을 할 때는 솔팅하고 해시화 된 저 비밀번호 자체를

 

식별하면 되는 것이다.

 

조금 복잡하게 느껴질 수도 있다.

 

쉽게 설명하기 위해 그림을 그려보았다.

 

(형편없어도 이해해주면 좋겠다.)

 

 

한 마디로 안드로이드 자바에서 애초에 비밀번호를 해시화 해 버린 다음에

 

서버로 보내버리는 것이다.

 

 	public class Login extends AppCompatActivity {
    
    private String saltHash;
    private String hashPw;
    private Button btn_login;
    pribate TextView idText, passwordText;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login_fistpage);
        
        btn_login = findViewById(R.id.login);
        idText = findViewById(R.id.idtext);
        passwordText = findViewById(R.id.PSText);
        
 	btn_login.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    String id = idText.getText().toString();
                    String pw = passwordText.getText().toString();

                    /** 비밀번호 해시화 중요(보안)*/
                    //서버에서 솔팅한 값
                    saltHash = "sooyeolBestDeveloperEver"+ pw +"inyoungBestWomanIntheWorld";
                    SHA516_Hash_InCode hash_inCode = new SHA516_Hash_InCode();
                    hashPw = hash_inCode.SHA516_Hash_InCode(saltHash); //솔팅한 값 해시화한 값
                    
                    Response.Listener<String> responseListener = new Response.Listener<String>() {

                        @Override
                        public void onResponse(String response) {
                            try {
                                JSONObject jsonObject = new JSONObject(response);
                                boolean success = jsonObject.getBoolean("success");

                                if (success) {//로그인 성공시
                                            Intent intent = new Intent(Login.this, Startbutton.class);
                                            startActivity(intent);
                                            finish();
                               
                                } else {//로그인 실패시
                                    Toast.makeText(getApplicationContext(), "아이디/비밀번호를 확인해주세요.", Toast.LENGTH_SHORT).show();
                                    return;
                                }

                            } catch (JSONException e) {
                                e.printStackTrace();
                                Toast.makeText(getApplicationContext(), "아이디/비밀번호를 확인해주세요.", Toast.LENGTH_SHORT).show();
                                return;
                            }
                        }
                    };
                    LoginRequest loginRequest = new LoginRequest(id, hashPw, responseListener);
                    RequestQueue queue = Volley.newRequestQueue(Login.this);
                    queue.add(loginRequest);

                }
            });
            
        }

이런 식으로 사용자가 입력한 비밀번호에

 

아까 서버에서 솔팅한 내용을

 

그대로 입력을 한 다음에,

 

아까 만든 해시화 클래스를 호출하여,

 

SHA 512로 해쉬화 된 비밀번호가 반환되며,

 

내가 가입할 때, 얻었던 해시화된 비밀번호와

 

동일하게 되는 것이다.

 

이 부분

                    /** 비밀번호 해시화 중요(보안)*/
                    //서버에서 솔팅한 값
                    saltHash = "sooyeolBestDeveloperEver"+ pw +"inyoungBestWomanIntheWorld";
                    SHA516_Hash_InCode hash_inCode = new SHA516_Hash_InCode();
                    hashPw = hash_inCode.SHA516_Hash_InCode(saltHash); //솔팅한 값 해시화한 값

 

내가 설명을 잘 못해서.. 여기까지 천천히 읽어보면

 

이해가 될 것이다.

 

오늘은 여기까지 쓰겠다.

 

최근에 면접을 여러 군데 보고 다녀서 많이 바빠

 

글을 많이 못쓰고 있다.

 

면접이 다 끝나고,

 

실컷 공부한 뒤 다시 글을 쓰도록 해야겠다.

728x90
반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading