EMDI는 지금도 개발중

Android : KISACrypto SEED CBC 적용하기 본문

네이티브/Android

Android : KISACrypto SEED CBC 적용하기

EMDI 2020. 5. 25. 17:30
public static PrivateKey readPrivateKey(String filePath, String passwd) throws Exception {

        byte[] encodedKey = FileUtils.readFileToByteArray(new File(filePath));
        EncryptedPrivateKeyInfo epki = new EncryptedPrivateKeyInfo(encodedKey);

        String OID = epki.getAlgName();

        Security.addProvider(new BouncyCastleProvider());

        if ("1.2.410.200004.1.15".equals(OID)) {
            byte[] salt = new byte[8];
            System.arraycopy(encodedKey, 20, salt, 0, 8);

            byte[] cBytes = new byte[4];
            System.arraycopy(encodedKey, 30, cBytes, 2, 2);
            ByteBuffer buffer = ByteBuffer.wrap(cBytes);
            buffer.order(ByteOrder.BIG_ENDIAN);

            int iterationCount = buffer.getInt();

            byte[] derivedKey = new byte[20];   //DK값
            MessageDigest md = MessageDigest.getInstance("SHA1", "BC");
            md.update(passwd.getBytes());
            md.update(salt);
            derivedKey = md.digest();
            for (int i = 1; i < iterationCount; i++) {
                derivedKey = md.digest(derivedKey);
            }

            byte key[] = new byte[16];          // K 값
            byte iv[] = new byte[16];           // 초기 벡터값
            byte ivTemp[] = new byte[4];        // IV값
            byte derivedIV[] = new byte[20];    // SHA1으로 해쉬한 값

            System.arraycopy(derivedKey, 0, key, 0, 16);
            System.arraycopy(derivedKey, 16, ivTemp, 0, 4);

            MessageDigest sha1 = MessageDigest.getInstance("SHA-1", "BC");
            derivedIV = sha1.digest(ivTemp);
            System.arraycopy(derivedIV, 0, iv, 0, 16);

            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            SecretKeySpec secKey = new SecretKeySpec(key, "SEED");

            //여기서 부터 문제
            Cipher cipher = Cipher.getInstance("SEED/CBC/PKCS5Padding", "BC");
            cipher.init(Cipher.DECRYPT_MODE, secKey, ivSpec);
            byte[] decryptedKey = cipher.doFinal(epki.getEncryptedData());

            PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(decryptedKey);
            KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
            return kf.generatePrivate(ks);

        } else if ("1.2.410.200004.1.4".equals(OID)) {
            byte[] salt = new byte[8];
            System.arraycopy(encodedKey, 20, salt, 0, 8);

            byte[] cBytes = new byte[4];
            System.arraycopy(encodedKey, 30, cBytes, 2, 2);
            ByteBuffer buffer = ByteBuffer.wrap(cBytes);
            buffer.order(ByteOrder.BIG_ENDIAN);

            int iterationCount = buffer.getInt();

            byte[] derivedKey = new byte[20];
            MessageDigest md = MessageDigest.getInstance("SHA1", "BC");
            md.update(passwd.getBytes());
            md.update(salt);
            derivedKey = md.digest();
            for (int i = 1; i < iterationCount; i++) {
                derivedKey = md.digest(derivedKey);
            }

            byte key[] = new byte[16];
            System.arraycopy(derivedKey, 0, key, 0, 16);

            byte iv[] = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53};

            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            SecretKeySpec secKey = new SecretKeySpec(key, "SEED");

            Cipher cipher = Cipher.getInstance("SEED/CBC/PKCS5Padding", "BC");
            cipher.init(Cipher.DECRYPT_MODE, secKey, ivSpec);
            byte[] decryptedKey = cipher.doFinal(epki.getEncryptedData());

            PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(decryptedKey);
            KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
            return kf.generatePrivate(ks);
        }

        throw new Exception("not support OID: " + OID);
    }

Java에서는 바로 성공했던 공인인증서 개인키 획득 메소드가 안드로이드에서는 계속 NoSuchnosuchalgorithmexception 오류가 나와서 한동안 애를 먹었습니다.ㅠㅠ 며칠이 지난 후 비로소 알게 된 사실은 바로 안드로이드 내에서는 Cipher 알고리즘 중 SEED가 빠져있다는 사실! 그러므로 SEED를 꼭 사용하지 않아도 되는 분들은 AES와 같이 다른 알고리즘을 사용하시면 좋을 듯 싶고요. 만약 저처럼 SEED를 꼭 사용해야하는 분들은 SEED 알고리즘 소스를 직접 컴파일 하여 사용하시기 바랍니다. SEED 소스는 KISA 홈페이지에 들어가시면 바로 JAVA소스를 얻을 수 있으니 굳굳!

 

▶ KISA 홈페이지 : https://seed.kisa.or.kr/kisa/Board/17/detailView.do

 

KISA 암호이용활성화 - 암호알고리즘 소스코드

한국인터넷진흥원(KISA)에서는 128비트 블록암호 SEED를 쉽게 활용할 수 있도록, ECB, CBC, CTR, CCM, GCM, CMAC 운영모드에 대한 소스코드를 배포하고 있습니다. 언어 : C/C++, Java, ASP, JSP, PHP  다음글 2019-01-3

seed.kisa.or.kr

 

public static String DecryptString(byte[] str) {

    Base64.Decoder decoder = Base64.getDecoder();
    byte[] enc = decoder.decode(str);

    String result = "";
    byte[] dec = null;

    try {
        //복호화 함수 호출
        dec = KISA_SEED_CBC.SEED_CBC_Decrypt(pbUserKey, bszIV, enc, 0, enc.length);
        result = new String(dec, charset);
    } catch (UnsupportedEncodingException e) {
    	e.printStackTrace();
    }

    System.out.println("decrypt Result = " + result);
    return result;
}


public static byte[] EncryptString(String str) {
    byte[] enc = null;

    try {
        //암호화 함수 호출
        enc = KISA_SEED_CBC.SEED_CBC_Encrypt(pbUserKey, bszIV, str.getBytes(charset), 0,
        str.getBytes(charset).length);
    } catch (UnsupportedEncodingException e) {
    	e.printStackTrace();
    }

    Base64.Encoder encoder = Base64.getEncoder();
    byte[] encArray = encoder.encode(enc);
    try {
    	System.out.println(new String(encArray, "utf-8"));
    } catch (UnsupportedEncodingException e) {
    	e.printStackTrace();
    }
    return encArray;
}

만약 단순 Encrypt와 Decrypt를 하실 분들은 위의 소스를 참고해서 해주세요. 저는 아직 공인인증서를 성공하지 못하여서 아직도 시도중...

 

참고했던 사이트 : https://lyb1495.tistory.com/89

 

e세로 전자세금계산서 연동을 위한 JAVA 기반 XML 전자서명

본 내용은 월간 마이크로소프트웨어 2012년 12월호에 기고된 내용입니다 :) -- 전자세금계산서 제도는 사업자가 전자적 방법에 의해 세금계산서를 교부하고, 교부한 전자세금계산서를 정해진 기��

lyb1495.tistory.com

 

Comments