4

我一直在研究 Oracle 针对 10g 数据库进行身份验证的机制。尽管它的文档比其 9i 版本少,但我仍然设法在各种网站和博客上找到了它的许多详细信息。然而,一件仍然是一个谜。在我提到缺少什么之前,让我用伪代码解释一下对协议的了解:

// CLIENT SIDE PSEUDO CODE

user = "SCOTT"
password = "TIGER"
password_hash = oracle_password_hash(user, password)

// 1. Client provides user name to server
send(user)

// 2. Server responds with its encrypted AUTH_SESSKEY, 
//    a randomly generated number associated with the current session
encrypted_server_AUTH_SESSKEY = receive_AUTH_SESSKEY() // 32 bytes

decrypted_server_AUTH_SESSKEY = aes_decrypt(
    encrypted_input => encrypted_server_AUTH_SESSKEY,
    decryption_key  => password_hash
)

// 3. Client generates its own AUTH_SESSKEY for this session
unencrypted_client_AUTH_SESSKEY = generate_random_AUTH_SESSKEY() // 32 bytes

encrypted_client_AUTH_SESSKEY = aes_encrypt(
    unencrypted_input => unencrypted_client_AUTH_SESSKEY,
    encryption_key    => password_hash
)

// 4. Client combines the two AUTH_SESSKEYs using a known Oracle-specific algorithm
combined_AUTH_SESSKEYs = oracle_combine(decrypted_server_AUTH_SESSKEY, unencrypted_client_AUTH_SESSKEY)

// 5. Client builds AUTH_PASSWORD
unencrypted_AUTH_PASSWORD = byte[32]
unencrypted_AUTH_PASSWORD[0 .. 16] = ??? // THIS IS THE PROBLEM
unencrypted_AUTH_PASSWORD[16 .. 16 + len(password)] = password
unencrypted_AUTH_PASSWORD[16 + len(password) .. ] = PKCS#7 padding

// 6. Client encrypts the AUTH_PASSWORD data using the combined AUTH_SESSKEYs as the encryption key
encrypted_AUTH_PASSWORD = aes_encrypt(
    unencrypted_input => unencrypted_AUTH_PASSWORD,
    encryption_key    => combined_AUTH_SESSKEYs
)

// 7. Client transmits its encrypted AUTH_SESSKEY and AUTH_PASSWORD to server for verification
send(encrypted_client_AUTH_SESSKEY, encrypted_AUTH_PASSWORD)

Oracle 客户端在步骤 5 中将 AUTH_PASSWORD 值的低 16 个字节放入了什么?

我发现的几乎所有文档都只关心获取其中包含的纯文本密码,很少注意这些第一个字节。我曾尝试查看 JDBC 驱动程序,但似乎即使是 10g 版本也通过请求服务器恢复为旧方案(这恰好更好理解)来避免这种身份验证方案。一个优秀的C 程序演示了 AUTH_PASSWORD 的解密。

谁能指出我正确的方向?

4

2 回答 2

3

我已经确定明文密码之前的 16 个字节是随机生成的(好奇的可以看看 oran10.dll 库导出的 ztvo5pe 函数——你会看到对 ztcen 的两次连续调用,第一次调用填充它在)。

我最初发布这个问题是因为我正在编写一个小程序来连接到 Oracle 数据库而不使用 Oracle 的 JDBC 驱动程序。我发现数据库拒绝了我的 32 字节 AUTH_PASSWORD。我假设它被拒绝了,因为我在前 16 个字节中输入了不正确的值。我错了。这些似乎对用户是否进行身份验证没有任何影响。

相反,事实证明数据库拒绝了我的 AUTH_PASSWORD 因为紧跟在纯文本密码之后的尾随字节。我天真地用零填充缓冲区。它应该根据 PKCS #7 规范进行填充。

于 2009-02-18T14:00:17.633 回答
-1

如果密码长度<16,前16个字节是随机数据,那么密码,填充数据是char of (16 – strlen(password))。Oracle 服务器可以接受我的 AUTH_PASSWORD。如果密码长度>= 16,我不知道该怎么做。我用随机数据填充了前 16 个字节,但服务器拒绝了我的数据。我想知道:您确定填充数据符合 PKCS#7 规范吗?

于 2009-07-22T06:04:04.377 回答