Does anybody know what encrypting technique is JDeveloper/SQL Developer using to persist credentials?

后端 未结 11 2099
广开言路
广开言路 2020-12-22 18:46

I\'d be more than interesting for me to understand which technique is being used here to persist sensible data since I\'m needing to implement a similar solution. Here\'s a

相关标签:
11条回答
  • 2020-12-22 19:21

    I'm not sure about this but I always thought hashes can't be decrypted, only compared to another hash. MD5 generates a hash. The saved password in SQL Developer needs to be decrypted and send to the server. So the DES3Encrypt and DES3Decrypt procedures in dbms_obfuscation_toolkit package are a better bet. But the decrypt should be called before connecting to a database, so it's probably a Java crypto package with DES methods.

    0 讨论(0)
  • 2020-12-22 19:25

    Here's a python snippet if anyone is intersted. It's a translation of Adam Paynter's example above. It uses 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:])
    
    0 讨论(0)
  • 2020-12-22 19:28

    Note that Tim's password hash above is not for "apps_ro" - presumably he cut and pasted from the wrong place... I won't post the real password in case it's something he doesn't want shared!

    I had a similar problem, trying to store my db credentials centrally (for non-secure databases!) and then exporting sql developer xml files. I have no idea what the algorithm is - however, you don't really need to know the algorithm, as you can just call the Oracle java API yourself. If you have SQLDeveloper, just grab the right Jar files:

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

    Then either load them in your Java app, or use something like JRuby as I do:

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

    Note that the algorithm, whatever it is, has a random factor so the same password used twice can produce two different hex strings.

    0 讨论(0)
  • 2020-12-22 19:31

    For the curious, what you're actually seeing is the secret key concatenated with the encrypted password. For example, I tried encrypting the password "SAILBOAT" using:

    DatabaseProviderHelper.goingOut("SAILBOAT")
    

    In this particular instance, the result was:

    0527C290B40C41D71139B5E7A4446E94D7678359087249A463
    

    The first byte is constant:

    05
    

    The next 8 bytes represent the randomly generated secret key (for the DES cipher):

    27C290B40C41D711
    

    The remaining bytes are the encrypted password:

    39B5E7A4446E94D7678359087249A463
    

    Therefore, to decrypt the password, you simply use this:

    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);
    }
    
    0 讨论(0)
  • 2020-12-22 19:37

    The length of the hash is 50 hex characters, which is 200 bits, so it may be the the hash of the password with a salt, prepended with the salt, like:

    salt | hash(salt | password)
    

    where | means concatenation.

    Just speculation though. My guess would be a 40-bit salt and a SHA-1 hash, since SHA-1 produces 160-bit hashes.

    Would be helpful to provide some input/output test data to check against!

    0 讨论(0)
  • 2020-12-22 19:39

    The same code as kornelissietsma has given, but written on 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();
        }   
    }
    

    Can be executed as following:

    # 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
    
    0 讨论(0)
提交回复
热议问题