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

java.com.ionic.sdk.agent.AgentSdk Maven / Gradle / Ivy

Go to download

The Ionic Java SDK provides an easy-to-use interface to the Ionic Platform.

There is a newer version: 2.9.0
Show newest version
package com.ionic.sdk.agent;

import com.ionic.sdk.cipher.aes.AesCipher;
import com.ionic.sdk.crypto.jce.CryptoAbstract;
import com.ionic.sdk.error.IonicException;
import com.ionic.sdk.error.SdkError;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.lang.reflect.Constructor;
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.Security;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Entry point into the Ionic SDK.
 * 

* The API {@link #initialize(Provider)} may be used to specify the {@link Provider} to use when cryptography * primitives are needed. By default, SDK 2.6+ uses the SunJCE provider built into the JRE. To use a different * cryptography provider, call the API {@link #initialize(Provider)} prior to any other usage of the Ionic SDK. *

* An implicit call to {@link #initialize(Provider)} is made upon first usage of Ionic cryptography APIs. *

* The cryptography {@link Provider} specified in the first call to {@link #initialize(Provider)} will remain in effect * for the lifetime of the hosting process. In order to enable accountability of the cryptography provider, any * subsequent calls to {@link #initialize(Provider)} will be ignored. */ public final class AgentSdk { /** * Exception which occurred on initialize call. */ private final IonicException exceptionInitialize; /** * The pass-through object that brokers access to JCE primitives. */ private final CryptoAbstract cryptoAbstract; /** * Constructor. * * @param provider the provider implementation that should be used to satisfy requests for cryptography objects */ private AgentSdk(final Provider provider) { final Logger logger = Logger.getLogger(AgentSdk.class.getName()); CryptoAbstract cryptoAbstractCtor = null; IonicException exception = null; try { // ensure that specified provider is registered in JCE if ((provider != null)) { Security.addProvider(provider); } final Provider providerUse = (provider == null) ? Security.getProvider(PROVIDER_SUNJCE) : provider; cryptoAbstractCtor = new CryptoAbstract(providerUse); checkForUnlimitedStrength(cryptoAbstractCtor); logger.log(Level.FINE, "initialize() = OK"); } catch (IonicException e) { exception = e; logger.log(Level.SEVERE, e.getMessage(), e); } this.exceptionInitialize = exception; this.cryptoAbstract = cryptoAbstractCtor; } /** * @return the pass-through object that brokers access to JCE primitives */ private CryptoAbstract getCryptoAbstract() { return cryptoAbstract; } /** * @return the {@link CryptoAbstract} singleton for the process * @throws IonicException on cryptography initialization failures */ public static CryptoAbstract getCrypto() throws IonicException { final AgentSdk agentSdk = SingletonHelper.getInstance(); // JCE-ok; internals of AgentSdk final IonicException exceptionInitialize = agentSdk.exceptionInitialize; if (exceptionInitialize == null) { return agentSdk.getCryptoAbstract(); } else { throw exceptionInitialize; } } /** * Initialize the Ionic SDK for usage. In Java, this implementation: *

    *
  1. checks the active JRE for the policy jurisdiction files needed to work with AES 256 bit keys,
  2. *
  3. adds the Bouncycastle provider (in JRE 7) so that necessary cryptography primitives are available.
  4. *
*

* https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples * * @param applicationContext the platform-specific context needed by the underlying platform * @return the per-process singleton of this object * @throws IonicException on cryptography initialization failures */ public static AgentSdk initialize(final Object applicationContext) throws IonicException { final AgentSdk agentSdk = SingletonHelper.getInstance(); // JCE-ok; internals of AgentSdk final IonicException exceptionInitialize = agentSdk.exceptionInitialize; if (exceptionInitialize == null) { return agentSdk; } else { throw exceptionInitialize; } } /** * Alternate API allowing for the specification of a particular {@link Provider}. When the Ionic SDK is * initialized using a particular provider, subsequent requests for cryptography primitives will pass the * request through to this provider. In versions of the SDK prior to 2.5, all registered providers are * used to satisfy the request. * * @param provider the provider implementation that should be used to satisfy requests for cryptography objects * @return the initialized {@link AgentSdk} object * @throws IonicException on cryptography initialization failures */ public static AgentSdk initialize(final Provider provider) throws IonicException { final AgentSdk agentSdk = SingletonHelper.initialize(provider); final IonicException exceptionInitialize = agentSdk.exceptionInitialize; if (exceptionInitialize == null) { return agentSdk; } else { throw exceptionInitialize; } } /** * Reset the state of the {@link AgentSdk} singleton. */ public static void deinitialize() { SingletonHelper.deinitialize(); } /** * Initialize the Ionic SDK for usage. In Java, this implementation: *

    *
  1. checks the active JRE for the policy jurisdiction files needed to work with AES 256 bit keys,
  2. *
  3. adds the Bouncycastle provider (in JRE 7) so that necessary cryptography primitives are available.
  4. *
*

* https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples * * @throws IonicException on cryptography initialization failures */ public static void initialize() throws IonicException { final AgentSdk agentSdk = SingletonHelper.getInstance(); // JCE-ok; internals of AgentSdk final IonicException exceptionInitialize = agentSdk.exceptionInitialize; if (exceptionInitialize != null) { throw exceptionInitialize; } } @Override public String toString() { return getClass().getName() + DELIMITER_AT + Integer.toHexString(hashCode()); } /** * Delimiter that can be used when joining strings together. */ private static final String DELIMITER_AT = "@"; /** * Helper to guard against double init. *

* http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html */ private static class SingletonHelper { /** * The per-process singleton of this object. The first fetch of this object should trigger its implicit * initialization. Subsequent fetches will return the cached value. */ private static volatile AgentSdk instance; /** * @return the per-process singleton of this object */ private static AgentSdk getInstance() { // JCE-ok; internals of AgentSdk if (instance == null) { synchronized (SingletonHelper.class) { if (instance == null) { instance = new AgentSdk(null); } } } return instance; } /** * Alternate API allowing for the specification of a particular {@link Provider}. When the Ionic SDK is * initialized using a particular provider, subsequent requests for cryptography primitives will pass the * request through to this provider. In versions of the SDK prior to 2.5, all registered providers are * used to satisfy the request. * * @param provider the provider implementation that should be used to satisfy requests for cryptography objects * @return the initialized {@link AgentSdk} object */ private static AgentSdk initialize(final Provider provider) { if (instance == null) { synchronized (SingletonHelper.class) { if (instance == null) { instance = new AgentSdk(provider); } } } return instance; } /** * Reset the state of the {@link AgentSdk} singleton. */ private static void deinitialize() { instance = null; } } /** * Attempt to instantiate a 256-bit AES key, and a cipher initialized with that key. If the "JCE Unlimited * Strength Jurisdiction Policy Files" are not installed in the active JRE, this operation will fail. *

* Instructions to upgrade a JRE: https://support.ca.com/us/knowledge-base-articles.tec1698523.html *

* Download binary from: http://www.oracle.com/technetwork/java/javase/downloads/index.html *

* Search page for: "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" * * @param cryptoAbstract the pass-through object that brokers access to JCE primitives * @throws IonicException if the javax.crypto.Cipher object cannot be initialized */ private static void checkForUnlimitedStrength(final CryptoAbstract cryptoAbstract) throws IonicException { try { final byte[] bytes = new byte[AesCipher.KEY_BITS / Byte.SIZE]; Arrays.fill(bytes, (byte) 0); final SecretKeySpec secretKeySpec = new SecretKeySpec(bytes, AesCipher.ALGORITHM); final Cipher cipher = Cipher.getInstance(AesCipher.TRANSFORM_CTR); // JCE-ok (maven-shade workaround) cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); } catch (GeneralSecurityException e) { throw new IonicException(SdkError.ISAGENT_INIT_FAILED_KEY_SIZE, e); } } /** * Using reflection, add BouncyCastle provider to provider list. * * @return the provider implementation that should be used to satisfy requests for cryptography objects * @throws IonicException if BouncyCastle provider is not in classpath or available */ private static Provider createProviderBouncyCastle() throws IonicException { final String className = CLASSNAME_BC_PROVIDER; try { final Class c = Class.forName(className); final Constructor ctor = c.getConstructor(); final Object object = ctor.newInstance(); if (object instanceof Provider) { Security.addProvider((Provider) object); return (Provider) object; } else { throw new IonicException(SdkError.ISCRYPTO_ERROR, new GeneralSecurityException(className)); } } catch (ReflectiveOperationException e) { throw new IonicException(SdkError.ISAGENT_RESOURCE_NOT_FOUND, e); } } /** * Provider name for built-in JCE implementation. */ private static final String PROVIDER_SUNJCE = "SunJCE"; /** * Class name for BouncyCastle Security Provider. When running in JRE less than or equal 7, BouncyCastle provides * implementation of AES/GCM transform (needed for communications with ionic.com). */ private static final String CLASSNAME_BC_PROVIDER = "org.bouncycastle.jce.provider.BouncyCastleProvider"; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy