Qualcuno sa quale tecnica di crittografia sta usando JDeveloper / SQL Developer per mantenere le credenziali?

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

Domanda

Sarei più che interessante per me capire quale tecnica viene utilizzata qui per conservare dati sensibili poiché ho bisogno di implementare una soluzione simile. Ecco una configurazione di connessione di esempio e lo snippet esportato risultante:

 Oracle SQL Developer Connections

<?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>

Qualsiasi consiglio sarebbe molto apprezzato.

È stato utile?

Soluzione

Per i curiosi, quello che stai effettivamente vedendo è la chiave segreta concatenata con la password crittografata. Ad esempio, ho provato a crittografare la password "BARCA A VELA" utilizzando:

DatabaseProviderHelper.goingOut("SAILBOAT")

In questo caso particolare, il risultato è stato:

0527C290B40C41D71139B5E7A4446E94D7678359087249A463

Il primo byte è costante:

05

I successivi 8 byte rappresentano la chiave segreta generata casualmente (per il codice DES):

27C290B40C41D711

I byte rimanenti sono la password crittografata:

39B5E7A4446E94D7678359087249A463

Pertanto, per decrittografare la password, è sufficiente utilizzare questo:

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

Altri suggerimenti

Nota che l'hash della password di Tim sopra non è per " apps_ro " - presumibilmente ha tagliato e incollato dal posto sbagliato ... Non pubblicherò la vera password nel caso sia qualcosa che non vuole condividere!

Ho avuto un problema simile, cercando di archiviare le mie credenziali db centralmente (per database non sicuri!) e quindi esportare i file XML dello sviluppatore sql. Non ho idea di cosa sia l'algoritmo, tuttavia non è necessario conoscere l'algoritmo, in quanto è possibile chiamare l'API Java Java da soli. Se hai SQLDeveloper, prendi semplicemente i file Jar giusti:

cp /Applications/SQLDeveloper.App/Contents/Resources/sqldeveloper/BC4J/lib/db-ca.jar .
cp /Applications/SQLDeveloper.App/Contents/Resources/sqldeveloper/jlib/ojmisc.jar .

Quindi caricali nella tua app Java o usa qualcosa come JRuby come faccio io:

$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" 

Nota che l'algoritmo, qualunque esso sia, ha un fattore casuale quindi la stessa password usata due volte può produrre due stringhe esadecimali diverse.

Questa soluzione funziona benissimo per me ... Copiato da: 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 soluzione fornita è troppo vecchia e funziona solo con la versione 2.x ma non ora. perché Oracle SQL Developer, ha modificato l'algoritmo di crittografia nelle versioni 3.xe 4.x.

Versione 3

Le password sono archiviate crittografate nel file connections.xml in quei percorsi:

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

Versione 4

Le password vengono archiviate crittografate nel file connections.xml sopra menzionato, ma la chiave di crittografia utilizza un valore univoco db.system.id nel file product-preferenze.xml accessibile qui:

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

Per decrittografare l'ultimo file crittografato è possibile utilizzare Mostrami password estensione per SQL Developer. Oppure decodifica il file con Decifratore password sviluppatore SQL

Lo stesso codice fornito da kornelissietsma, ma scritto su 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();
    }   
}

Può essere eseguito come segue:

# 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

Purtroppo i metodi descritti in altre risposte non funzionano in SQL Developer 4.x. C'è un'estensione che funziona su entrambe le versioni 3.xe 4.x ed è molto facile da usare:

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

Non ne sono sicuro, ma ho sempre pensato che gli hash non possano essere decifrati, solo rispetto ad un altro hash. MD5 genera un hash. La password salvata in SQL Developer deve essere decrittografata e inviata al server. Quindi le procedure DES3Encrypt e DES3Decrypt nel pacchetto dbms_obfuscation_toolkit sono una scommessa migliore. Ma il decrypt dovrebbe essere chiamato prima di connettersi a un database, quindi probabilmente è un pacchetto crittografico Java con metodi DES.

Ecco uno snippet di pitone se qualcuno è interessato. È una traduzione dell'esempio precedente di Adam Paynter . Utilizza 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:])

Non lo so, ma non sarei sorpreso se fosse DBMS_OBFUSCATION_TOOLKIT in uso qualcosa del genere:

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

La lunghezza dell'hash è di 50 caratteri esadecimali, che sono 200 bit, quindi potrebbe essere l'hash della password con un sale, anteposto con il sale, come:

salt | hash(salt | password)

dove | significa concatenazione.

Solo speculazioni però. La mia ipotesi sarebbe un sale a 40 bit e un hash SHA-1, poiché SHA-1 produce hash a 160 bit.

Sarebbe utile fornire alcuni dati di test di input / output per verificare!

Cordiali saluti la password 'apps_ro' crittografa come:

     <StringRefAddr addrType="password">
        <Contents>051DC8A88C574538CC4AEE32D326E9480659C06CEC271EA6D7</Contents>
     </StringRefAddr>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top