투케이2K

219. (AndroidStudio/android/java) aes 암호화 파생 인코딩 , 디코딩 수행 실시 - secretkey , iv , salt 본문

Android

219. (AndroidStudio/android/java) aes 암호화 파생 인코딩 , 디코딩 수행 실시 - secretkey , iv , salt

투케이2K 2021. 11. 18. 09:24

[개발 환경 설정]

개발 툴 : AndroidStudio

개발 언어 : java

 

[소스 코드]

import android.util.Base64;
import android.util.Log;

import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class C_AES256 {


    /**
     * TODO [클래스 설명]
     * 1. AES256 암호화 수행 파생 클래스
     * 2. 추가하는 값 KEY, IV, SALT 값
     * 3. CBC : 블록 암호화 운영 모드 중 보안 성이 제일 높은 암호화 방법으로 가장 많이 사용 (IV 사용)
     * 4. PKCS 5 : 8 바이트 패딩 (데이터 길이가 모자라다면 8 바이트까지 마지막 값 기준 채우고, 8 바이트 이상인 경우 뒤에 8바이트 패딩 추가)
     * 5. PKCS 7 : 16 바이트 패딩 (데이터 길이가 모자라다면 16 바이트까지 마지막 값 기준 채우고, 16 바이트 이상인 경우 뒤에 8바이트 패딩 추가)
     * 6. 참고 사이트 (aos) : https://www.tabnine.com/code/java/methods/javax.crypto.spec.PBEKeySpec/%3Cinit%3E
     * 7. 참고 사이트 (ios) : https://gist.github.com/hfossli/7165dc023a10046e2322b0ce74c596f8
     * */



    /** TODO [결과 출력 예시]
    W///===========//: ================================================
    I/: [C_AES256 >> encrypt() :: AES 암호화 인코딩 수행 실시]
        [secretKey :: 0123456789abcdef0123456789abcdef]
        [iv :: 0123456789abcdef]
        [salt :: 0123456789abcdef0123456789abcdef]
        [keyLength :: 32]
        [iterationCount :: 10000]
        [원본 :: hello]
        [인코딩 :: 4KpINm+YV8sEqzj8ccXIkw==
        ]
    W///===========//: ================================================

    W///===========//: ================================================
    I/: [C_AES256 >> decrypt() :: AES 암호화 디코딩 수행 실시]
        [secretKey :: 0123456789abcdef0123456789abcdef]
        [iv :: 0123456789abcdef]
        [salt :: 0123456789abcdef0123456789abcdef]
        [keyLength :: 32]
        [iterationCount :: 10000]
        [원본 :: 4KpINm+YV8sEqzj8ccXIkw==
        ]
        [디코딩 :: hello]
    W///===========//: ================================================
     */



    // TODO [전역 변수 선언 부분]
    public static final String secretKey = "0123456789abcdef0123456789abcdef";  // [32 바이트]

    public static final String ivKey = "0123456789abcdef";
    public static final byte[] iv = ivKey.getBytes(); // [16 바이트]

    public static final String saltKey = "0123456789abcdef0123456789abcdef";
    public static final byte[] salt = saltKey.getBytes(); // [random byte]

    public static final String padding = "AES/CBC/PKCS7Padding";  // [알고리즘]

    public static final int iterationCount = 10000;
    public static final int keyLength = 256; // [32 length]

    public static final String algo = "PBKDF2WithHmacSHA1";  // [알고리즘]
    public static final String secretKeySpecType = "AES";  // [타입]



    
    // TODO [AES256 base64 데이터 인코딩 수행]
    public static String encrypt(String strToEncrypt) {
        String returnData = "";
        try {
            // [iv 지정]
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            // [알고리즘 지정]
            SecretKeyFactory factory = SecretKeyFactory.getInstance(algo);

            // [KeySpec]
            KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt, iterationCount, keyLength);
            SecretKey tmp = factory.generateSecret(spec);

            // [SecretKeySpec : 인코딩, 디코딩 수행에서 AES 지정]
            SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), secretKeySpecType); // [인코딩, 디코딩 수행에서 AES 지정]

            // [Cipher]
            Cipher cipher = Cipher.getInstance(padding); // [인코딩, 디코딩 수행에서 필요한 패딩 지정]
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec); // [KeySpec + iv]
            returnData = Base64.encodeToString(cipher.doFinal(strToEncrypt.getBytes()), 0); // [base64 결과 반환 데이터]
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.i("---","---");
        Log.w("//===========//","================================================");
        Log.i("","\n"+"[C_AES256 >> encrypt() :: AES 암호화 인코딩 수행 실시]");
        Log.i("","\n"+"[secretKey :: "+String.valueOf(secretKey)+"]");
        Log.i("","\n"+"[iv :: "+String.valueOf(ivKey)+"]");
        Log.i("","\n"+"[salt :: "+String.valueOf(saltKey)+"]");
        Log.i("","\n"+"[keyLength :: "+String.valueOf(keyLength/8)+"]");
        Log.i("","\n"+"[iterationCount :: "+String.valueOf(iterationCount)+"]");
        Log.i("","\n"+"[원본 :: "+String.valueOf(strToEncrypt)+"]");
        Log.i("","\n"+"[인코딩 :: "+String.valueOf(returnData)+"]");
        Log.w("//===========//","================================================");
        Log.i("---","---");
        return returnData;
    }



    // TODO [AES256 base64 데이터 디코딩 수행]
    public static String decrypt(String strToDecrypt) {
        String returnData = "";
        try {
            // [iv 지정]
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            // [알고리즘 지정]
            SecretKeyFactory factory = SecretKeyFactory.getInstance(algo);

            // [KeySpec]
            KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt, iterationCount, keyLength);
            SecretKey tmp = factory.generateSecret(spec);

            // [SecretKeySpec : 인코딩, 디코딩 수행에서 AES 지정]
            SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), secretKeySpecType); // [인코딩, 디코딩 수행에서 AES 지정]

            // [Cipher]
            Cipher cipher = Cipher.getInstance(padding); // [인코딩, 디코딩 수행에서 필요한 패딩 지정]
            cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec); // [KeySpec + iv]
            returnData = new String(cipher.doFinal(Base64.decode(strToDecrypt, 0))); // [원본 데이터 반환]
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.i("---","---");
        Log.w("//===========//","================================================");
        Log.i("","\n"+"[C_AES256 >> decrypt() :: AES 암호화 디코딩 수행 실시]");
        Log.i("","\n"+"[secretKey :: "+String.valueOf(secretKey)+"]");
        Log.i("","\n"+"[iv :: "+String.valueOf(ivKey)+"]");
        Log.i("","\n"+"[salt :: "+String.valueOf(saltKey)+"]");
        Log.i("","\n"+"[keyLength :: "+String.valueOf(keyLength/8)+"]");
        Log.i("","\n"+"[iterationCount :: "+String.valueOf(iterationCount)+"]");
        Log.i("","\n"+"[원본 :: "+String.valueOf(strToDecrypt)+"]");
        Log.i("","\n"+"[디코딩 :: "+String.valueOf(returnData)+"]");
        Log.w("//===========//","================================================");
        Log.i("---","---");
        return returnData;
    }

} // TODO [클래스 종료]
 

[결과 출력]

 
 
 

 

반응형
Comments