Je serais plus que intéressant pour moi de comprendre quelle technique est utilisée ici pour persister les données sensibles depuis que je devais mettre en œuvre une solution similaire. Voici une configuration de connexion d'échantillon et l'extrait exporté obtenu:
<?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>
Tout conseil serait vraiment apprécié.
Pour le curieux, ce que vous voyez réellement est la clé secrète concaténée avec le mot de passe crypté. Par exemple, j'ai essayé de crypter le mot de passe "voilier" en utilisant:
DatabaseProviderHelper.goingOut("SAILBOAT")
Dans ce cas particulier, le résultat était:
[.____] 0527C290B40C41D71139B5E7A4446E94D7678359087249A463
Le premier octet est constant:
[.____] 05
Les 8 octets suivants représentent la clé secrète générée de manière aléatoire (pour le chiffrement DES):
27C290B40C41D711 [.____]
Les octets restants sont le mot de passe crypté:
39B5E7A4446E94D7678359087249A463 [.____]
Par conséquent, pour déchiffrer le mot de passe, vous utilisez simplement ceci:
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);
}
Notez que le mot de passe de Tim ci-dessus n'est pas pour "Apps_ro" - vraisemblablement, il a coupé et collé du mauvais endroit ... Je ne posterai pas le mot de passe réel au cas où il est quelque chose qu'il ne veut pas partagé!
J'ai eu un problème similaire, essayant de stocker mes identifiants de base de données de manière centralisée (pour des bases de données non sécurisées!), Puis exportation de fichiers XML de développeur SQL. Je n'ai aucune idée de ce que l'algorithme est - cependant, vous n'avez pas vraiment besoin de connaître l'algorithme, car vous pouvez simplement appeler l'Oracle Java API vous-même. Si vous avez SQLDEveloper, prenez simplement les fichiers JAR de droite:
cp /Applications/SQLDeveloper.App/Contents/Resources/sqldeveloper/BC4J/lib/db-ca.jar .
cp /Applications/SQLDeveloper.App/Contents/Resources/sqldeveloper/jlib/ojmisc.jar .
Ensuite, les chargez-les dans votre application Java ou utilisez quelque chose comme Jruby comme je le fais:
$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"
Notez que l'algorithme, quoi que ce soit, a un facteur aléatoire afin que le même mot de passe utilisé deux fois peut produire deux chaînes hexagonales différentes.
Cette solution fonctionne bien pour moi ... copié de: 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);
}
}
}
La solution donnée est trop ancienne et fonctionne uniquement avec la version 2.x mais pas maintenant. Parce que Oracle SQL Developer a modifié l'algorithme de cryptage dans la version 3.x et 4.x.
Version 3
Les mots de passe sont stockés cryptés dans le fichier Connections.xml dans ces emplacements:
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
Version 4
Les mots de passe sont stockés cryptés dans le fichier connections susmentionné.xml, mais la clé de cryptage utilise une valeur unique de la machine DB.System.Id dans le fichier préférences de produit.xml accessible ici:
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
Pour décrypter le dernier fichier crypté, vous pouvez utiliser ((( montre-moi mot de passe Extension pour le développeur SQL. Ou Decrypt File avec (( SQL Developer Mot de passe Decryptor
Le même code que Kornelissidetsma a donné, mais écrit sur 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();
}
}
Peut être exécuté comme suit:
# 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
Je ne suis pas sûr de cela, mais j'ai toujours pensé que les hachages ne peuvent pas être déchiffrés, comparé à un autre hachage. MD5 génère un hachage. Le mot de passe enregistré dans le développeur SQL doit être déchiffré et envoyer au serveur. Donc, les procédures Des3Crypt et Des3Decrypt dans le paquet DBMS_OBFUSCATION_TOOLKIT sont un meilleur pari. Mais le déchiffrement doit être appelé avant de se connecter à une base de données, il s'agit probablement d'un package Crypto JavaDES.
Voici un python Snippet si quelqu'un est interété. C'est une traduction de Adam Paynter exemple ci-dessus. Il utilise 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:])
Je ne sais pas, mais je ne serais pas surpris si c'était dbms_obfuscation_toolkit être utilisé quelque chose comme ceci:
l_hash := dbms_obfuscation_toolkit.md5(input_string=>:username||:password);
La longueur du hachage est de 50 caractères hexagonaux, qui sont de 200 bits, il se peut donc que le hachage du mot de passe avec un sel, a été préparé avec le sel, comme:
salt | hash(salt | password)
où | signifie une concaténation.
Juste spéculation cependant. Je suppose que le sel de 40 bits et un hachage SHA-1, puisque SHA-1 produit des hachages de 160 bits.
Serait utile de fournir des données de test d'entrée/sortie pour vérifier!