문서
/
레시피
/

Bytecode Array Encoding 키

Bytecode Array Encoding 키 외부화하기

Pro

vmBytecodeArrayEncodingKey로 자체 VM 바이트코드 암호화 키를 지정하고, 키 게터를 통해 런타임에 다시 전달하세요. 키는 번들 밖에 두고 클라이언트 스토리지에서 읽거나 백엔드에서 가져올 수 있습니다.

시청

Obfuscator.io Async Executor: Async Bytecode Key Getter and Async-Only VM Virtualization

YouTube에서 보기

Obfuscator.io Custom Bytecode Key: Compile-Time Key and Runtime Key Getter (Cookie, Fetch, Decoy Key)

YouTube에서 보기

이 옵션들이 하는 일

vmBytecodeArrayEncoding은 VM 바이트코드 배열을 암호화하여 출력에 평문으로 남지 않게 합니다. 기본적으로 암호화 키는 환경에서 파생되어 클라이언트에서 재구성되므로 직접 다룰 일이 없습니다. 편리하지만 키 재료는 여전히 번들 안에 있습니다.

두 가지 옵션을 사용하면 키를 번들 밖으로 꺼내 직접 관리할 수 있습니다.

  • vmBytecodeArrayEncodingKey - 컴파일 시점에 지정하는 키입니다. 설정하면 기본 환경 파생 키 대신 사용되며, 난독화된 출력에 포함되지 않습니다.
  • vmBytecodeArrayEncodingKeyGetter - 런타임에 같은 키를 반환하는 JavaScript 표현식입니다. 그대로 포함되며, 난독화된 코드가 로드될 때 브라우저에서 평가됩니다.

핵심은 분리입니다. 키가 코드에 없으므로 번들을 순수하게 정적으로 분석해서는 키를 복구할 수 없습니다. 코드가 실행되려면 런타임에는 키가 있어야 하므로 진정한 비밀은 아니지만, 키를 어디서 가져오고 누가 볼 수 있는지는 직접 결정할 수 있습니다.

이 두 옵션은 한 쌍이며, 난독화 도구가 이를 강제합니다. 하나만 설정하면 빌드 시점 검증 오류가 발생합니다 (vmBytecodeArrayEncodingKey만 있으면 런타임에 키를 얻을 방법이 없고, 게터만 있으면 맞춰 볼 컴파일 시점 키가 없습니다). 또한 바이트코드 배열이 실제로 암호화되고 있지 않으면 아무 효과가 없으므로 vmBytecodeArrayEncoding: true도 켜야 합니다. 또는 내부적으로 vmBytecodeArrayEncoding을 강제로 켜는 vmSelfDefending: true를 켜도 됩니다. 두 키를 이 중 하나와 함께 설정하세요.

두 키가 결합되는 방식

지정한 키는 단독으로 사용되지 않습니다. 양쪽 모두에서 난독화 도구가 관리하는 내부 키와 섞입니다.

  • 컴파일 시점. vmBytecodeArrayEncodingKey는 난독화 도구가 파생한 내부 키와 결합되며, 바이트코드 배열은 그 결과로 얻은 혼합 키로 인코딩됩니다.
  • 런타임. vmBytecodeArrayEncodingKeyGetter가 반환하는 값은 여러 런타임 요소로부터 클라이언트에서 재구성된 같은 내부 키와 결합되어 바이트코드를 디코딩합니다.

양쪽 모두 지정한 키를 내부 키와 섞으므로, 게터는 vmBytecodeArrayEncodingKey로 전달한 것과 정확히 같은 문자열을 반환해야 합니다. 어느 쪽도 단독으로는 충분하지 않습니다. 내부 키가 없으면 지정한 키로 바이트코드를 디코딩할 수 없고, 지정한 키가 없으면 내부 키는 쓸모가 없습니다. 그래서 실제로 코드를 보호하는 것은 누가 키를 받는지를 통제하는 일입니다.

런타임에 키 제공하기

기본적으로 게터는 동기식입니다. 표현식은 난독화된 코드가 로드될 때 즉시 키를 반환해야 합니다. 쿠키, localStorage, 전역 변수, 서버가 주입한 DOM 요소 등 클라이언트에 이미 있는 어떤 소스에서든 읽어 오세요.

JavaScript

키는 난독화된 코드가 실행되기 전에 존재해야 합니다.

JavaScript

다른 동기식 소스도 같은 방식으로 동작합니다. 앱이 이미 채우고 있는 것을 고르세요.

JavaScript

키를 난독화된 코드와 같은 파일이나 스크립트에 두지 마세요. 그곳에 인라인으로 넣으면 이 방식의 의미가 사라집니다. 번들을 정적으로 분석하면 코드와 키를 모두 복구할 수 있기 때문입니다. 키는 별도의 소스에 저장하고, 컴파일 시점의 vmBytecodeArrayEncodingKey는 커밋하지 말고 환경 변수나 시크릿에서 주입하세요.

백엔드에서 키 가져오기 (비동기)

vmAsyncExecutor 필요 · v7.3.0+

동기식 게터는 클라이언트에 이미 있는 것만 읽을 수 있습니다. 인증 뒤에 두고 철회할 수 있도록 서버에서 키를 가져오려면 게터가 비동기여야 하며, 이를 위해서는 vmAsyncExecutor가 필요합니다. Async Executor를 켜면 게터가 Promise를 반환할 수 있고, VM은 실행하기 전에 이를 기다립니다.

vmAsyncExecutor를 켜면 가상화되는 범위도 좁아집니다. 이 모드에서는 가장 바깥쪽 async 함수만 VM으로 컴파일되고 동기 코드는 가상화되지 않습니다(나머지 난독화는 그대로 적용됩니다). 프로그램이 대부분 동기 코드라면, 보호하려는 코드를 async 함수로 감싸서 계속 적용 범위에 들어가게 하세요. 전체 규칙은 vmAsyncExecutor를 참고하세요.

JavaScript

Promise를 반환하는 게터에는 vmAsyncExecutor가 반드시 필요합니다. 이는 빌드 시점에 확인할 수 없으므로, vmAsyncExecutor가 꺼진 상태에서 Promise 게터를 사용하면 런타임에 실패합니다.

서버에서는 애플리케이션이 신뢰하는 근거, 예를 들어 검증된 세션이나 라이선스 검사 등을 바탕으로 어떤 키를 반환할지 결정하세요. Origin이나 Referer만으로는 호출자를 인증할 수 없으며, 동일 출처 GET 요청에는 Origin이 빠질 수 있습니다. 요령은 신뢰할 수 없는 호출자를 거부하는 대신 잘못된 키(아래의 VM_DECOY_KEY)를 반환하는 것입니다. 그러면 보호된 코드가 스스로 실패하며(오류, 잘못된 결과, 또는 응답하지 않는 페이지), 이는 무엇을 우회해야 하는지 공격자에게 정확히 알려 주는 뻔한 401보다 은밀합니다.

한 호출자의 키가 다른 호출자에게 제공되지 않도록 응답 캐싱을 비활성화하세요. 키를 올바른 빌드 버전에 결속하고 키와 번들을 함께 배포하세요. 실제 키를 받은 클라이언트는 여전히 런타임에 그 키를 들여다볼 수 있습니다.

JavaScript

이 엔드포인트에서는 빌드 시점에 vmBytecodeArrayEncodingKey로 전달한 것과 정확히 같은 문자열을 제공하세요. 위의 게터는 상대 URL(/api/vm-key)을 가져오므로, 다른 출처에 호스팅된 번들 사본은 그 출처에 /api/vm-key를 요청하게 되어 여러분의 키를 결코 받지 못합니다. 미끼 키는 엔드포인트에 도달하기는 했지만 신뢰할 수 있는 세션이 없는 호출자(인증되지 않은 요청, 여러분의 출처를 통해 프록시된 탈취 번들)가 받는 것입니다. 어느 쪽이든 실제 키는 도착하지 않고 보호된 코드는 실행되지 않습니다.

무엇을 "유효"하다고 볼지는 전적으로 애플리케이션에 달려 있습니다. 인증된 세션, 서명된 라이선스, 또는 이들의 조합일 수 있습니다. 키를 무엇이 만들어 내든 Promise로 감싸면 Async Executor가 VM을 실행하기 전에 이를 기다립니다.

키가 일치하지 않을 때

난독화된 코드는 게터가 난독화 시 사용한 키와 정확히 같은 키를 반환할 때만 동작합니다. 키가 다르거나 게터가 undefined, null, 빈 문자열을 반환하면 코드는 런타임에 실패합니다. 잘못된 결과를 내거나, 평범한 런타임 오류를 던지거나, 응답하지 않게 됩니다.

키에 특화된 별도의 오류 메시지는 의도적으로 없습니다. 키 실패는 다른 런타임 오류와 구별되지 않습니다. 따라서 이 옵션을 사용한 뒤에야 VM으로 보호된 번들이 예외를 던지거나, 잘못된 결과를 반환하거나, 멈춘다면 키 경로부터 확인하세요. 게터가 페이지에서 값을 반환하는지, 빈 문자열이 아닌 값을 반환하는지, 빌드할 때 사용한 것과 같은 값을 반환하는지 살펴보세요.