투케이2K

465. (Android/Java) KeyStore 키스토어 사용해 X.509 인증서 생성 및 public key , private key 사용해 인코딩 , 디코딩 수행 실시 본문

Android

465. (Android/Java) KeyStore 키스토어 사용해 X.509 인증서 생성 및 public key , private key 사용해 인코딩 , 디코딩 수행 실시

투케이2K 2023. 1. 24. 22:07

[개발 환경 설정]

개발 툴 : AndroidStudio

 

[소스 코드]

        // -------------------------------------
        // [로직 처리 실시]
        // -------------------------------------
        try {


            /**
             * ----------------------------------
             * [요약 설명]
             * ----------------------------------
             * 1. KeyStore 시스템은 승인되지 않은 접근에 대해 중요한 데이터를 보호하기 위한 암호화 저장 공간입니다
             *
             * - KeyStore 는 디바이스에서의 승인되지 않은 접근에 대해 이들 제한을 강제함으로써 승인되지 않은 접근에 대한 위협을 줄여줍니다
             * ----------------------------------
             * 2. KeyStore 시스템은 Android 4.0(API 수준 14)에서 도입된 KeyChain API 에서 사용됩니다
             * ----------------------------------
             * 3. KeyStore 는 Encryption / Decryption (암 / 복호화) 및 Digital Signature (전자서명) 에 사용되는 Private Key (개인키), Public Key (공개키) 와 Certificate (인증서) 를 제공 합니다
             * ----------------------------------
             * 4. KeyStore 에 데이터 암호화 및 복호화를 수행 할 때 AES, RSA 등 알고리즘을 선택해서 사용할 수 있으며, AES 는 마시멜로 이상 버전에서 사용할 수 있습니다
             * ----------------------------------
             * 5. 해당 로직 :
             *
             * - X.509 공개키 인증서 생성
             *
             * - keyStore 에 인증서 저장
             *
             * - keyStore 에 저장된 인증서 호출
             *
             * - 데이터 암호화를 수행하기 위해 인증서 public key 확인
             * 
             * - 데이터 암호화 수행
             * 
             * - 데이터 복호화를 수행하기 위해 인증서 private key 확인
             * 
             * - 데이터 복호화 수행
             * ----------------------------------
             * 6. 참고 사이트 :
             *
             * https://developer.android.com/training/articles/keystore?hl=ko
             *
             * https://www.tabnine.com/code/java/classes/android.security.keystore.KeyGenParameterSpec$Builder
             *
             * https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec
             * ----------------------------------
             * */


            // [생성할 인증서 정보 및 유효 일자 정의 실시]
            String KEY_ALIAS = "PrivateKeyTwok";
            String AndroidKeyStore = "AndroidKeyStore";

            Calendar start = Calendar.getInstance();
            Calendar end = Calendar.getInstance();
            end.add(Calendar.YEAR, 20);


            // [AlgorithmParameterSpec 사용해 인증서 정보 정의]
            AlgorithmParameterSpec spec = null;
            if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
                spec = new KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                        .setCertificateSubject(new X500Principal("CN=" + KEY_ALIAS + " CA Certificate"))
                        .setCertificateSerialNumber(BigInteger.ONE)
                        .setCertificateNotBefore(start.getTime())
                        .setCertificateNotAfter(end.getTime())
                        .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                        .build();
            }
            else {
                spec = new KeyPairGeneratorSpec.Builder(getApplicationContext())
                        .setAlias(KEY_ALIAS)
                        .setSubject(new X500Principal("CN=" + KEY_ALIAS + " CA Certificate"))
                        .setSerialNumber(BigInteger.ONE)
                        .setStartDate(start.getTime())
                        .setEndDate(end.getTime())
                        .build();
            }


            // [비대칭 암호화 새 개인 키 생성 및 KeyStore 에 저장 실시]
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, AndroidKeyStore);
            kpg.initialize(spec);
            KeyPair kp = kpg.generateKeyPair();


            // [Keystore 로드]
            KeyStore keyStore = KeyStore.getInstance(AndroidKeyStore);
            keyStore.load(null);

            KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
            Certificate certificate = keyStore.getCertificate(KEY_ALIAS); // 인증서 정보


            // [데이터 암호화 및 복호화 수행에 필요한 형식 지정]
            String transformat = "RSA/ECB/PKCS1Padding";


            // [데이터 암호화 수행]
            RSAPublicKey pubKey = (RSAPublicKey) keyEntry.getCertificate().getPublicKey(); // [암호화에 사용하는 공개키]
            Cipher endcode_Cipher = Cipher.getInstance(transformat);
            endcode_Cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte encode[] = endcode_Cipher.doFinal("hello".getBytes());
            String encodeData = Base64.encodeToString(encode, 0);


            // [데이터 복호화 수행]
            PrivateKey privateKey = keyEntry.getPrivateKey(); // [복호화에 사용하는 개인키]
            Cipher decode_Cipher = Cipher.getInstance(transformat);
            decode_Cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte decode[] = Base64.decode(encodeData, Base64.DEFAULT);
            String decodeData = new String(decode_Cipher.doFinal(decode), "UTF-8");


            // [로그 출력 실시]
            S_Log.ltd("================================================");
            S_Log.cnt("["+ACTIVITY_NAME+" >> "+C_Util.getNowMethod(1)+" :: 로그 출력 실시]");
            S_Log.cnt("[keyStore isKeyEntry :: "+String.valueOf(keyStore.isKeyEntry(KEY_ALIAS))+"]");
            S_Log.cnt("[certificate getType :: "+String.valueOf(certificate.getType())+"]");
            S_Log.cnt("[pubKey :: "+String.valueOf(pubKey.getAlgorithm())+"]");
            S_Log.cnt("[privateKey :: "+String.valueOf(privateKey.getAlgorithm())+"]");
            S_Log.cnt("[certificate :: "+String.valueOf(certificate.toString())+"]");
            S_Log.cnt("[encodeData :: "+String.valueOf(encodeData)+"]");
            S_Log.cnt("[decodeData :: "+String.valueOf(decodeData)+"]");
            S_Log.lbd("================================================");
        }
        catch (Exception e){
            e.printStackTrace();
        }
 

[결과 출력]


반응형
Comments