¿Alguien sabe qué técnica de cifrado utiliza JDeveloper / SQL Developer para conservar las credenciales?

StackOverflow https://stackoverflow.com/questions/1032721

Pregunta

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:

 Conexiones Oracle Developer Developer

<?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ía muy apreciado.

¿Fue útil?

Solución

Para los curiosos, lo que realmente está viendo es la clave secreta concatenada con la contraseña cifrada. Por ejemplo, intenté encriptar la contraseña " SAILBOAT " utilizando:

DatabaseProviderHelper.goingOut("SAILBOAT")

En este caso 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 cifrada:

39B5E7A4446E94D7678359087249A463

Por lo tanto, para descifrar la contraseña, simplemente use 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);
}

Otros consejos

Tenga en cuenta que el hash de contraseña anterior de Tim no es para " apps_ro " - presumiblemente cortó y pegó desde 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 db de forma centralizada (¡para bases de datos no seguras!) y luego exportando archivos xml de sql developer. No tengo idea de qué es el algoritmo; sin embargo, realmente no necesita conocer el algoritmo, ya que puede llamar a la API de Oracle java usted mismo. Si tiene SQLDeveloper, simplemente 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árguelos en su aplicación Java o use algo como JRuby como lo hago 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 hexadecimales diferentes.

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);
        }
    }
}

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 encriptadas 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 encriptadas en el archivo connections.xml mencionado anteriormente, pero la clave de encriptación utiliza un valor único de máquina db.system.id en el archivo product -ferences.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 Mostrarme contraseña extensión para SQL Developer. O descifre el archivo con descifrador de contraseña de desarrollador SQL

El mismo código que ha dado kornelissietsma, 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

Los métodos descritos en otras respuestas lamentablemente no funcionan en SQL Developer 4.x. Hay una extensión que funciona en las versiones 3.xy 4.xy es muy fácil de usar:

https://github.com/tomecode/show-me-password- sqldev-jdev

No estoy seguro de esto, pero siempre pensé que los hash no se pueden descifrar, solo en comparación con otro hash. MD5 genera un hash. La contraseña guardada en SQL Developer necesita ser descifrada y enviada al servidor. Por lo tanto, los procedimientos DES3Encrypt y DES3Decrypt en el paquete dbms_obfuscation_toolkit son una mejor opción. Pero se debe llamar al descifrado antes de conectarse a una base de datos, por lo que probablemente sea un paquete criptográfico Java con métodos DES.

Aquí hay un fragmento de Python si alguien está interesado. Es una traducción del Adam Paynter ejemplo anterior. 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:])

No lo sé, pero no me sorprendería si fuera DBMS_OBFUSCATION_TOOLKIT se usa de la siguiente manera:

l_hash := dbms_obfuscation_toolkit.md5(input_string=>:username||:password);

La longitud del hash es de 50 caracteres hexadecimales, que es de 200 bits, por lo que puede ser el hash de la contraseña con una sal, antepuesta con la sal, como:

salt | hash(salt | password)

donde | significa concatenación.

Sin embargo, solo especulaciones. Supongo que 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 algunos datos de prueba de entrada / salida para verificar!

Para su información, la contraseña 'apps_ro' se cifra como:

     <StringRefAddr addrType="password">
        <Contents>051DC8A88C574538CC4AEE32D326E9480659C06CEC271EA6D7</Contents>
     </StringRefAddr>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top