コメントでリンクしたJava実装を適応させます。これは近いですが、saltを適切に使用していません。
import java.security.MessageDigest;
import java.util.Formatter;
class Main{
public static String calculateHash(String password) throws Exception{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
String encodedPassword = "S:71752CE0530476A8B2E0DD218AE59CB71B211D7E1DB70EE23BFB23BDFD48";
// Convert password to bytes
byte[] bPassword = password.getBytes("UTF-8");
// Get salt from encoded password
String salt = encodedPassword.substring(42, 62);
System.out.println("Salt is " + salt);
// Convert salt from hex back to bytes
// based on http://stackoverflow.com/a/140861/266304
int len = salt.length();
byte[] bSalt = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
bSalt[i / 2] = (byte) ((Character.digit(salt.charAt(i), 16) << 4)
+ Character.digit(salt.charAt(i+1), 16));
}
// Add converted salt to password bytes
// based on http://stackoverflow.com/a/80503/266304
byte[] bData = new byte[bPassword.length + bSalt.length];
System.arraycopy(bPassword, 0, bData, 0, bPassword.length);
System.arraycopy(bSalt, 0, bData, bPassword.length, bSalt.length);
// Hash the final byte array
crypt.update(bData);
byte bHash[] = crypt.digest();
Formatter formatter = new Formatter();
for (byte b : bHash)
{
formatter.format("%02x", b);
}
System.out.println("Expected " + encodedPassword.substring(2,42));
return formatter.toString().toUpperCase();
}
public static void main(String[] args) throws Exception {
System.out.println("The result is " + calculateHash("ZK3002"));
}
}
これは出力を与えます:
Salt is 1DB70EE23BFB23BDFD48
Expected 71752CE0530476A8B2E0DD218AE59CB71B211D7E
The result is 71752CE0530476A8B2E0DD218AE59CB71B211D7E
PL/SQLバージョンにはいくつかの変換が含まれます。dbms_crypto.hash()
引数を取るRAW
ので、プレーンテキストのパスワードをに変換してからRAW
、抽出されたソルトを連結する必要があります。これはすでに16進数です。(PeteFinniganのブログのPL/ SQLバージョンでは、彼が明示的なhextoraw
呼び出しを行っていることに気付くかもしれません。そのため、少し単純化しています)。したがって、この例で渡される引数は、dbms_crypto.hash
に相当する16進数(OK、raw)になりますZK3002
。これは5A4B33303032
、16進数のソルトが連結されたものです。そう5A4B333030321DB70EE23BFB23BDFD48
。
Javaバージョンの場合、バイト配列を渡しますが、これは、保存されているパスワードから抽出されたソルトを、パスワードに追加する前に16進数から変換する必要があることを意味します。また、有用な文字列表現がない可能性が高いため、バイト配列に直接配置することもできます。したがって、パスワードをバイト配列に変換し、ソルトをバイト配列に変換して、2つの配列を結合します。これが、に渡す値になりますMessageDigest
。
これが生成するハッシュをOracleハッシュバージョンと比較できます。最初S:
のソルトと埋め込まれたソルトはスキップします。