난독화 이야기 (1) 에서 가상 블랙박스 난독화, 즉 임의의 프로그램을 인풋-아웃풋만 알 수 있도록 일종의 “프로그램을 암호화”하는 난독화 기술이 불가능함을 설명했다. 그렇다면 자연스러운 질문은 얼마나 강력한 난독화가 가능한지, 가장 좋은 난독화가 무엇인지에 관한 것이다. 한참 쉬었는데, 난독화에 관한 콴타매거진 기사가 올라와서 다시 돌아와서 조금 더 써봄ㅋ
사실 2001년의 가상 블랙박스 난독화 불가능성 논문에서 이미 제시한 개념이 있다. 바로 구별불가능성 난독화, indistinguishability obfuscation, 소위 “IO”라고 불리는 난독화이다. 구별불가능성 난독화는 두 동등한 프로그램, 즉 크기가 같고 입출력이 같은 프로그램 A와 B를 난독화한 결과 O(A)와 O(B)가 구별 불가능하게 만들어준다.
[정의]구별불가능성 난독화 O는 프로그램 P를 인풋으로 받아 다른 프로그램 O(P)를 아웃풋으로 내는 효율적인 컴파일러로써 다음을 만족한다.
- (정확성) P의 입출력을 그대로 보존하여 O(P)(x)=P(x)를 만족한다
- (안전성) 크기가 같고 입출력이 같은 프로그램 A,B에 대해 O(A)와 O(B)가 구별 불가능하다.
여기서 구별불가능하다는 것은 임의의 효율적인 알고리즘을 들고와도, X=A 또는 B에 대해 O(X)에서 X가 A인지 B인지 결정할 확률이 맞출 확률이 1/2, 즉 찍는 것에 가깝다는 것.처음 보면 이게 뭔 의미인가 싶다. 나도 그랬다 -_- 하지만 이 정의만으로도 꽤 많은 프로그램의 정보를 숨길 수 있다. 다음 예시를 보자.
은행 등의 앱을 편리하게 이용하기 위해서는 일부 개인정보, 예를 들어 계좌번호와 비밀번호 등을 앱에 저장해놓는 것이 편리하다. 이를 가장 효율적으로 구현하는 방식은 그냥 비밀번호와 계좌번호를 그대로 앱에 저장해놓는 것. 근데 이건 앱을 뜯어볼 수 있으면 비밀번호와 계좌번호를 그대로 볼 수 있고, 바로 개인정보의 유출로 이어진다.
그렇지만 만약 발전한 암호기술을 바탕으로 계좌번호와 비밀번호를 암호화한 상태로 똑같은 태스크를 할 수 있다면? 이 경우에는 앱을 뜯어도 얻을 수 있는 정보가 없다. 바로 IO가 말하는 것은, 이 두 프로그램을 IO로 난독화 한 경우 구별이 불가능하고, 따라서 단순히 구현한 프로그램을 난독화하는 것만으로 프로그램을 뜯어보는 것에 대한 강력한 보안을 얻을 수 있다는 것.
잠깐, 우리는 난독화된 프로그램의 안전성을 논하기 위해 다른 안전한 프로그램을 들고왔다. 이 생각을 천천히 살펴보면 다음과 같은 직관을 얻을 수 있다.
IO를 이용해 난독화한 프로그램은 모든 입출력이 같은 프로그램 중 가장 안전하다!
이런 직관에 착안하여 2007년 골드와서 교수님과 그 제자였던 Guy Rothblum이 Best-possible obfuscation이라는 개념을 제안했다. 즉 난독화된 프로그램이 동등한 프로그램 중 가장 안전해지는 난독화 기술이 무엇인지에 대해 질문을 제시한 것.
저자들의 대답은 다음과 같다.
[정리] 컴파일러 O가 효율적인 IO 방법인 것과 효율적인 Best-possible 난독화인 것은 동치이다.
아주 간단하고 깔끔하다. 이 정리를 조금 더 엄밀하게 말하기 위해 Best-possible obfuscation (BPO)의 정의를 다음과 같이 살짝 정의하자.
[정의] Best-possible 난독화 O는 프로그램 P를 인풋으로 받아 다른 프로그램 O(P)를 아웃풋으로 내는 효율적인 컴파일러로써 다음을 만족한다.
- (정확성) P의 입출력을 그대로 보존하여 O(P)(x)=P(x)를 만족한다
- (안전성) 임의의 알고리즘 L에 대해서, 그리고 임의의 크기가 같고 입출력이 같은 프로그램 A,B에 대해 다음을 만족하는 효율적인 알고리즘 S가 존재한다:
L(O(A))와 S(B)의 결과 분포가 구별 불가능하다.
정확성은 IO와 정확히 같고, 안전성은 언뜻 봐서는 무슨 뜻인지 꽤 헷갈린다. 대충 그 뜻을 해석해보자면, 난독화 결과 O(A)에서 얻을수 있는 결과는 사실 임의의 다른 동등한 프로그램 B에서 얻을수 있었다는 뜻. 다시 말하면 O(A)에서 유출되는 정보는 다른 모든 동등한 프로그램에서 이미 유출되고 있다는 것.
이제 위 정리는 다음과 같이 증명할 수 있다.
[BPO=>IO] O가 BPO라고 하자. L을 identity, 즉 O(A)의 결과를 그대로 내는 알고리즘이라고 하면 임의의 동등한 두 프로그램 A,B에 대해 (O(A), S(A)), (S(A),O(B))가 각각 구별 불가능하고, 따라서 O(A)와 O(B)도 구별 불가능하다.
[IO=>BPO] O가 IO라고 하자. 임의의 L에 대해 S를 잡아줘야 한다. S(*)=L(O(*))로 정의하면 O(A)와 O(B)가 구별 불가능한 것에서 L(O(A))와 L(O(B))도 구별 불가능.
아주 간단하고 쉽다. 이 논문 이후 난독화의 이론적 연구는 IO가 옳은 목표라는 것에 많이들 동의하게 되었고, 이후 수년간 정체되어 있다가 2013년에 처음으로 그럴듯한 일반적인 난독화 기술이 나온다. 이는 다음 글에서 다룰 예정.
마지막으로 이 논문의 독특한 결과는 다음과 같다.
[정리] P=NP라면 BPO가 존재한다.
암호학적으로는 굉장히 어이없는 결과인게, 암호 시스템이 안전하다는 것은 보통 P≠NP보다도 강력한 결과이다. (즉, 암호가 (다른 가정 없이) 안전하면 P≠NP가 성립한다.) 증명은 자세히는 조금 복잡하고, 대충 아래와 같다.
P=NP라면 임의의 프로그램에 대해 동등한 프로그램 중 "가장 짧은" 프로그램을 효율적으로 찾을 수 있다. 그리고 이 가장 짧은 프로그램은 동등한 두 프로그램 A,B에 대해 같으므로, 이 과정은 IO이고 따라서 BPO이다.