gpt4 book ai didi

java - 将 Oracle 身份验证迁移到表

转载 作者:太空宇宙 更新时间:2023-11-04 08:07:28 25 4
gpt4 key购买 nike

我有一个基于 Java/Spring 且使用 Oracle 11g 的 Web 应用程序。目前,用户在登录时通过用户名/密码直接针对系统表 SYS.USER$ 进行身份验证。

这种情况必须改变,因此我们创建了一个(常规)新表来存储所有用户数据。我们将所有现有密码插入到新创建的表中。但是,密码似乎以 this site 描述的方式进行了加密/散列。

一个示例:一旦用户输入 XXXXX,数据库就会存储 07E4898C06DEF253

我想使用存储在新(常规)表中的旧密码执行身份验证。我的问题是我不知道如何验证现有密码,因为我不确切知道它们是如何散列/加密的。

我玩过ora_hashdbms_obfuscation_toolkit.DESDecrypt ,但这些都没有给我正确的结果。我知道我的用户的正确密码,并且可以看到 Oracle 为该密码生成的值,但我无法重现 Oracle 通常“处理”密码数据的方式。

有什么办法可以在不重置所有密码的情况下解决这个问题吗?

最佳答案

调整您在评论中链接到的 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 ,然后连接提取的盐 - 它已经是十六进制的。 (在 Pete Finnigan 博客的 PL/SQL 版本中,您可能会注意到他有一个显式的 hextoraw 调用,因此我进行了一些简化)。因此,对于您的示例,传递给 dbms_crypto.hash 的参数将是 ZK3002 的十六进制(OK,原始)等效项,即 5A4B33303032,并连接有十六进制盐;所以5A4B333030321DB70EE23BFB23BDFD48

对于 Java 版本,您传递一个字节数组,但这意味着您需要将从存储的密码中提取的盐从十六进制转换回十六进制,然后再将其附加到密码上;由于它不太可能有有用的字符串表示形式,因此您最好将其直接放入字节数组中。因此,将密码转换为字节数组,将盐转换为字节数组,然后将两个数组粘在一起。然后,该值将成为您传递给 MessageDigest 的值。

您可以将生成的哈希值与 Oracle 哈希版本进行比较,跳过初始的 S: 和嵌入的盐。

关于java - 将 Oracle 身份验证迁移到表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11843891/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com