Showing posts with label encryption. Show all posts
Showing posts with label encryption. Show all posts

Tuesday, April 9, 2013

Encoding and decoding in Java (encryption) and WLST

Faced with the need to encrypt passwords in a DB, I google and find this article, but then I realize it's not recommended (why?) to use sun.misc.BASE64Decoder, I should rather use Apache commons:

commons-codec-1.4.jar (in reality the latest release is not 1.4, but I don't care)

maven is:
<dependency>
 <groupId>commons-codec</groupId>
 <artifactId>commons-codec</artifactId>
 <version>1.4</version>
</dependency>
So I change implementation and I get this wonderful code:

package com.acme.osb.encryption;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import org.apache.commons.codec.binary.Base64;


public class PasswordEncoder {

    private static final char[] PASSWORD = "enfldsgbnlsngdlksdsgm".toCharArray();
    private static final byte[] SALT = {
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
    };

    public static void main(String[] args) throws Exception {
        String originalPassword = "secret";
        System.out.println("Original password: " + originalPassword);
        String encryptedPassword = encrypt(originalPassword, PASSWORD);
        System.out.println("Encrypted password: " + encryptedPassword);
        String decryptedPassword = decrypt(encryptedPassword, PASSWORD);
        System.out.println("Decrypted password: " + decryptedPassword);
    }

    private static String encrypt(String property, char[] pw) throws GeneralSecurityException, UnsupportedEncodingException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(pw));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
        return base64Encode(pbeCipher.doFinal(property.getBytes("UTF-8")));
    }

    private static String base64Encode(byte[] bytes) {
        return Base64.encodeBase64String(bytes);
    }

    private static String decrypt(String property, char[] pw) throws GeneralSecurityException, IOException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(pw));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
        return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
    }

    private static byte[] base64Decode(String property) throws IOException {
        return Base64.decodeBase64(property);
    }

}




In WebLogic there is a simple way of encrypting/decrypting passwords, but for fear of depending from the SerializedSystemIni.dat file I am afraid of using it.
Here the official documentation.
Anyway just run . ./setDomainEnv.sh and then "java weblogic.security.Encrypt mypwtoencrypt". To decrypt, since WebLogic doesn't provide a "weblogic.security.Decrypt" utility, follow these steps

In WLST, to decode you can do the following:


from javax.crypto import Cipher
from javax.crypto import SecretKey
from javax.crypto import SecretKeyFactory
from javax.crypto.spec import PBEKeySpec
from javax.crypto.spec import PBEParameterSpec

from org.apache.commons.codec.binary import Base64


def decode(encodedPassword):
    SALT='\xde\x33\x10\x12\xde\x33\x10\x12'
    key='yoursecretkeyhere'
    keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES")
    key = keyFactory.generateSecret(PBEKeySpec(key))
    pbeCipher = Cipher.getInstance("PBEWithMD5AndDES")
    
    pbeCipher.init(Cipher.DECRYPT_MODE, key, PBEParameterSpec(SALT, 20))
    
    resultb=pbeCipher.doFinal(Base64.decodeBase64(encodedPassword))
    
    print String(resultb, "utf-8")







Thursday, August 23, 2012

WebLogic: using encrypted passwords

useful post here

These are the commands to encrypt the password "weblogic1" :

cd /opt/oracle/domains/osbpl1do
. ./bin/setDomainEnv.sh
java weblogic.security.Encrypt weblogic1

result is:
{AES}B5eEjwtHcq7eg3xyq7m5u3ZHcW8/QvENN8DlxrnXixo=

Same thing if you do
java weblogic.WLST
print encrypt('weblogic1')

The funny thing is that each time you get a different value.

WebLogic doesn't let you connect with an encrypted password:

THIS WILL NOT WORK:
connect('weblogic', '{AES}B5eEjwtHcq7eg3xyq7m5u3ZHcW8/QvENN8DlxrnXixo=', 't3://localhost:7001')




For JDBC passwords, WebLogic will store them in the $DOMAIN_HOME/config/jdbc/DATASOURCENAME-nnnn-jdbc.xml file in encrypted format.

<?xml version='1.0' encoding='UTF-8'?>
<jdbc-data-source xmlns="http://xmlns.oracle.com/weblogic/jdbc-data-source" xmlns:sec="http://xmlns.oracle.com/weblogic/security" xmlns:wls="http://xmlns.oracle.com/weblogic/security/wls" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/jdbc-data-source http://xmlns.oracle.com/weblogic/jdbc-data-source/1.0/jdbc-data-source.xsd">
  <name>SOADataSource</name>
  <jdbc-driver-params>
    <url>jdbc:oracle:thin:@acme.com:1551:dosb01</url>
    <driver-name>oracle.jdbc.OracleDriver</driver-name>
    <properties>
      <property>
        <name>user</name>
        <value>pl1_soainfra</value>
      </property>
    </properties>
    <password-encrypted>{AES}hJ3eMa5bAzP8Oq1LbGMN+ZsUAWDCErZYuiBTfi2S2vg=</password-encrypted>
  </jdbc-driver-params>
  <jdbc-connection-pool-params>
    <test-table-name>SQL SELECT 1  FROM DUAL</test-table-name>
  </jdbc-connection-pool-params>
  <jdbc-data-source-params>
    <jndi-name>jdbc/SOALocalTxDataSource</jndi-name>
  </jdbc-data-source-params>
</jdbc-data-source>



This post shows how to create a DataSource with encrypted password. You can user either

drBean = jdbcResource.getJDBCDriverParams()
drBean.setPassword("{3DES}IQHx+vYPxQI5k1W1Dbwubw==")

or

drBean = jdbcResource.getJDBCDriverParams()
drBean.setPassword("cleartextpw")

and it works the same way.

If you encrypt the password on one domain and use it for a DataSource in another domain you will get this error:


weblogic.application.WrappedDeploymentException: Could not perform unpadding: invalid pad byte.
at com.rsa.jsafe.c.a(Unknown Source)
at com.rsa.jsafe.JSAFE_SymmetricCipher.decryptFinal(Unknown Source)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptBytes(JSafeEncryptionServiceImpl.java:124)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptString(JSafeEncryptionServiceImpl.java:184)
at weblogic.security.internal.encryption.ClearOrEncryptedService.decrypt(ClearOrEncryptedService.java:96)
at sun.reflect.GeneratedMethodAccessor95.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at weblogic.descriptor.DescriptorManager$SecurityServiceImpl$SecurityProxy._invokeServiceMethod(DescriptorManager.java:173)
at weblogic.descriptor.DescriptorManager$SecurityServiceImpl$SecurityProxy.decrypt(DescriptorManager.java:192)
at weblogic.descriptor.DescriptorManager$SecurityServiceImpl.decrypt(DescriptorManager.java:114)
at weblogic.descriptor.internal.AbstractDescriptorBean._decrypt(AbstractDescriptorBean.java:1092)
at weblogic.j2ee.descriptor.wl.JDBCDriverParamsBeanImpl.getPassword(JDBCDriverParamsBeanImpl.java:337)
at weblogic.jdbc.common.internal.DataSourceConnectionPoolConfig.getDriverProperties(DataSourceConnectionPoolConfig.java:355)
at weblogic.jdbc.common.internal.DataSourceConnectionPoolConfig$2.run(DataSourceConnectionPoolConfig.java:291)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:146)
at weblogic.jdbc.common.internal.DataSourceConnectionPoolConfig.initJDBCParameters(DataSourceConnectionPoolConfig.java:287)
at weblogic.jdbc.common.internal.DataSourceConnectionPoolConfig.access$000(DataSourceConnectionPoolConfig.java:24)
at weblogic.jdbc.common.internal.DataSourceConnectionPoolConfig$1.run(DataSourceConnectionPoolConfig.java:78)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:146)
at weblogic.jdbc.common.internal.DataSourceConnectionPoolConfig.getPoolProperties(DataSourceConnectionPoolConfig.java:75)
at weblogic.jdbc.common.internal.ConnectionPool.doStart(ConnectionPool.java:1154)
at weblogic.jdbc.common.internal.ConnectionPool.start(ConnectionPool.java:154)
at weblogic.jdbc.common.internal.ConnectionPoolManager.createAndStartPool(ConnectionPoolManager.java:454)
at weblogic.jdbc.common.internal.ConnectionPoolManager.createAndStartPool(ConnectionPoolManager.java:372)
at weblogic.jdbc.module.JDBCModule.prepare(JDBCModule.java:255)
at weblogic.application.internal.flow.ModuleListenerInvoker.prepare(ModuleListenerInvoker.java:199)
at weblogic.application.internal.flow.DeploymentCallbackFlow$1.next(DeploymentCallbackFlow.java:517)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:52)
at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:159)
at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:45)
at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:613)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:52)
at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:184)
at weblogic.application.internal.SingleModuleDeployment.prepare(SingleModuleDeployment.java:43)
at weblogic.application.internal.DeploymentStateChecker.prepare(DeploymentStateChecker.java:154)
at weblogic.deploy.internal.targetserver.AppContainerInvoker.prepare(AppContainerInvoker.java:60)
at weblogic.deploy.internal.targetserver.operations.ActivateOperation.createAndPrepareContainer(ActivateOperation.java:207)
at weblogic.deploy.internal.targetserver.operations.ActivateOperation.doPrepare(ActivateOperation.java:98)
at weblogic.deploy.internal.targetserver.operations.AbstractOperation.prepare(AbstractOperation.java:217)
at weblogic.deploy.internal.targetserver.DeploymentManager.handleDeploymentPrepare(DeploymentManager.java:747)
at weblogic.deploy.internal.targetserver.DeploymentManager.prepareDeploymentList(DeploymentManager.java:1216)
at weblogic.deploy.internal.targetserver.DeploymentManager.handlePrepare(DeploymentManager.java:218)
at weblogic.deploy.internal.targetserver.DeploymentServiceDispatcher.prepare(DeploymentServiceDispatcher.java:159)
at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.doPrepareCallback(DeploymentReceiverCallbackDeliverer.java:171)
at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.prepare(DeploymentReceiverCallbackDeliverer.java:41)
at weblogic.deploy.service.internal.statemachines.targetserver.AwaitingContextUpdateCompletion.callDeploymentReceivers(AwaitingContextUpdateCompletion.java:164)
at weblogic.deploy.service.internal.statemachines.targetserver.AwaitingContextUpdateCompletion.handleContextUpdateSuccess(AwaitingContextUpdateCompletion.java:66)
at weblogic.deploy.service.internal.statemachines.targetserver.AwaitingContextUpdateCompletion.contextUpdated(AwaitingContextUpdateCompletion.java:32)
at weblogic.deploy.service.internal.targetserver.TargetDeploymentService.notifyContextUpdated(TargetDeploymentService.java:225)
at weblogic.deploy.service.internal.DeploymentService$1.run(DeploymentService.java:189)
at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:528)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)