3

I'm using the STANDARD_HASH('input','SHA256') function within Oracle to populate records with their relative hash values.

This can be reproduced by connecting to Oracle doing:

select STANDARD_HASH('1234','SHA256') 
from dual
Table X    
Column 1, Column 1-hashed    
1234, sha512hashresult    
1234, sha512hashresult    
1234, sha512hashresult    
1234, sha512hashresult    

Now whats the question; What do I have to do in JAVA in order to reproduce exactly the hash values which are produced by STANDARD_HASH in Oracle? Does anyone have experience with this?

Note; For some reason there is no seed on the recommended Oracle hash function. Does anyone know the Default seed or how to figure this out?

Background: What do i want to do? Populate the table within Oracle with Oracle-Default-Tools and use a Java program to receive the input, hash it and select the correct record in the table.

What i don't want; People who tell me how I can achieve it in a different way, I need it exactly this way otherwise save your time

Oliver
  • 928
  • 9
  • 25
  • Instead of trying to reproduce the function in Java, why don't you just call it from Java using a service let's say(and let it execute on the DB side). – g00dy Sep 12 '17 at 12:01

2 Answers2

5

You can do this with standard libraries. Use java.security.MessageDigest with algorithm SHA-256:

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import javax.xml.bind.DatatypeConverter;
...

String input = "1234";        
byte[] hashBytes = MessageDigest.getInstance("SHA-256")
        .digest(input.getBytes(StandardCharsets.UTF_8));
String hash = DatatypeConverter.printHexBinary(hashBytes);
System.out.println(hash);

This prints 03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4, the same string that STANDARD_HASH would return.

As discussed in How to convert a byte array to a hex string in Java?, there are faster ways to convert a byte[] to a hex string, but DatatypeConverter.printHexBinary() has the benefit of being part of the standard library, and should be fine for most use cases.

Java 17 added HexFormat to the standard library, which lets you replace

String hash = DatatypeConverter.printHexBinary(hashBytes);

with

String hash = HexFormat.of().withUpperCase().formatHex(hashBytes);
markusk
  • 6,477
  • 34
  • 39
1

If you're fine with using Guava on the Java side, the following code should produce equal results with Oracle's STANDARD_HASH:

import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
...

String input = "1234";        
String hash = Hashing.sha256()
       .hashString(input, Charsets.UTF_8)
       .toString()
       // toString() returns the HEX value as lower-case, whereas
       // Oracle's STANDARD_HASH returns an upper-cased string
       .toUpperCase(); 

System.out.println(hash);

This prints out 03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4 which is the same you get in Oracle with

select STANDARD_HASH('1234','SHA256') from dual;
Mick Mnemonic
  • 7,808
  • 2
  • 26
  • 30