適應您的評論,這是接近,但不是很使用的鹽正確鏈接到Java實現:
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
,然後連接已提取的salt(已經是十六進制)。 (在Pete Finnigan博客的PL/SQL版本中,您可能會注意到他有一個明確的hextoraw
調用,所以我簡化了一下)。因此,對於您的示例,傳遞給dbms_crypto.hash
的參數應該是ZK3002
的十六進制(正常,未加工)等效,即5A4B33303032
,其中十六進制的鹽級聯到該值;所以5A4B333030321DB70EE23BFB23BDFD48
。
對於Java版本,您傳遞一個字節數組,但這意味着您需要將從存儲密碼中提取的鹽從十六進制中轉換回來,然後再將它加到密碼上;並且由於它不太可能具有有用的字符串表示形式,所以不妨將它直接放入字節數組中。因此,將密碼轉換爲字節數組,將鹽轉換爲字節數組,並將兩個數組粘在一起。然後這成爲您傳遞給MessageDigest
的值。
您可以將生成的散列與Oracle散列版本進行比較,跳過初始S:
和嵌入的salt。
如果您知道所有明文密碼,爲什麼不使用自己的salting + hashing過程,並用新的哈希密碼替換舊的密碼? – 2012-08-07 11:34:53
不,我不知道所有的密碼,只是我的(管理員)用戶的密碼。我會修改原來的問題,使其更清楚。 – 2012-08-07 12:00:35
啊,好的。鏈接頁面表示Oracle11g將SHA1(密碼|| salt)存儲在一列中。它不知道鹽是什麼或它存儲在哪裏。如果你能找到它,那麼實現這個相同的算法應該很容易。有關詳細信息,請參閱http://www.petefinnigan.com/weblog/archives/00001097.htm。 – 2012-08-07 12:05:28