我一直在研究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 program演示了AUTH_PASSWORD的解密。
有人能指出我正确的方向吗?
答案 0 :(得分:3)
我已经确定了明文密码之前的16个字节是随机生成的(对于好奇的,看看oran10.dll库导出的ztvo5pe函数 - 你会看到两个连续调用ztcen,第一个电话填写它。)
我最初发布这个问题是因为我正在编写一个小程序来连接Oracle数据库,而不使用Oracle的JDBC驱动程序。我发现数据库拒绝了我的32字节AUTH_PASSWORD。我认为它被拒绝了,因为我在前16个字节中放了一个不正确的值。我错了。看来这些对用户是否进行身份验证没有任何影响。
相反,事实证明数据库拒绝了我的AUTH_PASSWORD,因为紧跟在纯文本密码之后的尾随字节。我天真地用零填充缓冲区。它应该根据PKCS#7规范填充。
答案 1 :(得分:-1)
如果密码长度< 16,前16个字节是随机数据,然后是密码,填充数据是char(16 - strlen(密码))。 Oracle服务器可以接受我的AUTH_PASSWORD。 如果密码长度> = 16,我不知道该怎么做。我用随机数据填充了前16个字节,但服务器拒绝了我的数据。 我想知道:你确定填充数据符合PKCS#7规范。