firebase

DynamicLinks 암호화 / 복호화

이나주니 2023. 7. 11. 10:49
반응형

필자의 경우 JAVA 에서 암호화 된 값을 dart에서 복호화해 api 통신을 통한 자동 로그인을 구현했습니다

flutter 3.7.12 기준

AES/CBC/PKCS5Padding 기준 암호화

 

aes cbc 방식이란?

암호 블록 체인 (cipher-block chaining, CBC) 방식은 1976년 IBM에 의해 개발되었다. 각 블록은 암호화되기 전에 이전 블록의 암호화 결과와 XOR되며, 첫 블록의 경우에는 초기화 벡터가 사용된다. 초기화 벡터가 같은 경우 출력 결과가 항상 같기 때문에, 매 암호화마다 다른 초기화 벡터를 사용해야 한다.

 

CBC 방식은 현재 널리 사용되는 운용 방식 중 하나이다. CBC는 암호화 입력 값이 이전 결과에 의존하기 때문에 병렬화가 불가능하지만, 복호화의 경우 각 블록을 복호화한 다음 이전 암호화 블록과 XOR하여 복구할 수 있기 때문에 병렬화가 가능하다.

 

encrypt: ^5.0.1 라이브러리 사용 복호화

https://pub.dev/packages/encrypt

 

encrypt | Dart Package

A set of high-level APIs over PointyCastle for two-way cryptography.

pub.dev

Encrypter

 

static final byte[] iv = new byte[16];

String value = AESUtils.encryptBase64("암호키 값", "test");

public static String encryptBase64(String secret, String data) {
        try {
            return Base64.encodeBase64String(encrypt(secret, data));
        } catch (EncryptionException e) {
            e.printStackTrace();
            return "";
        }
    }


public static byte[] encrypt(String secret, String data) throws EncryptionException {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes("UTF-8"), "AES");
            AlgorithmParameterSpec ivParam = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParam);

            return cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException
                 | NoSuchPaddingException
                 | InvalidKeyException
                 | InvalidAlgorithmParameterException
                 | IllegalBlockSizeException
                 | BadPaddingException
                 | UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new EncryptionException(e);
        }
    }

 

암호화 된 값을 다이나믹링크 파라미터에 담아 요청

 

앱이 실행되며 flutter firebase 이벤트 리스너 수신

Decrypted

 

FirebaseDynamicLinks.instance.onLink.listen(
          (pendingDynamicLinkData) async {
        Uri link = pendingDynamicLinkData.link;

		    String? key= link.queryParameters['key'];
				final encryptKey = encrypt.Key.fromUtf8('암호키 값'); // 암호화 할때 설정한 키
	      final iv = encrypt.IV.fromLength(16);
	      final encrypter =
	      encrypt.Encrypter(encrypt.AES(encryptKey, mode: encrypt.AESMode.cbc));
	      final decrypted = encrypter.decrypt64(key!, iv: iv);

				print(decrypted);
				// 복호화 된 값 출력
	}
);

 

작성자의 경우 똑같은 요청을 또 다시하면 N번씩 이벤트리스너가 잡아 같은 페이지를 여러번 호출하기 되었다

이로인해 GlobalKey 중복 오류가 발생해

아래와 같이 임시 처리로 조치 했다

 

bool flag = true;

이벤트 수신시 flag 값 이용해 false 가 되면 다시 실행하지 못하도록 처리 함
    FirebaseDynamicLinks.instance.onLink.listen(
          (pendingDynamicLinkData) async {
        Uri link = pendingDynamicLinkData.link;
          if (flag) {
            flag = false;
            /*암호화된 파라미터 값 이용 로그인 처리*/
            dynamicLinkLogin(link);
          }
         },
    );

 

느낀점 : 암호화 알고리즘을 좀더 찾아보고 공부하고 사용해 봐야 겠다

반응형