同様のソリューションを実装する必要があるので、ここでどの手法が実用的なデータを永続化するために使用されているかを理解することは、私にとって興味深いものです。接続構成の例と、結果としてエクスポートされるスニペットは次のとおりです。
<?xml version = '1.0' encoding = 'UTF-8'?>
<References xmlns="http://xmlns.Oracle.com/adf/jndi">
<Reference name="My Connection" className="Oracle.jdeveloper.db.adapter.DatabaseProvider" xmlns="">
<Factory className="Oracle.jdeveloper.db.adapter.DatabaseProviderFactory"/>
<RefAddresses>
<StringRefAddr addrType="user">
<Contents>username</Contents>
</StringRefAddr>
<StringRefAddr addrType="password">
<Contents>054D4844D8549C0DB78EE1A98FE4E085B8A484D20A81F7DCF8</Contents>
</StringRefAddr>
<SKIPPED />
</RefAddresses>
</Reference>
</References>
どんなアドバイスでも本当にいただければ幸いです。
興味深いことに、実際に表示されているのは、暗号化されたパスワードと連結された秘密鍵です。たとえば、「SAILBOAT」というパスワードを次のように暗号化してみました。
DatabaseProviderHelper.goingOut("SAILBOAT")
この特定の例では、結果は次のとおりです。
0527C290B40C41D71139B5E7A4446E94D7678359087249A463
最初のバイトは定数です:
05
次の8バイトは、ランダムに生成された秘密鍵を表します(DES暗号の場合):
27C290B40C41D711
残りのバイトは暗号化されたパスワードです:
39B5E7A4446E94D7678359087249A463
したがって、パスワードを復号化するには、これを使用するだけです。
public static byte[] decryptPassword(byte[] result) throws GeneralSecurityException {
byte constant = result[0];
if (constant != 5) {
throw new IllegalArgumentException();
}
byte[] secretKey = new byte[8];
System.arraycopy(result, 1, secretKey, 0, 8);
byte[] encryptedPassword = new byte[result.length - 9];
System.arraycopy(result, 9, encryptedPassword, 0, encryptedPassword.length);
byte[] iv = new byte[8];
for (int i = 0; i < iv.length; i++) {
iv[i] = 0;
}
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secretKey, "DES"), new IvParameterSpec(iv));
return cipher.doFinal(encryptedPassword);
}
上記のTimのパスワードハッシュは「apps_ro」用ではないことに注意してください-おそらく彼は間違った場所からカットアンドペーストしました...彼が共有したくないものである場合に備えて、実際のパスワードは投稿しません!
同様の問題があり、db資格情報を一元的に保存しようとし(非セキュアデータベースの場合)、SQL開発者のxmlファイルをエクスポートしました。アルゴリズムが何であるかはわかりませんが、Oracle Java APIを自分で呼び出すことができるため、実際にアルゴリズムを知る必要はありません。SQLDeveloperがある場合は、右のjarファイル:
cp /Applications/SQLDeveloper.App/Contents/Resources/sqldeveloper/BC4J/lib/db-ca.jar .
cp /Applications/SQLDeveloper.App/Contents/Resources/sqldeveloper/jlib/ojmisc.jar .
次に、これらをJavaアプリにロードするか、JRubyのようなものを使用します。
$jirb
> require 'Java'
> require 'ojmisc.jar'
> require 'db-ca.jar'
> Java::Oracle.jdevimpl.db.adapter.DatabaseProviderHelper.goingOut("password")
=> "059D45F5EB78C99875F6F6E3C3F66F71352B0EB4668D7DEBF8"
> Java::Oracle.jdevimpl.db.adapter.DatabaseProviderHelper.goingOut("password")
=> "055CBB58B69B477714239157A1F95FDDD6E5B453BEB69E5D49"
> Java::Oracle.jdevimpl.db.adapter.DatabaseProviderHelper.comingIn("059D45F5EB78C99875F6F6E3C3F66F71352B0EB4668D7DEBF8")
=> "password"
> Java::Oracle.jdevimpl.db.adapter.DatabaseProviderHelper.comingIn("055CBB58B69B477714239157A1F95FDDD6E5B453BEB69E5D49")
=> "password"
アルゴリズムには、それが何であれランダムな要素があるため、同じパスワードを2回使用すると、2つの異なる16進文字列が生成される可能性があります。
このソリューションは私にとって素晴らしい働きをします...コピー元: http://www.mischiefblog.com/?p=912
import javax.crypto.*;
import javax.crypto.spec.*;
import Java.security.*;
/**
* Decrypt passwords stored in Oracle SQL Developer. This is intended for
* password recovery.
*
* Passwords are stored in
* ~/.sqldeveloper/system2.1.1.64.39/o.jdeveloper.db.connection
* .11.1.1.2.36.55.30/connections.xml
*/
public class Decrypt {
public static byte[] decryptPassword(byte[] result)
throws GeneralSecurityException {
byte constant = result[0];
if (constant != (byte) 5) {
throw new IllegalArgumentException();
}
byte[] secretKey = new byte[8];
System.arraycopy(result, 1, secretKey, 0, 8);
byte[] encryptedPassword = new byte[result.length - 9];
System.arraycopy(result, 9, encryptedPassword, 0,
encryptedPassword.length);
byte[] iv = new byte[8];
for (int i = 0; i < iv.length; i++) {
iv[i] = 0;
}
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secretKey, "DES"),
new IvParameterSpec(iv));
return cipher.doFinal(encryptedPassword);
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: Java Decrypt <password>");
System.exit(1);
}
if (args[0].length() % 2 != 0) {
System.err
.println("Password must consist of hex pairs. Length is odd (not even).");
System.exit(2);
}
byte[] secret = new byte[args[0].length() / 2];
for (int i = 0; i < args[0].length(); i += 2) {
String pair = args[0].substring(i, i + 2);
secret[i / 2] = (byte) (Integer.parseInt(pair, 16));
}
try {
System.out.println(new String(decryptPassword(secret)));
} catch (GeneralSecurityException e) {
e.printStackTrace();
System.exit(3);
}
}
}
指定されたソリューションは古すぎて、バージョン2.xでのみ機能しますが、現在は機能しません。 Oracle SQL Developerがバージョン3.xおよび4.xで暗号化アルゴリズムを変更したため。
バージョン3
パスワードは、次の場所にあるconnections.xmlファイルに暗号化されて保存されます。
Windows: C:\Users\<USER>\AppData\Roaming\SQL Developer\system<VERSION>\o.jdeveloper.db.connection.<VERSION>\connections.xml
Linux: ~/.sqldeveloper/system<VERSION>/o.jdeveloper.db.connection.<VERSION>/connections.xml
バージョン4
パスワードは前述のconnections.xmlファイルに暗号化されて保存されますが、暗号化キーは、ここからアクセス可能なproduct-preferences.xmlファイルのmachine-unique値db.system.idを使用します。
Windows: C:\Users\<USER>\AppData\Roaming\SQL Developer\system<VERSION>\o.sqldeveloper.<VERSION>\product-preferences.xml
Linux: ~/.sqldeveloper/system<VERSION>/o.sqldeveloper.<VERSION>/product-preferences.xml
最新の暗号化ファイルを復号化するには、SQL Developerの Show me password 拡張子を使用できます。または SQL Developerパスワード復号化子 でファイルを復号化します
Kornelissietsmaと同じコードが指定されていますが、Javaで記述されています。
import Oracle.jdevimpl.db.adapter.DatabaseProviderHelper;
class Decode {
String pass = "";
public Decode() {
pass = DatabaseProviderHelper.comingIn("HASH");
System.out.println(pass);
}
public static void main(String[] args){
new Decode();
}
}
次のように実行できます。
# javac -classpath .:/full/path/to/sqldeveloper/BC4J/lib/db-ca.jar:/full/path/to/sqldeveloper/jlib/ojmisc.jar sqldeveloper_hash_decode.Java
# Java -classpath .:/full/path/to/sqldeveloper/BC4J/lib/db-ca.jar:/full/path/to/sqldeveloper/jlib/ojmisc.jar Decode
他の回答で説明されているメソッドは、残念ながらSQL Developer 4.xでは機能しません。 3.xと4.xの両方のバージョンで機能する拡張機能があり、非常に使いやすいです。
私はこれについてはわかりませんが、ハッシュは他のハッシュと比較して解読できないといつも思っていました。 MD5はハッシュを生成します。 SQL Developerに保存されているパスワードを復号化してサーバーに送信する必要があります。したがって、dbms_obfuscation_toolkitパッケージのDES3EncryptおよびDES3Decryptプロシージャの方が適しています。ただし、復号化はデータベースに接続する前に呼び出す必要があるため、おそらくJavaメソッドを備えたDES暗号パッケージです。
これはpythonのスニペットです。誰かが邪魔をしている場合です。これは上記の Adam Paynter's の例の翻訳です。これは pyDes を使用しています。
import os
import pyDes
import binascii
if __name__ == '__main__':
# Encrypt example
zero = '\0\0\0\0\0\0\0\0'
key = os.urandom(8)
plainText = 'open sesame'
cipher = pyDes.des(key, mode=pyDes.CBC, IV=zero, padmode=pyDes.PAD_PKCS5)
cipherText = '\5%s%s' % (key, cipher.encrypt(plainText))
cipherHex = binascii.hexlify(cipherText)
# This is what SQLDeveloper stores in XML
print cipherHex
# Decrypt above
cipherText = binascii.unhexlify(cipherHex)
assert cipherHex[0:2] == '05'
key = cipherText[1:1+8]
cipher = pyDes.des(key, mode=pyDes.CBC, IV=zero, padmode=pyDes.PAD_PKCS5)
print cipher.decrypt(cipherText[1+8:])
わかりませんが、 DBMS_OBFUSCATION_TOOLKIT が次のように使用されていても驚くことはありません。
l_hash := dbms_obfuscation_toolkit.md5(input_string=>:username||:password);
ハッシュの長さは50桁の16進文字、つまり200ビットなので、次のように、ソルトを前に付加したソルトを含むパスワードのハッシュになります。
salt | hash(salt | password)
どこ|連結を意味します。
ただの憶測です。 SHA-1は160ビットのハッシュを生成するので、私の推測は40ビットのソルトとSHA-1のハッシュでしょう。
チェックするいくつかの入力/出力テストデータを提供すると役立ちます!