[블록체인 PICK] Android Keystore 보안

 

 Android Keystore 보안

 

이번  시간에는 Android 내의 보안영역 Keystore 를 다룰 예정입니다.

 

Keystore 언제 쓸 수 있을까?

이더리움 KeyStore 파일은 이더리움 Private Key의 암호화된 버전입니다.

만약 Private Key가 탈취되었을 경우, 공격자는 당신의 계좌에 대한 모든 권한을 얻을 수 있기 때문에 매우 위험합니다.

위 원문은 여기에서 확인 하실 수 있습니다

 

Android 암호화폐 Wallet 을 제작 시 Transaction 의 주체가 되기 위한 Private Key(이하 PK) 를 기기 내부의 어느 영역에 저장해야 합니다. 이 PK를 어디에 저장할 수 있을까요? Wallet 을 제작한 회사의 Server나 Android 기기 내의 Internal Storage 아니면 External Storage 에다 저장할 수 있을겁니다.

 

서버의 경우에는 여느 서버와 마찬가지로 해킹의 위험이 있으며, Storage는 상대적으로 접근이 어렵지 않습니다. 이 중요한 PK를 Plain Text로 노출해 놓았다면, 접근과 동시에 탈취당할것 입니다.

 

PK는 Encrypted 된 상태로 놓여야 하며, 복호화가 가능해야 합니다. 복호화를 위해 사용되는 Key또한 Plant Text로 존재하면 안됩니다.

 

간단하게 KeyStore는 암호화를 위한 Key를 생성하는 시스템입니다. 이 포스팅은 Keystore 가 무엇인가를 소개하기 위한 자료입니다.

 

다음 포스팅에서는 Device내에서 PK를 저장하기 위해 Keystore가 어떻게 쓰이고 암호화, 복호화가 어떤 Flow로 이루어지는지 소개하도록 하겠습니다.

 

Android KeyStore 시스템

Android KeyStore 시스템에서는 암호화 키를 Store에 저장해야 하므로 이 키를 기기에서 추출해내기가 더 어렵습니다. 일단 키가 Store에 들어가면, 이 키는 주요 material을 내보낼 수 없는 암호화 작업에 사용될 수 있습니다. 이 시스템에서는 또한 키 사용 시기와 사용 방법을 제한하는 기능이 있습니다(예: 키 사용을 위해 사용자 인증 요구 또는 특정 암호화 모드에서만 사용하도록 키를 제한)

 

보안

Android KeyStore 시스템은 승인되지 않은 접근에 대해 중요한 Key material를 보호합니다

 

  • 디바이스 밖에서의 승인되지 않은 key material 사용에 대해 key material 추출을 보호함으로써 승인되지 않은 접근에 대한 위협을 줄여줍니다.
  • Keystore는 디바이스에서의 승인되지 않은 접근에 대해 키를 specify 하고 앱 프로세스 바깥에서의 이들 제한을 강제함으로써 승인되지 않은 접근에 대한 위협을 줄여줍니다.

 

추출 차단

Android KeyStore 키의 주요 material이 추출되는 것을 차단하기 위해 두 가지 보안 조치가 사용됩니다.

 

  • 주요 material은 절대로 애플리케이션 프로세스에서 접근할 수 없습니다. 애플리케이션이 KeyStore 키를 사용하여 암호화 작업을 수행하는 경우, 배후에서 서명하거나 확인하려는 일반 텍스트, 암호 텍스트 및 메시지는 암호화 작업을 수행하는 시스템 프로세스로 들어갑니다. 앱의 프로세스가 노출되면, 공격자가 앱 키를 사용할 수 있어도 키의 주요 material을 추출해낼 수는 없습니다

 

  • 주요 material은 Android 기기의 보안 하드웨어(예: Trusted Execution Environment, Secure Element)에 바인딩 될 수도 있습니다. 키에 대해 이 기능이 활성화되면, 키의 주요 material이 절대로 보안 하드웨어 바깥에 노출되지 않습니다. Android OS가 손상되거나 공격자가 기기의 내부 저장소를 읽을 수 있는 경우, 이 공격자는 Android 기기에 있는 모든 앱의 Android KeyStore 키를 사용할 수는 있겠지만, 기기에서 키를 추출해낼 수는 없습니다. 이 기능이 활성화되려면 기기의 보안 하드웨어가 특정 조합의 키 알고리즘, 차단 모드, 변환 방법 및 다이제스트를 지원해야 하며, 이를 통해 키 사용을 승인합니다.

 

키 사용 승인

Android 기기에서 키의 불법 사용을 줄이기 위해, Android KeyStore는 키를 생성하거나 가져올 때 적법한 키 사용을 앱에서 지정하도록 만듭니다. 키를 생성하거나 가져온 후에는 그 승인을 변경할 수 없습니다. 그런 다음 이 키가 사용될 때마다 Android KeyStore에 의해 승인이 시행됩니다. 이 기능은 고급 보안 기능이며, 일반적으로 키 생성/가져오기 이후(이전이나 도중은 아님) 애플리케이션 프로세스의 손상이 불법 키 사용으로 이어져서는 안 된다는 요구사항이 있는 경우에만 유용합니다.

 

지원되는 키 사용 승인은 다음과 같은 범주로 구분됩니다.

 

  • 암호화 : 키를 사용할 수 있는 승인된 키 알고리즘, 작업 또는 용도(encrypt, decrypt, sign, verify), 변환 방법, 차단 모드 및 다이제스트
  • 인증 유효기간 : 키 사용이 승인되는 유효기간 지정
  • 사용자 인증 : 사용자가 최근에 인증된 경우에만 키를 사용할 수 있습니다.

 

추가적인 보안 조치로서, 주요 material이 보안 하드웨어 안에 있는 키의 경우 / KeyInfo.isInsideSecurityHardware(), Android 기기마다 다르지만 일부 키 승인은 보안 하드웨어에 의해 시행될 수도 있습니다. ‘암호화’ 승인 및 ‘사용자 인증’ 승인은 주로 보안 하드웨어에 의해 시행됩니다. ‘시간적 유효성 간격’ 승인은 대개 보안 하드웨어에 의해 시행되지 않는데, 그 이유는 일반적으로 독립된 실시간 보안 클록이 없기 때문입니다.

 

키의 사용자 인증 승인이 보안 하드웨어에 의해 시행되는지 여부는 / KeyInfo.isUserAuthenticationRequirementEnforcedBySecureHardware()를 사용하여 쿼리할 수 있습니다.

 

키체인 또는 Android KeyStore 제공자 중에 선택

시스템 범위의 자격 증명을 원하면 KeyChain API를 사용합니다. 앱이 KeyChain API를 통해 자격 증명 사용을 요청하는 경우, 사용자는 설치된 자격 증명 중에서 이 앱이 액세스할 수 있는 자격 증명을 시스템 제공 UI를 통해 선택합니다. 이렇게 하면 사용자 동의 하에 여러 앱이 동일한 자격 증명을 사용할 수 있습니다.

 

Android KeyStore 제공자를 사용하면 개별 앱이 혼자만 액세스할 수 있는 자격 증명을 저장할 수 있습니다. 이 방법을 사용하면 앱이 혼자만 사용할 수 있는 자격 증명을 관리할 수 있을 뿐만 아니라 Keychain API가 시스템 범위의 자격 증명에 제공하는 것과 동일한 보안 이점을 누릴 수 있습니다. 이 방법은 자격 증명을 선택하기 위한 사용자 상호작용이 필요 없습니다.

 

Android KeyStore 제공자 사용

이 기능을 사용하려면, 표준 KeyStore 및 KeyPairGenerator 또는 KeyGenerator클래스와 Android 4.3(API 레벨 18)에 소개된 AndroidKeyStore 제공자를 함께 사용합니다.

 

AndroidKeyStore는 KeyStore.getInstance(type)메서드와 사용하기 위해 KeyStore 유형으로 등록되며, KeyPairGenerator.getInstance(algorithm, provider) 및 KeyGenerator.getInstance(algorithm, provider)메서드와 사용하기 위해 제공자로 등록됩니다.

 

새 개인 키 생성

새 Private Key 를 생성하려면 자체 서명 인증서가 갖게 될 초기 X.509 특성도 지정해야 합니다.

키를 생성하려면 KeyPairGenerator와 KeyPairGeneratorSpec을 함께 사용합니다.

/*
 * Generate a new EC key pair entry in the Android Keystore by
 * using the KeyPairGenerator API. The private key can only be
 * used for signing or verification and only with SHA-256 or
 * SHA-512 as the message digest.
 */
KeyPairGenerator kpg = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
kpg.initialize(new KeyGenParameterSpec.Builder(
        alias,
        KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
        .setDigests(KeyProperties.DIGEST_SHA256,
            KeyProperties.DIGEST_SHA512)
        .build());
KeyPair kp = kpg.generateKeyPair();

새 비밀 키 생성

키를 생성하려면 KeyGenerator와 KeyGenParameterSpec을 함께 사용합니다.

 

키스토어 항목 사용

AndroidKeyStore 제공자 사용은 모든 표준 KeyStore API에서 발생합니다.

 

항목 나열

aliases() 메서드를 호출하여 키스토어에 항목을 나열합니다.

/*
 * Load the Android KeyStore instance using the the
 * "AndroidKeyStore" provider to list out what entries are
 * currently stored.
 */
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
Enumeration<String> aliases = ks.aliases();

데이터 서명 및 확인

키스토어에서 KeyStore.Entry 가져오고 sign()과 같은 Signature API를 사용하여 데이터에 서명합니다.

/*
 * Use a PrivateKey in the KeyStore to create a signature over
 * some data.
 */
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.Entry entry = ks.getEntry(alias, null);
if (!(entry instanceof PrivateKeyEntry)) {
    Log.w(TAG, "Not an instance of a PrivateKeyEntry");
    return null;
}
Signature s = Signature.getInstance("SHA256withECDSA");
s.initSign(((PrivateKeyEntry) entry).getPrivateKey());
s.update(data);
byte[] signature = s.sign();

마찬가지로, verify(byte[])메서드를 사용하여 데이터를 확인합니다.

/*
 * Verify a signature previously made by a PrivateKey in our
 * KeyStore. This uses the X.509 certificate attached to our
 * private key in the KeyStore to validate a previously
 * generated signature.
 */
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.Entry entry = ks.getEntry(alias, null);
if (!(entry instanceof PrivateKeyEntry)) {
    Log.w(TAG, "Not an instance of a PrivateKeyEntry");
    return false;
}
Signature s = Signature.getInstance("SHA256withECDSA");
s.initVerify(((PrivateKeyEntry) entry).getCertificate());
s.update(data);
boolean valid = s.verify(signature);

키 사용을 위해 사용자 인증 요구

키를 생성하거나 AndroidKeyStore로 가져올 경우, 사용자가 인증된 후에만 키 사용을 승인하도록 지정할 수 있습니다. 사용자는 자신의 보안 잠금 화면 자격 증명(패턴/PIN/암호, 지문)을 사용하여 인증됩니다.

 

이 기능은 고급 보안 기능이며, 일반적으로 키 생성/가져오기 이후(이전이나 도중은 아님) 애플리케이션 프로세스 손상이 키 사용을 위한 사용자 인증 요구사항을 무시해서는 안 된다는 요구사항이 있는 경우에만 유용합니다.

 

사용자가 인증된 후에만 키 사용을 승인하는 경우, 두 가지 모드 중 하나에서 작동하도록 구성할 수 있습니다.

 

  • 사용자 인증에서 일정한 기간 동안 키 사용을 승인합니다. 이 모드에서는 사용자가 보안 잠금 화면을 해제하거나 KeyguardManager.createConfirmDeviceCredentialIntent 흐름을 사용하여 보안 잠금 화면 자격 증명을 확인하는 즉시 모든 키의 사용이 승인됩니다. 승인이 유효하게 유지되는 기간은 각 키 마다 다르며, 이 기간은 키 생성 또는 가져오기 중에 setUserAuthenticationValidityDurationSeconds를 사용하여 지정됩니다. 이러한 키는 보안 잠금 화면이 활성화된 경우에만 생성되거나 가져올 수 있습니다. 보안 잠금 화면이 비활성화되면 이러한 키는 영구적으로 무효화되거나(사용자를 인증하지 않는 None 모드, Swipe 모드 또는 기타 모드로 재구성) 또는 강제로 재설정됩니다(예: 기기 관리자에 의해 재설정).

 

  • 사용자 인증에서는 하나의 키와 연관된 특정 암호화 작업을 승인합니다. 이 모드에서는 이러한 키가 관련된 각 작업을 사용자가 개별적으로 승인해야 합니다. 현재로서는 이러한 승인의 유일한 수단은 지문 인증(FingerprintManager.authenticate)뿐입니다. 이러한 키는 최소 하나 이상의 지문이 등록된 경우에만 생성되거나 가져올 수 있습니다. 지문이 새로 등록되거나 모든 지문이 등록 해제되면 이러한 키가 영구적으로 무효화됩니다.

 

지원되는 알고리즘

 

참고자료

대부분의 내용이 Android developer 에서 따왔습니다. (개발문서 원본보다 정확할 순 없겠죠)

 

 

 

원문 확인하기 >> https://bit.ly/2BfrvkV

error: 본 콘텐츠의 저작권은 BTC코리아닷컴에 있으며 무단전재&배포 금지합니다.