String, char Hash
-
Sehr geehrte Community,
und zwar bin ich dabei Code zum Hashen von Strings in C in einem Java-Programm zu implementieren, daher bin ich nicht so fit in C.
Die Funktion die den Hashwert zurückliefern soll, sieht folgendermaßen aus:
JNIEXPORT jstring JNICALL Java_DLLAufrufen_HelloWorld2 (JNIEnv * env, jclass myclass, jstring inString) { //char *inString; //const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy); MD5_CTX mdContext; const char *nativeString = (*env)->GetStringUTFChars(env, inString, 0); unsigned int len = strlen (nativeString); MD5Init (&mdContext); MD5Update (&mdContext, inString, len); MD5Final (&mdContext); //MDPrint (&mdContext); //printf (" \"%s\"\n\n", inString); return inString; (*env)->ReleaseStringUTFChars(env, inString, nativeString); }
bisher hat die Funktion MDPrint das Ausgeben übernommen:
static void MDPrint (mdContext) MD5_CTX *mdContext; { int i; for (i = 0; i < 16; i++) printf ("%02x", mdContext->digest[i]); }
Allerdings soll der Hashwert dem Javaprogramm zurückgeliefert werden.
Der vollständige Programmcode sieht so aus:
/* Replace "dll.h" with the name of your header */ #include <jni.h> #include "dll.h" #include <windows.h> #include <stdio.h> #include <stdlib.h> /* typedef a 32 bit type */ typedef unsigned long int UINT4; /* Data structure for MD5 (Message Digest) computation */ typedef struct { UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ UINT4 buf[4]; /* scratch buffer */ unsigned char in[64]; /* input buffer */ unsigned char digest[16]; /* actual digest after MD5Final call */ } MD5_CTX; void MD5Init (); void MD5Update (); void MD5Final (); /* -- include the following line if the md5.h header file is separate -- */ /* #include "md5.h" */ /* forward declaration */ static void Transform (); static unsigned char PADDING[64] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* F, G and H are basic MD5 functions: selection, majority, parity */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ /* Rotation is separate from addition to prevent recomputation */ #define FF(a, b, c, d, x, s, ac) \ {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) \ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) \ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) \ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } void MD5Init (mdContext) MD5_CTX *mdContext; { mdContext->i[0] = mdContext->i[1] = (UINT4)0; /* Load magic initialization constants. */ mdContext->buf[0] = (UINT4)0x67452301; mdContext->buf[1] = (UINT4)0xefcdab89; mdContext->buf[2] = (UINT4)0x98badcfe; mdContext->buf[3] = (UINT4)0x10325476; } void MD5Update (mdContext, inBuf, inLen) MD5_CTX *mdContext; unsigned char *inBuf; unsigned int inLen; { UINT4 in[16]; int mdi; unsigned int i, ii; /* compute number of bytes mod 64 */ mdi = (int)((mdContext->i[0] >> 3) & 0x3F); /* update number of bits */ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) mdContext->i[1]++; mdContext->i[0] += ((UINT4)inLen << 3); mdContext->i[1] += ((UINT4)inLen >> 29); while (inLen--) { /* add new character to buffer, increment mdi */ mdContext->in[mdi++] = *inBuf++; /* transform if necessary */ if (mdi == 0x40) { for (i = 0, ii = 0; i < 16; i++, ii += 4) in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | (((UINT4)mdContext->in[ii+2]) << 16) | (((UINT4)mdContext->in[ii+1]) << 8) | ((UINT4)mdContext->in[ii]); Transform (mdContext->buf, in); mdi = 0; } } } void MD5Final (mdContext) MD5_CTX *mdContext; { UINT4 in[16]; int mdi; unsigned int i, ii; unsigned int padLen; /* save number of bits */ in[14] = mdContext->i[0]; in[15] = mdContext->i[1]; /* compute number of bytes mod 64 */ mdi = (int)((mdContext->i[0] >> 3) & 0x3F); /* pad out to 56 mod 64 */ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); MD5Update (mdContext, PADDING, padLen); /* append length in bits and transform */ for (i = 0, ii = 0; i < 14; i++, ii += 4) in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | (((UINT4)mdContext->in[ii+2]) << 16) | (((UINT4)mdContext->in[ii+1]) << 8) | ((UINT4)mdContext->in[ii]); Transform (mdContext->buf, in); /* store buffer in digest */ for (i = 0, ii = 0; i < 4; i++, ii += 4) { mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); } } /* Basic MD5 step. Transform buf based on in. */ static void Transform (buf, in) UINT4 *buf; UINT4 *in; { UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; /* Round 1 */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 FF ( a, b, c, d, in[ 0], S11, 3614090360u); /* 1 */ FF ( d, a, b, c, in[ 1], S12, 3905402710u); /* 2 */ FF ( c, d, a, b, in[ 2], S13, 606105819u); /* 3 */ FF ( b, c, d, a, in[ 3], S14, 3250441966u); /* 4 */ FF ( a, b, c, d, in[ 4], S11, 4118548399u); /* 5 */ FF ( d, a, b, c, in[ 5], S12, 1200080426u); /* 6 */ FF ( c, d, a, b, in[ 6], S13, 2821735955u); /* 7 */ FF ( b, c, d, a, in[ 7], S14, 4249261313u); /* 8 */ FF ( a, b, c, d, in[ 8], S11, 1770035416u); /* 9 */ FF ( d, a, b, c, in[ 9], S12, 2336552879u); /* 10 */ FF ( c, d, a, b, in[10], S13, 4294925233u); /* 11 */ FF ( b, c, d, a, in[11], S14, 2304563134u); /* 12 */ FF ( a, b, c, d, in[12], S11, 1804603682u); /* 13 */ FF ( d, a, b, c, in[13], S12, 4254626195u); /* 14 */ FF ( c, d, a, b, in[14], S13, 2792965006u); /* 15 */ FF ( b, c, d, a, in[15], S14, 1236535329u); /* 16 */ /* Round 2 */ #define S21 5 #define S22 9 #define S23 14 #define S24 20 GG ( a, b, c, d, in[ 1], S21, 4129170786u); /* 17 */ GG ( d, a, b, c, in[ 6], S22, 3225465664u); /* 18 */ GG ( c, d, a, b, in[11], S23, 643717713u); /* 19 */ GG ( b, c, d, a, in[ 0], S24, 3921069994u); /* 20 */ GG ( a, b, c, d, in[ 5], S21, 3593408605u); /* 21 */ GG ( d, a, b, c, in[10], S22, 38016083u); /* 22 */ GG ( c, d, a, b, in[15], S23, 3634488961u); /* 23 */ GG ( b, c, d, a, in[ 4], S24, 3889429448u); /* 24 */ GG ( a, b, c, d, in[ 9], S21, 568446438u); /* 25 */ GG ( d, a, b, c, in[14], S22, 3275163606u); /* 26 */ GG ( c, d, a, b, in[ 3], S23, 4107603335u); /* 27 */ GG ( b, c, d, a, in[ 8], S24, 1163531501u); /* 28 */ GG ( a, b, c, d, in[13], S21, 2850285829u); /* 29 */ GG ( d, a, b, c, in[ 2], S22, 4243563512u); /* 30 */ GG ( c, d, a, b, in[ 7], S23, 1735328473u); /* 31 */ GG ( b, c, d, a, in[12], S24, 2368359562u); /* 32 */ /* Round 3 */ #define S31 4 #define S32 11 #define S33 16 #define S34 23 HH ( a, b, c, d, in[ 5], S31, 4294588738u); /* 33 */ HH ( d, a, b, c, in[ 8], S32, 2272392833u); /* 34 */ HH ( c, d, a, b, in[11], S33, 1839030562u); /* 35 */ HH ( b, c, d, a, in[14], S34, 4259657740u); /* 36 */ HH ( a, b, c, d, in[ 1], S31, 2763975236u); /* 37 */ HH ( d, a, b, c, in[ 4], S32, 1272893353u); /* 38 */ HH ( c, d, a, b, in[ 7], S33, 4139469664u); /* 39 */ HH ( b, c, d, a, in[10], S34, 3200236656u); /* 40 */ HH ( a, b, c, d, in[13], S31, 681279174u); /* 41 */ HH ( d, a, b, c, in[ 0], S32, 3936430074u); /* 42 */ HH ( c, d, a, b, in[ 3], S33, 3572445317u); /* 43 */ HH ( b, c, d, a, in[ 6], S34, 76029189u); /* 44 */ HH ( a, b, c, d, in[ 9], S31, 3654602809u); /* 45 */ HH ( d, a, b, c, in[12], S32, 3873151461u); /* 46 */ HH ( c, d, a, b, in[15], S33, 530742520u); /* 47 */ HH ( b, c, d, a, in[ 2], S34, 3299628645u); /* 48 */ /* Round 4 */ #define S41 6 #define S42 10 #define S43 15 #define S44 21 II ( a, b, c, d, in[ 0], S41, 4096336452u); /* 49 */ II ( d, a, b, c, in[ 7], S42, 1126891415u); /* 50 */ II ( c, d, a, b, in[14], S43, 2878612391u); /* 51 */ II ( b, c, d, a, in[ 5], S44, 4237533241u); /* 52 */ II ( a, b, c, d, in[12], S41, 1700485571u); /* 53 */ II ( d, a, b, c, in[ 3], S42, 2399980690u); /* 54 */ II ( c, d, a, b, in[10], S43, 4293915773u); /* 55 */ II ( b, c, d, a, in[ 1], S44, 2240044497u); /* 56 */ II ( a, b, c, d, in[ 8], S41, 1873313359u); /* 57 */ II ( d, a, b, c, in[15], S42, 4264355552u); /* 58 */ II ( c, d, a, b, in[ 6], S43, 2734768916u); /* 59 */ II ( b, c, d, a, in[13], S44, 1309151649u); /* 60 */ II ( a, b, c, d, in[ 4], S41, 4149444226u); /* 61 */ II ( d, a, b, c, in[11], S42, 3174756917u); /* 62 */ II ( c, d, a, b, in[ 2], S43, 718787259u); /* 63 */ II ( b, c, d, a, in[ 9], S44, 3951481745u); /* 64 */ buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } #include <stdio.h> #include <sys/types.h> #include <time.h> #include <string.h> #include <jni.h> /* -- include the following file if the file md5.h is separate -- */ /* #include "md5.h" */ /* Prints message digest buffer in mdContext as 32 hexadecimal digits. Order is from low-order byte to high-order byte of digest. Each byte is printed with high-order hexadecimal digit first. */ static void MDPrint (mdContext) MD5_CTX *mdContext; { int i; for (i = 0; i < 16; i++) printf ("%02x", mdContext->digest[i]); } JNIEXPORT void JNICALL Java_DLLAufrufen_HelloWorld (JNIEnv * env, jclass myclass) { printf ("Hello World from DLL!\n Hi"); } JNIEXPORT jstring JNICALL Java_DLLAufrufen_HelloWorld2 (JNIEnv * env, jclass myclass, jstring inString) { //char *inString; //const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy); MD5_CTX mdContext; const char *nativeString = (*env)->GetStringUTFChars(env, inString, 0); unsigned int len = strlen (nativeString); MD5Init (&mdContext); MD5Update (&mdContext, inString, len); MD5Final (&mdContext); //MDPrint (&mdContext); //printf (" \"%s\"\n\n", inString); return inString; (*env)->ReleaseStringUTFChars(env, inString, nativeString); } BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ , DWORD reason /* Reason this function is being called. */ , LPVOID reserved /* Not used. */ ) { switch (reason) { case DLL_PROCESS_ATTACH: break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } /* Returns TRUE on success, FALSE on failure */ return TRUE; }
Meine eigentliche Frage lautet jetzt, wie ich aus dem mdContext den eigentlich String bekomme bzw. in C char Array. Das Ausgeben hat ja bisher die Funktion MDPrint übernommen.
Danke schon im Voraus
DerProgrammierer
-
Du musst deinen
jstring inString
wie mit printf gezeigt, befüllen, d.h. da kannst du sprintf nehmen, unter der Annahme dass jstring kompatibel zu unsigned char* ist also in etwa:{ int i,j; unsigned char *p=inString; for (i = j = 0; i < 16; i++, j+=2) sprintf( p+j, "%02x", mdContext->digest[i]); }
inString muss hier mind. für 33 Byte Platz bieten aber das sollte ja wohl gegeben sein.
-
Danke erst einmal für die Antwort.
Also so ganz komme ich mit C noch nicht klar, warum werden die prrintf-Ausgaben weiter unten nach der for-Schleife nicht in die Konsole geschrieben?JNIEXPORT jstring JNICALL Java_DLLAufrufen_HelloWorld2 (JNIEnv * env, jclass myclass, jstring inString)
{
//char *inString; //const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy); MD5_CTX mdContext; const char *nativeString = (*env)->GetStringUTFChars(env, inString, 0); unsigned int len = strlen (nativeString); MD5Init (&mdContext); MD5Update (&mdContext, inString, len); MD5Final (&mdContext); //MDPrint (&mdContext); //printf (" \"%s\"\n\n", inString); int i,j; unsigned char *p; for (i = j = 0; i < 16; i++, j+=2) { printf ("%02x", mdContext.digest[i]); sprintf( p+j, "%02x", mdContext.digest[i]); } char *buf = (char*)malloc(33); strcpy(buf, p); jstring tempString = (*env)->NewStringUTF(env, buf); printf("\ntest %s\n", tempString); printf("\ntest %s\n", inString); return tempString; (*env)->ReleaseStringUTFChars(env, inString, nativeString); }
-
Hallo,
wahrscheinlich weil printf nichts mit jstrings anfangen kann, dafür gibt es wohl GetStringUTFChars, die die Konvertierung vornehmen kann?
MfG,
Probe-Nutzer
-
Anscheinend wirklich nicht. Ich dachte, dass wenigstens dann das "test" ausgegeben wird. Aktueller Status:
JNIEXPORT jstring JNICALL Java_DLLAufrufen_HelloWorld2 (JNIEnv * env, jclass myclass, jstring inString) { MD5_CTX mdContext; const char *nativeString = (*env)->GetStringUTFChars(env, inString, 0); unsigned int len = strlen (nativeString); MD5Init (&mdContext); MD5Update (&mdContext, inString, len); MD5Final (&mdContext); int i,j; unsigned char *p; for (i = j = 0; i < 16; i++, j+=2) { //printf ("%02x", mdContext.digest[i]); sprintf( p+j, "%02x", mdContext.digest[i]); } (*env)->ReleaseStringUTFChars(env, inString, nativeString); char *buf; strcpy(buf, p); printf("\ntest %s\n", buf); return (*env)->NewStringUTF(env, buf); }
Die per Konsole ausgegebenen Werte aus dem C-Code stimmen, allerdings wird scheinbar nichts an das Java-Programm weitergegeben, da von der Seite aus nichts ausgegeben wird.
-
Also das hier:
unsigned char *p;
ist ein Zeiger auf irgendwas und daher ungeeignet, verwende besser:
unsigned char p[33] = {0};
Genau das gleiche Problem bei buf, also wenn, dann so:
char buf[33];
MfG,
Probe-Nutzer
-
Vielen Dank hat geholfen!
-
Anderes Problem:
Anscheinend funktioniert der Hash nicht. Den Algorithmus habe ich von dieser Seite:
http://www.tierradelazaro.com/public/criptologia/md5codigofuente.txt
Ich denke der greift auch nur auf vorhandene md5-Bibiliotheken zu. Grundlegendes habe ich ja in der MDString nicht verändert, eben nur auf meine Bedürfnisse zugeschnitten, ich mische mich ja gar nicht in den Algorithmus ein.
Für zz sollte beispielsweise 25ed1bcb423b0b7200f485fc5ff71c8e rauskommen, dabei kommt bei jedem Programmstart ein neuer Wert heraus, wenn ich das Programm mit der DLL hashen lassen. Ich zeig mal kurz einen Ausschnitt:qz ae7eb1e86da5f9c90e67f0ce3e55148b rz 667e40238c7e7c8f0a63d3f70b26d69c sz 32ef8ae06098ff542442310ced90c8c2 tz 07b10613628ca2815e23731981c79c19 uz 7489bc5a41cf5223cc71e2bc556a62c2 vz 26225fe6889e069eb6706235c7fc7a83 wz 83002a8f3a41eb9e04845aaf8a07541b xz 9f33b1a28c4d9006833930be51ab9a6f yz 12085c26a74d356af4e05880a5f355bd zz 627713ec65a40fbbbfc0b13e1f0746bb
Dabei sollte die Ausgabe so aussehen:
qz 3879186336b2b4a1ad89cadf910a5b19 rz 80fcd632dc2558177aaf6f8f5cd57678 sz 7dabf5c198b0bab2eaa42bb03a113e55 tz 73bb4387b3075739eacb9cd62ac4049c uz 8b3274b755aa033902f57fb557e25923 vz 54107dd5d77b8a3bcbc0faecd128de7c wz d0965c07d1a00fcc85d28b8a241ae35a xz dbd69ee9ae289a85ea34dbef8435d7c1 yz 2151a2bc77807b81113febbf50c4bc95 zz 25ed1bcb423b0b7200f485fc5ff71c8e
Den korrekten Durchlauf kann ich nur erbringen, wenn ich mit der Java-Bibliothek hashe.
Ich zeige mal kurz den Java Code (nichts kompliziertes):
public class BruteForcer { HashGenerator hashGenerator = new HashGenerator(); String hashString; static { System.loadLibrary("dllmain"); } public static native void HelloWorld(); public static native String MD5Hash(String input); public String bruteForcerMD5(String input, int pwLength) throws NoSuchAlgorithmException { char ini = 'A'; String testString = ""; for(int integerChar1 = (int)ini; integerChar1 <= 122; integerChar1++) { for(int integerChar2 = (int)ini; integerChar2 <= 122; integerChar2++) { testString = "" + (char)integerChar2 + (char)integerChar1; // hashString = MD5Hash(testString); // in dieser Zeile greife ich auf die Funktion der DLL zu hashString = hashGenerator.makeMD5Hash(testString); // in dieser Zeile würde ich mit Java hashen System.out.println(testString + " " + hashString); if(input.equals(hashString)) { return testString; } } } return "konnte nicht ermittel werden"; } }
Meine Vermutung ist, dass irgendetwas bei der Stringübergabe nicht stimmt.
-
Da habe ich noch etwas übersehen, oder du, wie man es sehen mag ;):
Immer darauf achten, an C-Routinen auch nur "native C-Strings" zu übergeben, aber das passiert hier:
MD5Update (&mdContext, inString, len);
nicht, hier wird inString übergeben, das ist ein jstring. Den "nativeString" hast du ja schon hier:
const char *nativeString = (*env)->GetStringUTFChars(env, inString, 0);
erzeugt, der muss an MD5Update übergeben werden:
MD5Update (&mdContext, nativeString, len);
Dann solltest du noch den Parameter-Typ von inBuf der Funktion MD5Update in "const unsigned char"* ändern:
void MD5Update (mdContext, inBuf, inLen) MD5_CTX *mdContext; const unsigned char *inBuf; unsigned int inLen; { ....
Das können wir machen, weil MD5Update die Zeichen in inBuf sowieso nicht ändert.
MfG,
Probe-Nutzer
-
Hallo und danke! Das nehme ich auf meine Kappe.
Ich versuche gerade den gesamten Algorithmus in C zu implementieren, leider mangelt es an Grundlagen (String, char Array, Zeiger, etc.)
Hier mal die Fehlermeldung:
SHA1DLL.c: In function `Java_main_HashGenerator_SHA1Hash': SHA1DLL.c:463: warning: passing arg 2 of `SHAUpdate' discards qualifiers from pointer target type SHA1DLL.c: In function `SHA1InterHash': SHA1DLL.c:497: warning: return from incompatible pointer type SHA1DLL.c:497: warning: function returns address of local variable SHA1DLL.c: In function `Java_main_HashGenerator_SHA1main': SHA1DLL.c:529: error: invalid initializer SHA1DLL.c:536: error: incompatible types in assignment
und hier mal mein Code:
#define MAX_LENGTH 8 char anfangBuchstabe = 'a'; // = 'a' char endBuchstabe = 'z'; // = 'z' char cg[MAX_LENGTH] = {0}; // Current Guess char currentChar = {0}; int index; JNIEXPORT jstring JNICALL Java_main_HashGenerator_SHA1main(JNIEnv * env, jclass myclass, jstring inString) { const char *nativeString = (*env)->GetStringUTFChars(env, inString, 0); cg[0] = anfangBuchstabe; char attempt[1] = SHA1InterHash(cg); while (1) { if (strcmp(attempt, nativeString) == 0) { printf("Password Found: %s", cg); return (*env)->NewStringUTF(env, cg); } //increment(); attempt = SHA1Hash(cg); } } char **SHA1InterHash(char tempString[]) { SHA_CTX sha; unsigned int len = strlen (tempString); SHAInit(&sha); SHAUpdate(&sha, tempString, len); SHAFinal(digest, &sha); char p[41] = {0}; int i,j; for (i = j = 0; i < 20; ++i,j+=2) { //if ((i % 4) == 0) printf(" "); //printf("%02x", digest[i]); sprintf(p+j, "%02x", digest[i]); } return p; }
Einmal kann ich das 'p' nicht so einfach zurückgeben, jedenfalls nicht mit der Funktionsdefinition und dann kann ich nicht einfach diese Zuweisung durchführen "attempt = SHA1Hash(cg);"
DerProgrammierer