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

java.com.ionic.sdk.agent.cipher.batch.BatchCipherV2 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.cipher.batch;

import com.ionic.sdk.agent.cipher.batch.data.CipherTextItem;
import com.ionic.sdk.agent.cipher.batch.data.PlainTextItem;
import com.ionic.sdk.agent.cipher.batch.spec.BatchGcmParameterSpec;
import com.ionic.sdk.agent.cipher.data.DecryptAttributes;
import com.ionic.sdk.agent.cipher.data.EncryptAttributes;
import com.ionic.sdk.agent.key.KeyAttributesMap;
import com.ionic.sdk.agent.request.createkey.CreateKeysResponse;
import com.ionic.sdk.agent.request.getkey.GetKeysResponse;
import com.ionic.sdk.agent.request.updatekey.UpdateKeysRequest;
import com.ionic.sdk.agent.request.updatekey.UpdateKeysResponse;
import com.ionic.sdk.cipher.aes.AesCipher;
import com.ionic.sdk.cipher.aes.AesGcmCipher;
import com.ionic.sdk.core.codec.Transcoder;
import com.ionic.sdk.error.IonicException;
import com.ionic.sdk.error.SdkData;
import com.ionic.sdk.error.SdkError;
import com.ionic.sdk.key.KeyServices;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Ionic Machina Tools batch crypto implementation, version 2.  This wrapper object is intended to perform
 * cryptography operations on a discrete set of related data values.  It is intended for use in applications where
 * storage space for the resulting data is constrained.
 * 

* The underlying cryptography leverages {@link AesGcmCipher}. *

* The storage requirement for the encrypted form of the data value set is equal to that of the original data, plus * that of the associated key id (eleven printable ASCII characters). The initialization vectors used for the * ciphertexts are derived using RNG, and stored in the {@link KeyAttributesMap} of the key. The GCM authentication * tags of the ciphertexts are stored in the mutable {@link KeyAttributesMap} of the key. *

* The {@link com.ionic.sdk.agent.cipher.batch.data.PlainTextItem} values provided in a call to * {@link #encrypt(EncryptAttributes, List)} must match (count and order) the * {@link com.ionic.sdk.agent.cipher.batch.data.CipherTextItem} values provided in a subsequent call to * {@link #decrypt(String, DecryptAttributes, List)}. Otherwise, the decryption operation will fail. */ public final class BatchCipherV2 extends BatchCipherAbstract { /** * Constructor. * * @param keyServices the key services implementation; used to broker key transactions and crypto operations */ public BatchCipherV2(final KeyServices keyServices) { super(keyServices); } @Override public List encrypt(final EncryptAttributes encryptAttributes, final List items) throws IonicException { final ArrayList cipherTextResults = new ArrayList(); // fabricate batch IV final KeyAttributesMap keyAttributes = encryptAttributes.getKeyAttributes(); final BatchGcmParameterSpec batchParameterSpec = new BatchGcmParameterSpec(items.size()); keyAttributes.put(IONIC_IVS, Collections.singletonList(batchParameterSpec.getIvData())); // storage for batch ATAGs final ByteArrayOutputStream bos = new ByteArrayOutputStream(items.size() * AesCipher.SIZE_ATAG); // create key final KeyServices keyServices = getKeyServices(); final CreateKeysResponse createKeysResponse = keyServices.createKey( keyAttributes, encryptAttributes.getMetadata()); final CreateKeysResponse.Key createKey = createKeysResponse.getFirstKey(); encryptAttributes.setKeyResponse(createKey); // iterate through plaintexts final AesGcmCipher cipher = new AesGcmCipher(createKey.getSecretKey()); cipher.setAuthData(Transcoder.utf8().decode(createKey.getId())); for (PlainTextItem item : items) { final byte[] plainText = item.getData(); final byte[] cipherText = new byte[plainText.length + AesCipher.SIZE_ATAG]; final ByteBuffer plainBuffer = ByteBuffer.wrap(plainText); final ByteBuffer cipherBuffer = ByteBuffer.wrap(cipherText); final int count = cipher.encrypt(plainBuffer, cipherBuffer, batchParameterSpec.next()); SdkData.checkTrue(cipherText.length == count, SdkError.ISAGENT_ERROR); cipherTextResults.add(new CipherTextItem(Arrays.copyOfRange(cipherText, 0, plainText.length))); bos.write(cipherText, plainText.length, AesCipher.SIZE_ATAG); } // store GCM ATAGs of batch as a mutable attribute of Machina key final UpdateKeysRequest updateKeysRequest = new UpdateKeysRequest(); final UpdateKeysRequest.Key updateKey = new UpdateKeysRequest.Key(createKey, false); final KeyAttributesMap mutableAttributes = updateKey.getMutableAttributesMap(); mutableAttributes.put(IONIC_ATAGS, Collections.singletonList(Transcoder.base64().encode(bos.toByteArray()))); updateKeysRequest.addKey(updateKey); // carry out update transaction final UpdateKeysResponse updateKeysResponse = keyServices.updateKeys(updateKeysRequest); SdkData.checkTrue(updateKeysResponse.getErrors().isEmpty(), SdkError.ISAGENT_REQUESTFAILED); return cipherTextResults; } @Override public List decrypt(final String keyId, final DecryptAttributes decryptAttributes, final List items) throws IonicException { final ArrayList plainTextResults = new ArrayList(); // fetch key final KeyServices keyServices = getKeyServices(); final GetKeysResponse getKeysResponse = keyServices.getKey(keyId, decryptAttributes.getMetadata()); final GetKeysResponse.Key getKey = getKeysResponse.getFirstKey(); decryptAttributes.setKeyResponse(getKey); // reconstitute batch IVs final String ivs = getBatchAttribute(decryptAttributes.getKeyAttributes(), IONIC_IVS); final BatchGcmParameterSpec batchParameterSpec = new BatchGcmParameterSpec(ivs); // reconstitute batch ATAGs final String atags = getBatchAttribute(decryptAttributes.getMutableKeyAttributes(), IONIC_ATAGS); final ByteArrayInputStream isAtags = new ByteArrayInputStream(Transcoder.base64().decode(atags)); // iterate through ciphertexts final AesGcmCipher cipher = new AesGcmCipher(getKey.getSecretKey()); cipher.setAuthData(Transcoder.utf8().decode(getKey.getId())); for (CipherTextItem item : items) { final byte[] cipherText = item.getData(); final byte[] cipherTextWithAtag = Arrays.copyOf(cipherText, cipherText.length + AesCipher.SIZE_ATAG); final int countAtag = isAtags.read(cipherTextWithAtag, cipherText.length, AesCipher.SIZE_ATAG); SdkData.checkTrue(countAtag == AesCipher.SIZE_ATAG, SdkError.ISAGENT_INVALIDVALUE); final byte[] plainText = new byte[cipherText.length]; final ByteBuffer cipherBuffer = ByteBuffer.wrap(cipherTextWithAtag); final ByteBuffer plainBuffer = ByteBuffer.wrap(plainText); final int count = cipher.decrypt(plainBuffer, cipherBuffer, batchParameterSpec.next()); SdkData.checkTrue(plainText.length == count, SdkError.ISAGENT_INVALIDVALUE); plainTextResults.add(new PlainTextItem(plainText)); } return plainTextResults; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy