달달한 스토리

728x90
반응형

출처:garfield.wikia.com

요즘 일찍 일찍 자는 중이다.

 

취미도 잘 즐기고 있고, 코딩도 즐겁게 하고 있다.

 

12시에 자야 하고, 배운 것도 써야 하니,

 

오늘 배웠던 것은 크립토 라이브러리이다.

 

https://developer.android.com/guide/topics/security/cryptography?hl=ko

 

암호화  |  Android 개발자  |  Android Developers

Android의 암호화 기능을 알아보세요.

developer.android.com

자세한 정보는 이 곳에서 볼 수 있다.

 

암호화는 보통 로그인을 할 때 아이디나 비밀번호 등

 

보안을 위한 값들(키 스토어 라이브러리 사용을 하는 경우이지만 여기서는 암호화)을

 

보통 암호화를 해주고 서버에 보내주곤 한다.

 

보통 크게 암호화에는 두 가지가 있다.

 

대칭 암호화와 비대칭 암호화이다.

 

전자는 암호화와 복호화의 키가 같고,

 

후자는 암호화와 복호화의 키가 다르다.

 

이 말이 무슨 말이 냐면,

 

전자는 암호화를 하는 쪽과 복호화를 하는 쪽 둘 다

 

똑같은 키를 사용하는 것이다.

 

보안에는 취약하나, 속도가 빠르다는 장점이 있다.

 

그렇다면 후자는 어떠할까? 

 

비대칭은 암호화와 복호화를 위한 키가 각각 다르게 하는 것을 의미한다.

 

공개키(public Key)로는 암호화를 하는 데 사용이 되고,

 

비밀키(private Key)로는 복호화를 하는데 사용이 된다.

 

속도는 느리나 보안에 강점이 있다.

 

다음 그림을 보면 쉽게 이해할 수 있다.

 

출처:Yeons 블로그

https://yeonfamily.tistory.com/17

 

대칭키와 비대칭키 암호화 방식에 대하여

개요 암호화 방법으로는 크게 대칭키와 비대칭키 암호화 방식으로 구분을 합니다. 이 두가지 암호화 알고리즘 방법에 대해 가볍게 알아보고, 각각의 암호화 알고리즘을 언제 사용하는지, 차이

yeonfamily.tistory.com

이 그림에 출처는 남깁니다.

 

순서는 이러하다.

 

1. 우선 공개키를 달라고 서버에 요청한다.

 

2. 공개키를 받고 서버에 보낼 데이터를 공개키로 암호화한다.

 

3. 서버에서는 데이터를 받고, 개인키로 암호화된 데이터를 복호화한다.

 

참고

 

복잡해 보이지만, 차근차근 보면 알 수 있다.

 

하지만 아쉽게도, 나는 프로젝트에서 암호화된 키만을 사용하기 때문에,

 

지금부터 보여줄 예제는 암호화해서 서버로 보내는 예제이다.

 

https://linsoo.pe.kr/archives/27961

 

안드로이드에서 RSA 암호 사용하기

안드로이드에서 RSA 방식으로 데이터 암호화 해서 Golang이랑 통신하는거 하다가 여기 정리해둠. val keygen = KeyPairGenerator.getInstance(

linsoo.pe.kr

이 블로그에 출처를 밝힌다.

 

나는 개인 pem키가 있기 때문에, 

 

공개키와 비밀키를 만들고 시작을 하였다.

 

 

만약 pem키가 없어 공개키와 비밀키를 못 만드는 상황이라면,

 

위에 블로그에 들어가 KeytoPEM() 메서드를 통해 만들기 바란다.

 

(위에 블로그에 잘 나와있음..)

 

나 같은 경우는 pem키가 있어 pem 변수에 넣어주었다.

 

public static Key PEMtoKey(String keyStr) {
        Key tmpKey = null;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            String keyString = keyStr;
            if (keyString.contains("PUBLIC KEY")) {
                keyString = keyString.replace("-----BEGIN PUBLIC KEY-----", "");
                keyString = keyString.replace("-----END PUBLIC KEY-----", "");
                KeySpec spec = new X509EncodedKeySpec(Base64.decode(keyString, Base64.NO_WRAP));
                tmpKey = keyFactory.generatePublic(spec);
            }
            //이건 프라이빗 키 쓸 때 사용하기;
//            } else if (keyString.contains("PRIVATE KEY")) {
//                keyString = keyString.replace("-----BEGIN PRIVATE KEY-----", "");
//                keyString = keyString.replace("-----END PRIVATE KEY-----", "");
//                KeySpec spec = new PKCS8EncodedKeySpec(Base64.decode(keyString, Base64.DEFAULT));
//                tmpKey = keyFactory.generatePrivate(spec);
//            }"

        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            e.printStackTrace();
            return null;
        }
        return tmpKey;
    }

    //문자열 암호화 하기
    public static String encryptData(String text) throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Key publicKey = PEMtoKey(pem);
        Cipher encCipher = Cipher.getInstance("RSA/ECB/OAEPwithSHA-1andMGF1Padding");
        encCipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] encryptTextByteArray = encCipher.doFinal(text.getBytes(StandardCharsets.UTF_8));

        return new String(Base64.encode(encryptTextByteArray, Base64.NO_WRAP));
    }

그리고 위에 코드를 통해 내가 원하는 String 데이터를 암호화할 수 있었다.

 

사용법은

 

encryptData()를 호출하여 String 데이터를 파라미터로 넣어준다.

 

 

그러면 PEMtoKey를 통해 pem변수를 넣어 공개키를 반환받게 된다.

 

그리고 Cipher 인스턴스를 통해 사용하게 되는 서버와 사양(알고리즘)을 맞춰야 한다.

 

이 부분이 틀리면 500 에러가 뜨게 된다.

 

아까 위에 올려두었던 안드로이드 개발자 사이트 (암호문)에서 다음과 같이 나와 있다.

이 밖에도 더 있지만, 나 같은 경우는 서버 사양이 OAEP, padding, sha-1이었기 때문에,

 

알고리즘은 RSA로 하고, 모드는 ECB로, 패딩은 OAEPwithSHA-1 andMGF1 Padding로 하였다.

 

알고리즘, 모드, 패딩에 자세한 내용은 다루지 않겠다.

 

나도 잘 모른다.. 헤헤 서버 사양이라는 정도만 알고 있고,

 

프런트에서 맞춰줘야 한다는 상황만 파악 중이다.. 따로 공부하자..

 

아무튼 이 부분은 꼭 맞춰주자.

그리고 퍼블릭 키를 넣어주고, 암호화 모드로 Cipher를 초기화해준다.

 

복호화 모드는

DECRYPT_MODE

이 것을 사용하면 된다.

 

 

그리고 우리가 암호화하려는 text를 바이트 배열로 만들어 encryptTextByteArray 배열에 담아주고,

 

이 녀석을 Base64 형태로 인코딩해주어 String 값으로 리턴해준다.

 

형태는 Base64.NO_WRAP으로 해주었다.

 

원래는 DEFAULT모드를 사용했는데,

 

일정 문자열 후에 자동 줄 바꿈이 되어, 서버에 전송할 때 오류가 있었다.

 

이러한 자동 줄 바꿈을 원하지 않아, 나는 NO_WRAP으로 바꿔어 자동 줄바꿈을 없앴다.

 

 

상황에 맞게 바꿔 쓰면 좋을 듯하다.

 

이런 식으로 암호화의 세계를 잠시 맛보았다.

 

내일 출근해야 해서 급하게 쓴 감이 없지 않지만,

 

필수적인 것은 파악해서 다행이라고 생각한다.

 

여유로울 때 더 깊이 들어가 보자.

728x90
반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading