2017-08-26 4 views
3

Ich benutze PBKDF2 Kennwort Hashing-Technik in meinem Programm. Das Beispielprogramm, auf die ich mich beziehe ist in C. Das Programm Schnipsel ist wie folgt:Ausgabedifferenz in C-Implementierung von Java-Code

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <getopt.h> 
#include <openssl/evp.h> 
#include <openssl/rand.h> 
#include "base64.h" 

#define KEY_LENGTH  24 
#define SEPARATOR  "$" 
#define SALTLEN 12 

#define USAGE() fprintf(stderr, "Usage: %s [-i iterations] [-p password]\n", progname) 

int main(int argc, char **argv) 
{ 
    int iterations = 901, rc, blen; 
    unsigned char saltbytes[SALTLEN]; 
    char *salt, *b64; 
    unsigned char key[128]; 
    char *pw1, *pw2, *password; 
    char *progname = argv[0]; 
    int c; 
    int prompt; 

    prompt = 1; 

    while ((c = getopt(argc, argv, "i:p:")) != EOF) { 
     switch (c) { 
      case 'i': 
       iterations = atoi(optarg); 
       break; 
      case 'p': 
       pw1 = strdup(optarg); 
       pw2 = strdup(optarg); 
       prompt = 0; 
       break; 
      default: 
       exit(USAGE()); 
     } 
    } 

    argc -= optind - 1; 
    argv += optind - 1; 

    if (argc != 1) { 
     exit(USAGE()); 
    } 

    if (prompt) { 
     pw1 = strdup(getpass("Enter password: ")); 
     pw2 = getpass("Re-enter same password: "); 
    } 

    if (strcmp(pw1, pw2) != 0) { 
     fprintf(stderr, "Passwords don't match!\n"); 
     return (1); 
    } 

    password = pw1; 

    rc = RAND_bytes(saltbytes, SALTLEN); 
    if (rc == 0) { 
     fprintf(stderr, "Cannot get random bytes for salt!\n"); 
     return 2; 
    } 

    base64_encode(saltbytes, SALTLEN, &salt); 

#ifdef RAW_SALT 
    PKCS5_PBKDF2_HMAC(password, strlen(password), 
     (unsigned char *)saltbytes, SALTLEN, 
     iterations, 
     EVP_sha256(), KEY_LENGTH, key); 
#else 
    int saltlen; 
    saltlen = strlen(salt); 

    PKCS5_PBKDF2_HMAC(password, strlen(password), 
     (unsigned char *)salt, saltlen, 
     iterations, 
     EVP_sha256(), KEY_LENGTH, key); 
#endif 


    blen = base64_encode(key, KEY_LENGTH, &b64); 
    if (blen > 0) { 
     printf("PBKDF2$%s$%d$%s$%s\n", 
      "sha256", 
      iterations, 
      salt, 
      b64); 

     free(b64); 
    } 

    free(password); 
    return 0; 
} 

Und das C-Programm Ausgabe wird wie folgt dar: PBKDF2 $ sha256 $ 901 $ QLtznh6yjEs4a4Fl $ uzp3QAEpFZsqBvCssnL1eXZFxCiKzV7P

ich habe versucht, das gleiche in Java zu replizieren, die wie folgt lautet:

public class NewPBKDF2 { 

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException { 
     String originalPassword = "A3E9907E59A6379DB6A9C2657D242A64886D5B21E3586B3D4C2B4E6329570A10"; 
     String generatedSecuredPasswordHash = generateStorngPasswordHash(originalPassword); 
     System.out.println(generatedSecuredPasswordHash); 
    } 

    private static String generateStorngPasswordHash(String password) throws NoSuchAlgorithmException, InvalidKeySpecException { 
     int iterations = 901; 
     char[] chars = password.toCharArray(); 
     byte[] salt = getSalt(); 
     String salt1 = Base64.getEncoder().encodeToString(salt); 
     int length = 24; 




     PBEKeySpec spec = new PBEKeySpec(chars, salt, iterations, length * 8); 
     SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); 
     byte[] hash = skf.generateSecret(spec).getEncoded(); 
     String hash1 = bytesToHex(hash); 

     try { 
      hash1 = Base64.getEncoder().encodeToString(hash1.getBytes("utf-8")); 
     } catch (UnsupportedEncodingException ex) { 
      Logger.getLogger(NewPBKDF2.class.getName()).log(Level.SEVERE, null, ex); 
     } 


     return "PBKDF2$sha256$"+ iterations +"$"+salt1+"$"+hash1; 
    } 

    private static byte[] getSalt() throws NoSuchAlgorithmException { 
     SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 

     byte[] salt = new byte[12]; 


     sr.nextBytes(salt); 
     return salt; 
    } 

    static char[] hexArray = "ABCDEF".toCharArray(); 
    public static String bytesToHex(byte[] bytes) { 
     char[] hexChars = new char[bytes.length * 2]; 
     for (int j = 0; j < bytes.length; j++) { 
      int v = bytes[j] & 0xFF; 
      hexChars[j * 2] = hexArray[v >>> 4]; 
      hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
     } 
     return new String(hexChars); 
    } 

    public static byte[] hexStringToByteArray(String s) { 
     int len = s.length(); 
     byte[] data = new byte[len/2]; 
     for (int i = 0; i < len; i += 2) { 
      data[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 
        + Character.digit(s.charAt(i+1), 16)); 
     } 
     return data; 
    } 

} 

Und das obige Programm gibt mir wie folgt ausgegeben:

PBKDF2 $ SHA256 901 $ $ v2DdYPk47r/I3aQJ $ N0Y3MjZENzVEOTE5MDcxQkNEOEM5MTAyREQ2MjdEQ0NGNzIzRTZGN0ZCOUYzN0NF

Warum ich verschiedene Passwortlänge immer bin (der letzte Teil). Ich verstehe es nicht. Können Sie mir bitte helfen, meinen Fehler zu finden?

+0

Was ist in 'originalPassword' (genau) Variable gespeichert? – Mandy8055

+0

String ist jetzt hardcoded. aber es wird zufällig erzeugt werden /. –

Antwort

1

Die Antwort auf Ihre Frage ist auf die Grundlagen der verschiedenen Zeichencodierung Stile gelegt. Und die Unähnlichkeit in der Länge von String ist wegen der Verwendung von verschiedenen Encoding in beiden Fällen (C und Java-Implementierung).

Sie können in Ihrem Beispiel beachten Sie, dass die hash1 (wegen dem die Unähnlichkeit in der Länge ist prominent) Variable in UTF-8 in Java codiert wird, während die C ASCII Zeichenkodierung verwendet (Bereits in den ANSI Normen erwähnt).
Auch UTF-8 ist eine Multi-Byte-Codierung ist eine Multi-Byte-Codierung, die zwischen 1 und 4 Bytes pro Zeichen verwendet. Sie können auch diese verweisen: How many bytes does Unicode Character takes? die interessant sein könnte und deshalb die Hashes in der Länge länger in Java sind im Vergleich zu C.

Hoffen, dass die Antwort hilft, einige Erkenntnisse über das gut recherchierten Problem zu bekommen.

Verwandte Themen