简体   繁体   中英

Java 8 vs Python 2.7 pbkdf2 hashing — different output hash letter casing

I have written, previously in Python, a function to garble a target string using PBKDF2:

from hashlib import pbkdf2_hmac
from binascii import hexlify

def garbleString(string, salt, iterations, hash_algorithm):
    target = str.encode(string)
    dk = pbkdf2_hmac(hash_algorithm, target, salt, iterations)
    hash = hexlify(dk)
    return (hash, salt, iterations)

>>> garbleString("1000000000","salt",100000,'sha256')
('d973f4855206bd777b25355782f1b14bf06fb395bf49a26086035b3b8820a74b', 'salt',  100000)

Based on this page, this function is correct -- it yields the same hash for the same inputs. http://www.neurotechnics.com/tools/pbkdf2

I am now trying to implement the same in Java, here is where I am now:

import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.xml.bind.DatatypeConverter;

public class GarbledStringFactory {

    private String algorithm;

    public GarbledStringFactory(String algorithm){
        this.algorithm = algorithm;
    }
    public String getGarbledString(String string, String salt,  int iterations,  int derivedKeyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
        SecretKeyFactory f = SecretKeyFactory.getInstance(this.algorithm);
        KeySpec spec = new PBEKeySpec(string.toCharArray(), salt.getBytes(), iterations, derivedKeyLength * 8);
        SecretKey key = f.generateSecret(spec);
        String hexStr = DatatypeConverter.printHexBinary(key.getEncoded());
        return hexStr;
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {
        // TODO Auto-generated method stub
        GarbledStringFactory factory = new GarbledStringFactory("PBKDF2WithHmacSHA256");
        String hash = factory.getGarbledString("1000000000","salt",100000,32);
        System.out.println(hash);
    }
}

This yields the hash "D973F4855206BD777B25355782F1B14BF06FB395BF49A26086035B3B8820A74B", which is the same, just with different letter casing. Does the casing matter?

No, the casing doesn't matter.

If you inspect the hashes you'll find that the only letters included are from A to F. This isn't really a string, but rather a hexadecimal (base 16) number equivalent to 98356763175438224738455306401383784358747884932620687880657531803811513935691 in decimal / base 10.

  • A₁₆ (A in base 16) is the same as 10₁₀ (10 in base 10)
  • B₁₆ is 11₁₀
  • C₁₆ is 12₁₀
  • D₁₆ is 13₁₀
  • E₁₆ is 14₁₀
  • F₁₆ is 15₁₀

It doesn't matter whether the digits are shown in upper- or lower-case. The meaning is the same.

You can see this in the Python interpreter, where a leading 0x indicates a hexadecimal number:

>>> hex(12)
'0xc'
>>> 0xf
15
>>> 0xF
15

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM