All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.org.jets3t.service.security.AWSCredentials Maven / Gradle / Ivy

/*
 * jets3t : Java Extra-Tasty S3 Toolkit (for Amazon S3 online storage service)
 * This is a java.net project, see https://jets3t.dev.java.net/
 * 
 * Copyright 2006 James Murty
 * 
 * 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.jets3t.service.security;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Serializable;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jets3t.service.Constants;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.utils.ServiceUtils;

/**
 * Class to contain the Amazon Web Services (AWS) credentials of a user. This class also includes
 * utility methods to store credentials to password-encrypted files, and retrieve credentials from
 * these files.
 * 
 * @author James Murty
 */
public class AWSCredentials implements Serializable {
    private static final long serialVersionUID = -9198887548912640773L;

    private static final Log log = LogFactory.getLog(AWSCredentials.class);    
    
    protected static final String KEYS_DELIMITER = "AWSKEYS";
    protected static final String VERSION_PREFIX = "jets3t AWS Credentials, version: ";

    private String awsAccessKey = null;
    private String awsSecretAccessKey = null;
    private String friendlyName = null;

    /**
     * Construct credentials.
     * 
     * @param awsAccessKey
     * AWS access key for an Amazon S3 account.
     * @param awsSecretAccessKey
     * AWS secret key for an Amazon S3 acount.
     */
    public AWSCredentials(String awsAccessKey, String awsSecretAccessKey) {
        this.awsAccessKey = awsAccessKey;
        this.awsSecretAccessKey = awsSecretAccessKey;
    }

    /**
     * Construct credentials, and associate them with a human-friendly name.
     * 
     * @param awsAccessKey
     * AWS access key for an Amazon S3 account.
     * @param awsSecretAccessKey
     * AWS secret key for an Amazon S3 acount.
     * @param friendlyName
     * a name identifying the owner of the credentials, such as 'James'.
     */
    public AWSCredentials(String awsAccessKey, String awsSecretAccessKey, String friendlyName) {
        this(awsAccessKey, awsSecretAccessKey);
        this.friendlyName = friendlyName;
    }

    /**
     * @return
     * the AWS Access Key.
     */
    public String getAccessKey() {
        return awsAccessKey;
    }

    /**
     * @return
     * the AWS Secret Key.
     */
    public String getSecretKey() {
        return awsSecretAccessKey;
    }

    /**
     * @return
     * the friendly name associated with an AWS account, if available. 
     */
    public String getFriendlyName() {
        return friendlyName;
    }
    
    /**
     * Encrypts AWS Credentials with the given password and saves the encrypted data to a file.
     * 
     * @param password
     * the password used to encrypt the credentials.
     * @param file
     * the file to write the encrypted credentials data to.
     * 
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeySpecException
     * @throws IllegalStateException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     * @throws InvalidAlgorithmParameterException
     * @throws IOException
     */
    public void save(String password, File file) throws InvalidKeyException,
        NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException,
        IllegalStateException, IllegalBlockSizeException, BadPaddingException,
        InvalidAlgorithmParameterException, IOException
    {
        FileOutputStream fos = new FileOutputStream(file);
        save(password, fos);
        fos.close();
    }
    
    /**
     * Encrypts AWS Credentials with the given password and writes the encrypted data to an
     * output stream.
     * 
     * @param password
     * the password used to encrypt the credentials.
     * @param outputStream
     * the output stream to write the encrypted credentials data to, this stream must be closed by
     * the caller.
     * 
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeySpecException
     * @throws IllegalStateException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     * @throws InvalidAlgorithmParameterException
     * @throws IOException
     */
    public void save(String password, OutputStream outputStream) throws InvalidKeyException,
        NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException,
        IllegalStateException, IllegalBlockSizeException, BadPaddingException,
        InvalidAlgorithmParameterException, IOException
    {
        BufferedOutputStream bufferedOS = null;
        EncryptionUtil encryptionUtil = new EncryptionUtil(password);
        bufferedOS = new BufferedOutputStream(outputStream);

        // Encrypt AWS credentials
        String dataToEncrypt = getAccessKey() + KEYS_DELIMITER + getSecretKey();
        byte[] encryptedData = encryptionUtil.encrypt(dataToEncrypt);
        
        // Write plain-text header information to file.
        bufferedOS.write((VERSION_PREFIX + EncryptionUtil.DEFAULT_VERSION + "\n").getBytes(Constants.DEFAULT_ENCODING));
        bufferedOS.write((encryptionUtil.getAlgorithm() + "\n").getBytes(Constants.DEFAULT_ENCODING));
        bufferedOS.write(((friendlyName == null? "" : friendlyName) + "\n").getBytes(Constants.DEFAULT_ENCODING));
        
        bufferedOS.write(encryptedData);
        bufferedOS.flush();
    }

    /**
     * Loads encrypted credentials from a file.
     * 
     * @param password
     * the password used to decrypt the credentials. If null, the AWS Credentials are not decrypted
     * and only the version and friendly-name information is loaded.
     * @param file
     * a file containing an encrypted data encoding of an AWSCredentials object.
     * @return 
     * the decrypted credentials in an object.
     * 
     * @throws S3ServiceException
     */
    public static AWSCredentials load(String password, File file) throws S3ServiceException {
    	if (log.isDebugEnabled()) {
    		log.debug("Loading credentials from file: " + file.getAbsolutePath());
    	}
        BufferedInputStream fileIS = null;
        try {
            fileIS = new BufferedInputStream(new FileInputStream(file));
            return load(password, fileIS);
        } catch (Throwable t) {
            throw new S3ServiceException("Failed to load AWS credentials", t);
        } finally {
            if (fileIS != null) {
                try {
                    fileIS.close();
                } catch (IOException e) {
                }
            }
        }
    }
    
    /**
     * Loads encrypted credentials from a data input stream.
     * 
     * @param password
     * the password used to decrypt the credentials. If null, the AWS Credentials are not decrypted
     * and only the version and friendly-name information is loaded.
     * @param inputStream
     * an input stream containing an encrypted  data encoding of an AWSCredentials object.
     * @return 
     * the decrypted credentials in an object.
     * 
     * @throws S3ServiceException
     */
    public static AWSCredentials load(String password, BufferedInputStream inputStream) throws S3ServiceException {
        boolean partialReadOnly = (password == null);
        if (partialReadOnly) {
        	if (log.isDebugEnabled()) {
        		log.debug("Loading partial information about AWS Credentials from input stream");
        	}
        } else {
        	if (log.isDebugEnabled()) {
        		log.debug("Loading AWS Credentials from input stream");
        	}
        }
        
        try {
            EncryptionUtil encryptionUtil = null; 
            byte[] encryptedKeys = new byte[2048];
            int encryptedDataIndex = 0;
            
            String version = null;
            String algorithm = null;
            String friendlyName = null;
            
            // Read version information from AWS credentials file.
            version = ServiceUtils.readInputStreamLineToString(inputStream, Constants.DEFAULT_ENCODING);
            
            if (!version.startsWith(VERSION_PREFIX)) {
                // Either this is not a valid AWS Credentials file, or it's an obsolete version.
                // Try decrypting using the obsolete approach.
                friendlyName = version;
                
                if (!partialReadOnly) {
                    encryptionUtil = EncryptionUtil.getObsoleteEncryptionUtil(password);
                }
            } else {
                // Read algorithm and friendly name from file.
                algorithm = ServiceUtils.readInputStreamLineToString(inputStream, Constants.DEFAULT_ENCODING);
                friendlyName = ServiceUtils.readInputStreamLineToString(inputStream, Constants.DEFAULT_ENCODING);    
                
                if (!partialReadOnly) {
                    encryptionUtil = new EncryptionUtil(password, algorithm, EncryptionUtil.DEFAULT_VERSION);
                }
            }
            
            if (partialReadOnly) {
                return new AWSCredentials(null, null, friendlyName);                
            }            
            
            // Read encrypted data bytes from file.
            encryptedDataIndex = inputStream.read(encryptedKeys);
            
            // Decrypt data.
            String keys = encryptionUtil.decryptString(encryptedKeys, 0, encryptedDataIndex);

            int delimOffset = keys.indexOf(KEYS_DELIMITER);
            if (delimOffset < 0) {
                throw new Exception("Unable to load AWS keys. Is the password correct?");
            }

            AWSCredentials awsCredentials = new AWSCredentials(keys.substring(0, delimOffset), keys
                .substring(delimOffset + KEYS_DELIMITER.length()), friendlyName);
            
            return awsCredentials;
        } catch (BadPaddingException bpe) {
            throw new S3ServiceException("Unable to decrypt AWS credentials. Is your password correct?", bpe);
        } catch (Throwable t) {
            throw new S3ServiceException("Failed to load AWS credentials", t);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     * Console utility to store AWS credentials information in an encrypted file in the toolkit's
     * default preferences directory.
     * 

* This class can be run from the command line as: *

     * java org.jets3t.service.security.AWSCredentials <friendlyName> <credentialsFilename>
     * 
* When run it will prompt for the user's AWS access key,secret key and encryption password. * It will then encode into the specified credentials file. * * @param args */ public static void main(String[] args) throws Exception { if (args.length != 2) { printHelp(); System.exit(1); } String userName = args[0]; File encryptedFile = new File(args[1]); // Check arguments provided. try { FileOutputStream testFOS = new FileOutputStream(encryptedFile); testFOS.close(); } catch (IOException e) { System.err.println("Unable to write to file: " + encryptedFile); } BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); // Obtain credentials and password from user. System.out.println("Please enter your AWS Credentials"); System.out.print("Access Key: "); String awsAccessKey = reader.readLine(); System.out.print("Secret Key: "); String awsSecretKey = reader.readLine(); System.out .println("Please enter a password to protect your credentials file (may be empty)"); System.out.print("Password: "); String password = reader.readLine(); // Create AWSCredentials object and save the details to an encrypted file. AWSCredentials awsCredentials = new AWSCredentials(awsAccessKey, awsSecretKey, userName); awsCredentials.save(password, encryptedFile); System.out.println("Successfully saved AWS Credentials to " + encryptedFile); } /** * Prints help for the use of this class from the console (via the main method). */ private static void printHelp() { System.out.println("AWSCredentials "); System.out.println(); System.out .println("User Name: A human-friendly name for the owner of the credentials, e.g. Horace."); System.out .println("File Path: Path and name for the encrypted file. Will be replaced if it already exists."); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy