2014-12-27 5 views
0

나는 C++과 Java 모두에서 md5에 대해 brute-forcer를 구현했으며 효율성이 다른 이유에 대해 질문을했습니다.
데이터 및 시간 대 복잡도의 플롯 (암호 E는^길이) 여기에서 : http://i.imgur.com/hckCe8f.png
암호는 간단한 "B"S는 C에서성능 무차별 대항력 해시 C++ Java

가 ++ 나 MD5의 구현을 사용하여 길이를 채우기 위해 반복했다 : 재귀 C++ 구현에서 http://www.asjava.com/core-java/java-md5-example/

루프 내 코드는 별도의 클래스에서 수행되었다 :

class bruteChar { 
    string charset; 
    char last_char; 
    string str; 
    string double_start; 
    char reverse_charset[256]; 
    private: 
    string next(string s) 
    { 
     size_t length = s.size()-1; 
     if(length == 0) 
     { 
      if(s[0]==last_char) 
       return double_start; 
      return string(1, charset[reverse_charset[s[length]]+1]); 
     } 
     if(s[length] == last_char) 
      return next(s.substr(0,length))+charset[0]; 
     else 
      return str.substr(0,length)+string(1, charset[reverse_charset[s[length]]+1]); 
    }; 

    public: 
    void start (string chars) 
    { 
     charset = chars; 
     str=charset[0]; 
     last_char=charset[charset.size()-1]; 
     double_start=charset[0]; 
     double_start+=charset[0]; 

     for(size_t i = 0; i < charset.size(); ++i) 
      reverse_charset[charset[i]]=i; 
     reverse_charset[charset[charset.size()]]=0; 
    } 

    string next() 
    { 
     str=next(str); 
     return str; 
    } 
}; 

그리고 자바 zedwood.com/article/cpp-md5-function는이 사이트에 두 번째 구현을 사용자바에서 10

나는 사용자 정의 클래스

public class picochar { 
    public static char[] charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); 
    int num; 
    int mod; 

    picochar(int init, int mod) 
    { 
     num = init%mod; 
    } 

    picochar(char init, int mod) 
    { 
     for(int i = 0; i < mod; i++) 
     { 
      if(charset[i] == init) 
       num = i; 
     } 
    } 

    public char get() 
    { 
     return charset[num]; 
    } 

    public boolean equals(char ch) 
    { 
     return (get() == ch); 
    } 

    public void increment() 
    { 
     num++; 
    } 
} 

하고 다음 방법

public static String next(String s) { 
    int length = s.length(); 
    picochar pc = new picochar(s.charAt(length - 1),mod); 
    if(pc.equals(picochar.charset[mod-1])) 
     return length > 1 ? next(s.substring(0, length - 1)) + 'a' : "aa"; 
    pc.increment(); 
    return s.substring(0, length - 1) + pc.get(); 
} 

을 사용하는 이유는 자바 C++보다 더 해시를 계산 훨씬 더 효율적?를
Java 용 MD5 구현과 C++ 용 MD5 구현을 간단하게 사용 했습니까?
Java가 JVM을 통해 모든 것을 실행해야하고 C가 기본적으로 수행하므로 C++이 Java보다 훨씬 빠르다 고 가정했습니다.

그러나 Java는 C++ 솔루션보다 훨씬 뛰어납니다. 이것이 단순히 C++ 프로그램의 일부분에 대한 코딩이 제대로 이루어지지 않았기 때문에 어떻게 해결할 수 있습니까?

다른 C++ 프로그램을 제거하기 위해 편집되었으므로 두 솔루션 모두 재귀 적으로 루프됩니다.

해싱없이 루프를 돌리는 데 걸리는 시간을 약간했는데 여기 자바는 @Dunes로 설명한 C보다 두 배 빠릅니다. 재귀 적으로 substr()을 사용하지 않고 다시 원래 문자열을 변형 시키려고 recoded했을 때 C는 Java보다 두 배 빠릅니다.

해시 "hello"에 걸리는 시간이 얼마나되는지에 대한 테스트를 한 번 수행했습니다. < < 25 번, 이상한 점을 발견했습니다. Java는 "워밍업"속도가 빠르지 만 처음에는 속도가 느려지더라도 C 구현에.
C++은 해싱을 몇 초 동안 수행 한 후에도 비슷한 성능 향상을 보였으 나, Java만큼이나 이득이 컸습니다.

왜 Java가 더 워밍업합니까?

+2

을 걸린 시간 대 2 27 해시를 계산합니다. C++과 Java는 그렇게 다르게 보일 수 없습니다. 이러한 차이가 성능 차이를 설명 할 수 있습니다. –

+0

글쎄, 당신이 말했듯이, 당신은 동일한 구현을 비교해야합니다. C++은 일반적으로 잘 수행된다면 일반적으로 더 빠를 것입니다. 그리고 부수적 인 메모는 JIT 때문 만은 아닙니다. – keyser

+2

또 다른 차이점은 다른 MD5 라이브러리를 사용하고 있으며 이것이 프로그램이 더 많은 시간을 소비해야하는 곳입니다. 필자는이 라이브러리가 코드를보기 전에 성능을 어떻게 비교하는지 보려고했습니다. –

답변

0

밝혀졌습니다. 비효율적 인 md5 구현을 사용하고있었습니다.
는 여기 걸린 시간이 OpenSSL을

나는 코드가 더 유사 만들려고 할
openssl v1 
17.4911 

openssl v2 
14.9546 

custom 
291.201 
1

C++ 구현이 너무 느린 이유는 문자열을 값으로 전달하기 때문입니다. 문자열 인자를 가진 메소드를 호출하거나 문자열을 반환 할 때마다 프로그램은 전체 문자열의 아주 새로운 사본을 만들어야합니다.

Java는 불변의 문자열을 가지고 있기 때문에 동일한 문자열의 다른보기를 지나갈 수 있습니다. String.substring은 보조 문자 배열을 복사하지 않습니다. 대신 새 문자열 객체는 뒷받침 문자 배열을 기준으로 시작 색인과 길이를 추적합니다. 하위 문자열을 부 자연스럽게 사용하면 메모리 누수가 발생할 수 있습니다. 한 문자 뷰는 존재하는 한 오리지날 백만 그루의 문자 배열을 그대로 유지합니다.

+0

아! 가능한 한 비슷하게 두 개의 루프를 만들려고했으나 어떻게 작동하는지 알지 못했습니다. – robertkin