/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package org.pentaho.di.core.encryption;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.util.StringUtil;
/**
* This class handles basic encryption of passwords in Kettle. Note that it's not really encryption, it's more
* obfuscation. Passwords are <b>difficult</b> to read, not impossible.
*
* @author Matt
* @since 17-12-2003
*
*/
public class KettleTwoWayPasswordEncoder implements TwoWayPasswordEncoderInterface {
private static final int RADIX = 16;
private static final String SEED = "0933910847463829827159347601486730416058";
public KettleTwoWayPasswordEncoder() {
}
@Override
public void init() throws KettleException {
// Nothing to do here.
}
@Override
public String encode( String rawPassword ) {
return encode( rawPassword, true );
}
@Override
public String encode( String rawPassword, boolean includePrefix ) {
if ( includePrefix ) {
return encryptPasswordIfNotUsingVariables( rawPassword );
} else {
return encryptPassword( rawPassword );
}
}
@Override
public String decode( String encodedPassword ) {
if ( encodedPassword != null && encodedPassword.startsWith( PASSWORD_ENCRYPTED_PREFIX ) ) {
encodedPassword = encodedPassword.substring( PASSWORD_ENCRYPTED_PREFIX.length() );
}
return decryptPassword( encodedPassword );
}
@Override
public String decode( String encodedPassword, boolean optionallyEncrypted ) {
if ( encodedPassword == null ) {
return null;
}
if ( optionallyEncrypted ) {
if ( encodedPassword.startsWith( PASSWORD_ENCRYPTED_PREFIX ) ) {
encodedPassword = encodedPassword.substring( PASSWORD_ENCRYPTED_PREFIX.length() );
return decryptPassword( encodedPassword );
} else {
return encodedPassword;
}
} else {
return decryptPassword( encodedPassword );
}
}
public static final String encryptPassword( String password ) {
if ( password == null ) {
return "";
}
if ( password.length() == 0 ) {
return "";
}
BigInteger bi_passwd = new BigInteger( password.getBytes() );
BigInteger bi_r0 = new BigInteger( SEED );
BigInteger bi_r1 = bi_r0.xor( bi_passwd );
return bi_r1.toString( RADIX );
}
public static final String decryptPassword( String encrypted ) {
if ( encrypted == null ) {
return "";
}
if ( encrypted.length() == 0 ) {
return "";
}
BigInteger bi_confuse = new BigInteger( SEED );
try {
BigInteger bi_r1 = new BigInteger( encrypted, RADIX );
BigInteger bi_r0 = bi_r1.xor( bi_confuse );
return new String( bi_r0.toByteArray() );
} catch ( Exception e ) {
return "";
}
}
/**
* The word that is put before a password to indicate an encrypted form. If this word is not present, the password is
* considered to be NOT encrypted
*/
public static final String PASSWORD_ENCRYPTED_PREFIX = "Encrypted ";
@Override
public String[] getPrefixes() {
return new String[] { PASSWORD_ENCRYPTED_PREFIX };
}
/**
* Encrypt the password, but only if the password doesn't contain any variables.
*
* @param password
* The password to encrypt
* @return The encrypted password or the
*/
public static final String encryptPasswordIfNotUsingVariables( String password ) {
String encrPassword = "";
List<String> varList = new ArrayList<String>();
StringUtil.getUsedVariables( password, varList, true );
if ( varList.isEmpty() ) {
encrPassword = PASSWORD_ENCRYPTED_PREFIX + KettleTwoWayPasswordEncoder.encryptPassword( password );
} else {
encrPassword = password;
}
return encrPassword;
}
/**
* Decrypts a password if it contains the prefix "Encrypted "
*
* @param password
* The encrypted password
* @return The decrypted password or the original value if the password doesn't start with "Encrypted "
*/
public static final String decryptPasswordOptionallyEncrypted( String password ) {
if ( !Utils.isEmpty( password ) && password.startsWith( PASSWORD_ENCRYPTED_PREFIX ) ) {
return KettleTwoWayPasswordEncoder.decryptPassword( password.substring( PASSWORD_ENCRYPTED_PREFIX.length() ) );
}
return password;
}
}