마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

키스토어 RSA 개인키로 암호화 하는 방법

0 추천
안녕하세요. 안드로이드 암복호화 공부하는 대학생입니다.

지금 키스토어로 RSA 개인키 및 공개키 생성해서 개인키는 암호화, 공개키는 복호화하는 기능을 만들고 있는데

어째서인지 키스토어 개인키로 암호화 하면 InvalidKeyException이 나오네요.

키스토어 말고 따로 만든 개인키로는 가능하더군요.

게다가 키스토어개인키는 String으로 바뀌지도 않습니다.

키스토어공개키는 또 바뀌고..

키스토어로 생성한 RSA개인키로 암호화하는 방법 없을까요?
yes8438 (120 포인트) 님이 2022년 2월 25일 질문
final KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
            final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(alias,
                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                    .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                    .build();
            keyGenerator.init(keyGenParameterSpec);
            keyGenerator.generateKey();

1개의 답변

0 추천

아래는 안드로이드에서 API레벨에 따라 지원되는 Cipher 입니다. 혹시 지원되지 않는 걸 사용했는지 확인해 보세요.
 

 

그리고 아래는 Gihub에 있는 샘플 소스 코드입니다.

https://github.com/charanolati/Android-encryption-sample

spark (230,170 포인트) 님이 2022년 2월 25일 답변
안녕하세요 답변 감사합니다. 제가 사용한건 "RSA/ECB/PKCS1Padding"인데 API레벨이 29여서 문제는 없을 것 같습니다. 그리고 깃허브의 소스도 확인했는데 소스에서는 공개키로 암호화를 하고 있어서 제 케이스에는 해당되지는 않는 것 같습니다. 감사합니다.
그럼, 원하시는게 private key로 encyption을 하고 public key로 decryption을 하는 건가요?
네 맞습니다. 지금 키스토어를 사용하지 않고 만든 키쌍의 경우에는 그게 가능했는데 키스토어를 써서만든 키로는 안되더라고요.
Cipher.java 소스코드의  init메소드에서 해당 에러가 나는 것 같은데, 아마도 아래 라인으로 보이네요.

if (certificate instanceof java.security.cert.X509Certificate) {
            // Check whether the cert has a key usage extension
            // marked as a critical extension.
            X509Certificate cert = (X509Certificate)certificate;
            Set<String> critSet = cert.getCriticalExtensionOIDs();
            if (critSet != null && !critSet.isEmpty()
                && critSet.contains(KEY_USAGE_EXTENSION_OID)) {
                boolean[] keyUsageInfo = cert.getKeyUsage();
                // keyUsageInfo[2] is for keyEncipherment;
                // keyUsageInfo[3] is for dataEncipherment.
                if ((keyUsageInfo != null) &&
                    (((opmode == Cipher.ENCRYPT_MODE) &&
                      (keyUsageInfo.length > 3) &&
                      (keyUsageInfo[3] == false)) ||
                     ((opmode == Cipher.WRAP_MODE) &&
                      (keyUsageInfo.length > 2) &&
                      (keyUsageInfo[2] == false)))) {
                    throw new InvalidKeyException("Wrong key usage");
                }
            }
        }

       PublicKey publicKey =
            (certificate==null? null:certificate.getPublicKey());
        try {
            chooseProvider(InitType.KEY, opmode, (Key) publicKey, null, null, random);
        } catch (InvalidAlgorithmParameterException e) {
            // should never occur
            throw new InvalidKeyException(e);
        }

정확하지는 않지만 사용하신 키가 요건에 맞지 않아서 나는 에러인거는 확실해 보입니다.
디버깅이 가능하다면 브레이크 포인트를 찍어서 keyUsageInfo 변수에 어떤 값이 들어오는지 확인하실 수 있다면 좋을 것 같은데요.
Cipher.init  부분에 브레이크포인트 걸어서 찾아보고 있는데 여기에는 저 부분이 안나오네요;; 도와주셔서 감사합니다.
...