java - portable - ¿Alguien sabe qué técnica de cifrado utiliza JDeveloper/SQL Developer para conservar las credenciales?
sql developer ubuntu (11)
Sería más que interesante para mí entender qué técnica se está utilizando aquí para conservar datos sensibles ya que necesito implementar una solución similar. Aquí hay una configuración de conexión de muestra y el fragmento exportado resultante:
Oracle SQL Developer Connections http://i44.tinypic.com/2lcwpkg.gif
<?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>
Cualquier consejo será apreciado.
Aquí hay un fragmento de Python si alguien está intercalado. Es una traducción del ejemplo anterior de . Utiliza 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:])
El mismo código que kornelissietsma ha dado, pero escrito en 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();
}
}
Se puede ejecutar de la siguiente manera:
# 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
Esta solución funciona muy bien para mí ... Copiado 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);
}
}
}
FYI la contraseña ''apps_ro'' encripta como:
<StringRefAddr addrType="password">
<Contents>051DC8A88C574538CC4AEE32D326E9480659C06CEC271EA6D7</Contents>
</StringRefAddr>
La longitud del hash es de 50 caracteres hexadecimales, que son 200 bits, por lo que puede ser el hash de la contraseña con una sal, junto con la sal, como:
salt | hash(salt | password)
donde | significa concatenación.
Solo especulación sin embargo. Mi suposición sería una sal de 40 bits y un hash SHA-1, ya que SHA-1 produce hashes de 160 bits.
¡Sería útil proporcionar datos de prueba de entrada / salida para verificar!
La solución dada es demasiado antigua y solo funciona con la versión 2.x pero no ahora. porque Oracle SQL Developer, cambió el algoritmo de cifrado en la versión 3.xy 4.x.
Versión 3
Las contraseñas se almacenan cifradas en el archivo connections.xml en esas ubicaciones:
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
Versión 4
Las contraseñas se almacenan cifradas en el archivo connections.xml antes mencionado, pero la clave de cifrado utiliza un valor único de la máquina db.system.id en el archivo product-preferences.xml accesible aquí:
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
Para descifrar el archivo cifrado más reciente, puede usar la extensión Mostrar contraseña para SQL Developer. O descifrar el archivo con descifrador de contraseñas de SQL Developer
Los métodos descritos en otras respuestas desafortunadamente no funcionan en SQL Developer 4.x. Hay una extensión que funciona en las versiones 3.x y 4.x y es muy fácil de usar:
No estoy seguro de esto, pero siempre pensé que los hash no pueden ser descifrados, solo en comparación con otro hash. MD5 genera un hash. La contraseña guardada en SQL Developer debe ser descifrada y enviada al servidor. Así que los procedimientos DES3Encrypt y DES3Decrypt en el paquete dbms_obfuscation_toolkit son una mejor opción. Pero debe llamarse al descifrado antes de conectarse a una base de datos, por lo que probablemente sea un paquete criptográfico Java con métodos DES.
No lo sé, pero no me sorprendería si DBMS_OBFUSCATION_TOOLKIT se utilizara de la siguiente manera:
l_hash := dbms_obfuscation_toolkit.md5(input_string=>:username||:password);
Para los curiosos, lo que realmente está viendo es la clave secreta concatenada con la contraseña encriptada. Por ejemplo, intenté encriptar la contraseña "VELERO" usando:
DatabaseProviderHelper.goingOut("SAILBOAT")
En esta instancia particular, el resultado fue:
0527C290B40C41D71139B5E7A4446E94D7678359087249A463
El primer byte es constante:
05
Los siguientes 8 bytes representan la clave secreta generada aleatoriamente (para el cifrado DES):
27C290B40C41D711
Los bytes restantes son la contraseña encriptada:
39B5E7A4446E94D7678359087249A463
Por lo tanto, para descifrar la contraseña, simplemente usa esto:
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);
}
Tenga en cuenta que el hash de contraseña de Tim anterior no es para "apps_ro", presumiblemente se cortó y pegó en el lugar equivocado ... No publicaré la contraseña real en caso de que sea algo que no quiera compartir.
Tuve un problema similar, tratando de almacenar mis credenciales de db de forma centralizada (¡para bases de datos no seguras!) Y luego exportar los archivos xl del desarrollador de sql. No tengo idea de qué es el algoritmo; sin embargo, no es necesario que conozcas el algoritmo, ya que solo puedes llamar a la API de Oracle java. Si tiene SQLDeveloper, solo tome los archivos jar correctos:
cp /Applications/SQLDeveloper.App/Contents/Resources/sqldeveloper/BC4J/lib/db-ca.jar .
cp /Applications/SQLDeveloper.App/Contents/Resources/sqldeveloper/jlib/ojmisc.jar .
Luego, cárgalos en tu aplicación Java o utiliza algo como JRuby como yo:
$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"
Tenga en cuenta que el algoritmo, sea lo que sea, tiene un factor aleatorio, por lo que la misma contraseña utilizada dos veces puede producir dos cadenas hexagonales diferentes.