/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2017 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 org.eclipse.jetty.util.security.Password;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.KettleClientEnvironment;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.plugins.PluginInterface;
import org.pentaho.di.core.plugins.PluginRegistry;
/**
* 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 Encr {
private static TwoWayPasswordEncoderInterface encoder;
public Encr() {
}
@Deprecated
public boolean init() {
return true;
}
public static void init( String encoderPluginId ) throws KettleException {
if ( Utils.isEmpty( encoderPluginId ) ) {
throw new KettleException( "Unable to initialize the two way password encoder: No encoder plugin type specified." );
}
PluginRegistry registry = PluginRegistry.getInstance();
PluginInterface plugin = registry.findPluginWithId( TwoWayPasswordEncoderPluginType.class, encoderPluginId );
if ( plugin == null ) {
throw new KettleException( "Unable to find plugin with ID '" + encoderPluginId + "'" );
}
encoder = (TwoWayPasswordEncoderInterface) registry.loadClass( plugin );
// Load encoder specific options...
//
encoder.init();
}
private static final int RADIX = 16;
private static final String SEED = "0933910847463829827159347601486730416058";
/**
* Old Kettle 1.x code which built a signature to validate a license key against.
*
* @param mac
* @param username
* @param company
* @param products
* @return
* @deprecated
*/
@Deprecated
public String buildSignature( String mac, String username, String company, String products ) {
try {
BigInteger bi_mac = new BigInteger( mac.getBytes() );
BigInteger bi_username = new BigInteger( username.getBytes() );
BigInteger bi_company = new BigInteger( company.getBytes() );
BigInteger bi_products = new BigInteger( products.getBytes() );
BigInteger bi_r0 = new BigInteger( SEED );
BigInteger bi_r1 = bi_r0.xor( bi_mac );
BigInteger bi_r2 = bi_r1.xor( bi_username );
BigInteger bi_r3 = bi_r2.xor( bi_company );
BigInteger bi_r4 = bi_r3.xor( bi_products );
return bi_r4.toString( RADIX );
} catch ( Exception e ) {
return null;
}
}
/**
* Old signature code, used in license keys, from the Kettle 1.x days.
* @param signature
* @param verify
* @return
* @deprecated
*/
@Deprecated
public static final boolean checkSignatureShort( String signature, String verify ) {
return getSignatureShort( signature ).equalsIgnoreCase( verify );
}
/**
* Old Kettle 1.x code used to get a short signature from a long version signature for license checking.
* @param signature
* @return
* @deprecated
*/
@Deprecated
public static final String getSignatureShort( String signature ) {
String retval = "";
if ( signature == null ) {
return retval;
}
int len = signature.length();
if ( len < 6 ) {
return retval;
}
retval = signature.substring( len - 5, len );
return retval;
}
public static final String encryptPassword( String password ) {
return encoder.encode( password, false );
}
public static final String decryptPassword( String encrypted ) {
return encoder.decode( encrypted );
}
/**
* 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 ";
/**
* 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 ) {
return encoder.encode( password, true );
}
/**
* 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 ) {
return encoder.decode( password, true );
}
/**
* Create an encrypted password
*
* @param args
* the password to encrypt
*/
public static void main( String[] args ) throws KettleException {
KettleClientEnvironment.init();
if ( args.length != 2 ) {
printOptions();
System.exit( 9 );
}
String option = args[0];
String password = args[1];
if ( Const.trim( option ).substring( 1 ).equalsIgnoreCase( "kettle" ) ) {
// Kettle password obfuscation
//
try {
String obfuscated = Encr.encryptPasswordIfNotUsingVariables( password );
System.out.println( obfuscated );
System.exit( 0 );
} catch ( Exception ex ) {
System.err.println( "Error encrypting password" );
ex.printStackTrace();
System.exit( 2 );
}
} else if ( Const.trim( option ).substring( 1 ).equalsIgnoreCase( "carte" ) ) {
// Jetty password obfuscation
//
String obfuscated = Password.obfuscate( password );
System.out.println( obfuscated );
System.exit( 0 );
} else {
// Unknown option, print usage
//
System.err.println( "Unknown option '" + option + "'\n" );
printOptions();
System.exit( 1 );
}
}
private static void printOptions() {
System.err.println( "encr usage:\n" );
System.err.println( " encr <-kettle|-carte> <password>" );
System.err.println( " Options:" );
System.err.println( " -kettle: generate an obfuscated password to include in Kettle XML files" );
System.err.println( " -carte : generate an obfuscated password to include in the carte password file 'pwd/kettle.pwd'" );
System.err.println( "\nThis command line tool obfuscates a plain text password for use in XML and password files." );
System.err.println( "Make sure to also copy the '" + PASSWORD_ENCRYPTED_PREFIX + "' prefix to indicate the obfuscated nature of the password." );
System.err.println( "Kettle will then be able to make the distinction between regular plain text passwords and obfuscated ones." );
System.err.println();
}
}