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

com.cybersource.flex.sdk.authentication.CGKCredentials Maven / Gradle / Ivy

There is a newer version: 0.11.1
Show newest version
/**
 * Copyright (c) 2017 by CyberSource
 */
package com.cybersource.flex.sdk.authentication;

import com.cybersource.flex.sdk.exception.FlexException;
import com.cybersource.flex.sdk.internal.SecurityHelper;
import com.cybersource.flex.sdk.repackaged.Base64;
import java.io.IOException;

import javax.security.auth.DestroyFailedException;

/**
 * Provide authentication to use FLEX API via CYBS CGK Platform.
 */
public final class CGKCredentials implements FlexCredentials {

    /**
     * Defines CGK environment
     */
    public enum Environment {
        /**
         * The production environment.
         */
        PRODUCTION,
        /**
         * The test environment.
         */
        CAS
    }

    private volatile boolean destroyed = false;
    private Environment environment;
    private String mid;
    private String keyId;
    private byte[] sharedSecret;

    /**
     * Default constructor. Please use it, when you want to call setters one by
     * one. Note that you can use fluent API in such case.
     */
    public CGKCredentials() {
    }

    /**
     * Constructor that can be used to pass all authentication information in
     * one call. Successfully invoked constructor produces object that is ready
     * for use (i.e. to create @see FlexService instance).
     *
     * @param environment environment to which credentials relate
     * @param mid merchant ID
     * @param keyId shared secret key ID used to identify credentials
     * @param sharedSecret byte array containing raw shared secret. Note that
     * the array referenced by this parameter will be overridden after it is
     * used to initialize FlexService instance.
     */
    public CGKCredentials(Environment environment, String mid, String keyId, byte[] sharedSecret) {
        this.environment = environment;
        this.mid = mid;
        this.keyId = keyId;
        setSharedSecret(sharedSecret); // field not set directly to ensure memory is overridden after use.
    }

    /**
     * Constructor that can be used to pass all authentication information in
     * one call. Successfully invoked constructor produces object that is ready
     * for use (i.e. to create @see FlexService instance).
     *
     * @param environment environment to which credentials relate
     * @param mid merchant ID
     * @param keyId shared secret key ID used to identify credentials
     * @param sharedSecret character array containing base64 encoded shared
     * secret. Note that the array referenced by this parameter will be
     * overridden after it is used to initialize FlexService instance.
     */
    public CGKCredentials(Environment environment, String mid, String keyId, char[] sharedSecret) throws FlexException {
        this.environment = environment;
        this.mid = mid;
        this.keyId = keyId;
        setSharedSecret(sharedSecret); // field not set directly to ensure memory is overridden after use.
    }

    @Override
    public String toString() {
        return String.format("CGKCredentials[env=%s, mid=%s, keyId=%s, destroyed=%b]", environment, mid, keyId, destroyed);
    }

    /**
     * Retrieves environment
     *
     * @return environment referenced by this credentials instance
     */
    public Environment getEnvironment() {
        return environment;
    }

    /**
     * Sets the environment
     *
     * @param environment
     * @return this instance to facilitate fluent API usage.
     */
    public CGKCredentials setEnvironment(Environment environment) {
        this.environment = environment;
        return this;
    }

    /**
     * Convenience method to set environment using String literal, rather than
     * enum instance.
     *
     * @param environment "CAS" or "PRODUCTION".
     * @return this instance to facilitate fluent API usage.
     */
    public CGKCredentials setEnvironment(String environment) {
        this.environment = Environment.valueOf(environment);
        return this;
    }

    /**
     * @return merchant identifier - mid
     */
    public String getMid() {
        return mid;
    }

    /**
     * @param mid
     * @return this instance to facilitate fluent API usage.
     */
    public CGKCredentials setMid(String mid) {
        this.mid = mid;
        return this;
    }

    /**
     * @return id of symmetric or asymmetric key or authentication key -
     * providing authentication to the CyberSource Gate Keeper
     */
    public String getKeyId() {
        return keyId;
    }

    /**
     * @param keyId
     * @return this instance to facilitate fluent API usage.
     */
    public CGKCredentials setKeyId(String keyId) {
        this.keyId = keyId;
        return this;
    }

    /**
     * @return CGK HMAC shared secret
     * @throws IllegalStateException If the credentials were destroyed
     */
    public byte[] getSharedSecret() {
        if (destroyed) {
            throw new IllegalStateException("Credentials were destroyed");
        }
        return sharedSecret;
    }

    /**
     * @param sharedSecret byte array containing shared secret. Note that array
     * elements can lie within the range 0x00 to 0xFF (-128 to +127). Please
     * make no assumption that shared secret byte array can be used to construct
     * valid String object.
     * @return this instance to facilitate fluent API usage.
     */
    public CGKCredentials setSharedSecret(byte[] sharedSecret) {
        try {
            this.sharedSecret = sharedSecret.clone();
            return this;
        } finally {
            SecurityHelper.randomize(sharedSecret);
        }
    }

    /**
     * @param encodedSharedSecret base64 encoded shared secret
     * @return this instance to facilitate fluent API usage.
     * @throws com.cybersource.flex.sdk.exception.FlexException
     */
    public CGKCredentials setSharedSecret(char[] encodedSharedSecret) throws FlexException {
        return setSharedSecret(decodeSharedSecret(encodedSharedSecret));
    }

    private static byte[] decodeSharedSecret(char[] encodedSharedSecret) throws FlexException {
        final byte[] sharedSecret = new byte[encodedSharedSecret.length];
        try {
            for (int i = 0; i < sharedSecret.length; i++) {
                if (encodedSharedSecret[i] > 128) {
                    throw new FlexException("non ASCII character");
                }
                sharedSecret[i] = (byte) encodedSharedSecret[i];
            }
            return Base64.decode(sharedSecret);
        } catch (IOException ioe) {
            throw new FlexException("Error during Base64 decoding");
        } finally {
            SecurityHelper.randomize(encodedSharedSecret);
            SecurityHelper.randomize(sharedSecret);
        }
    }

    @Override
    protected void finalize() throws Throwable {
        internalDestroy();
        super.finalize();
    }

    @Override
    public void destroy() throws DestroyFailedException {
        internalDestroy();
    }

    @Override
    public boolean isDestroyed() {
        return destroyed;
    }

    private void internalDestroy() {
        this.destroyed = true;

        this.environment = null;
        this.keyId = null;
        this.mid = null;
        SecurityHelper.randomize(this.sharedSecret);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy