2014-09-15 2 views
-4

문자열을 "소화"하는 방법을 찾고 있지만 항상 동일한 32 (또는 64) 바이트의 긴 값 (16 진수 문자열 또는 일반 문자)을 반환합니다.항상 동일한 값을 반환하는 문자열에 대한 안티 다이제스트 연산

std::string digest(const std::string& input) 
{ 
    std::string result = ""; 
    // do something with the input string, update result accordingly 
    return result; 
} 

을하고 조금 더 세부 정보 : 다음과 같은 코드는 않습니다 I (1 각 다른 문자열은 다르지만 항상 같은를 반환하는 고전이하는 기능을 소화 무엇인지 정확히 반대합니다 1) 값. 각 문자열에 대해 동일한 값 (n을 1로)을 반환하는 함수가 필요합니다.

명백히 "쉬운"솔루션은 항상 동일한 상수 result을 반환합니다. 해결책으로 간주되지 않습니다. 코드는 실제로 입력 문자열을 소화해야하고 연산 결과로 result을 빌드해야합니다.

그리고 예 :

digest ("fox") == digest ("whale") 

것은 사실 일 것이다.

또는 수학적으로 말하면 : ∀ A 및 B에 대한

경우 A = B = "다이제스트 (a) == 다이제스트 (b)!. 그래서 나는이 소위 말하는 소화를 불렀다.

+0

SHA 제품군 또는 MD5 암호화 알고리즘을 사용해 보셨습니까? –

+0

아니요, 실제 다이제스트 기능입니다. 서로 다른 문자열로 피드하면 다른 값을 반환합니다. 나는 항상 다른 문자열에 대해 동일한 것을 반환하는 것을 원한다. – fritzone

+4

* 다른 문자열에 대해 항상 같은 것을 반환하려면 * [XKCD 221 - 난수] (http://www.xkcd.com/221/)를 참조하십시오. –

답변

3

긴 수학 데모

귀하의 요구 사항은 다음과 같습니다

a!=b => digest(a)==digest(b) 

이의 또 다른 메시지를 다른 메시지 C를 보자, 그리고 그것이 다른 겠와 b :

a!=c => digest(a)==digest(c) 
b!=c => digest(b)==digest(c) 

이것으로부터 당신은 다이제스트가 a 또는 b와 같지 않으면 어떤 c에 대해서도 일정하다는 것을 알 수 있습니다.

이 지금은 무엇이든간에 다른 메시지의 X 걸릴 :

digest(x)!=digest(c) => c==x 

그래서 가정

부터 다이제스트 다른과 X이있을 것입니다 :

c!=x => digest(c)==digest(x) 

을이 의미를 contraposing함으로써를이 동일합니다 일정한 다이제스트 (c). 우리는이 :

digest(x)!=digest(c) and digest(x)!=digest(a) 
=> x==c and x==a 
=> c==a 
=> digest(c)!=digest(a) 

그러나 밖이 모순 약 원래 가설, C는 소화 (a)와 (c) 소화, 그래서 같은 X이있을 수 없습니다. 따라서 은 다이제스트가 완전히 일정한 기능을 가져야한다고 결론 내릴 수 있습니다.

지금 당신의 기능이 일정하지 않을 것입니다 가정 :

digest(x)!=digest(a) => x==a 

을하지만 다이제스트 함수 인 경우, 항상 의미, 동일한 입력에 대해 동일한 결과가 반환 X == A => (소화 x) == digest (a). 이는 상수 함수 이외의 다른 솔루션이없는 이 있음을 보여줍니다.사이드 effet (정적 변수이든)가 존재하지 않는 함수 요컨대 및

C++에서

동일한 매개 변수에 대해 동일한 결과를 반환한다. 다른 값에 대해 동일한 결과를 가지지 만 동일한 값에 대해 다른 결과를 얻으려는 요구 사항은 하나의 매개 변수 만있는 함수에서는 간단하게 실현할 수 없습니다. 어떻게 든 내가 달성하고자하는 것에 대한 불분명 보인다

-1

...

어쨌든, 나는 다음과 같은 내놓았다 : ideone에

static const size_t DIGEST_SIZE = 32; 
std::string antiDigest(const std::string& a) 
{ 
    if(a.empty()) { throw "cannot digest empty string"; } 
    char r[DIGEST_SIZE ] = {0}; 
    int block_size = std::min(DIGEST_SIZE, a.length()); 
    int block_count = 1 + DIGEST_SIZE/a.length(); 
    for(int i=0; i<block_size; i++) 
    { 
     int hlp = 0, bc = 0; 

     while(bc < block_count) 
     { 
      int idx = i + bc * block_size; 
      if(idx >= a.length()) break; 
      hlp += a[idx]; 
      bC++; 
     } 
     hlp = (int)(hlp << 3) + hlp; 
     unsigned int hlp2 = 0; 
     while(hlp) 
     { 
      int t = hlp - ((hlp/10) * 10); 
      hlp2 += t; 
      hlp /= 10; 
     } 
     bc = 0; 
     while(bc < block_count) 
     { 
      int idx = i + bc * block_size; 
      if(idx >= DIGEST_SIZE) break; 
      r[idx] = ((hlp2/10) + (hlp2-(hlp2/10)*10)) ;  
      bc++; 
     } 
    } 

    std::stringstream result; 
    for(int i=0; i<DIGEST_SIZE; i++) 
    { 
     result << int_to_hex(r[i]) ; 
    } 
    return result.str(); 
} 

: http://ideone.com/t4dibL

물론, 이것은 비트 연산으로 수학 연산을 대체함으로써 더욱 혼란 스러울 수 있지만 개념 증명을 위해이를 수행합니다.

+0

최적화가 있습니다 : std :: string antiDigest() {return"090909090909090909090909090909090909090909090909090909090909 ";}' –

관련 문제