![JAR search and dependency download from the Maven repository](/logo.png)
com.unbound.provider.SecretKeyCipher Maven / Gradle / Ivy
package com.unbound.provider;
import com.dyadicsec.provider.KeyGenSpec;
import com.dyadicsec.provider.KeyParameters;
import com.unbound.common.Log;
import com.unbound.provider.kmip.KMIP;
import com.unbound.provider.kmip.attribute.CryptoParams;
import com.unbound.provider.kmip.attribute.KeyWrappingSpec;
import com.unbound.provider.kmip.attribute.MessageExt;
import com.unbound.provider.kmip.object.PrivateKey;
import com.unbound.provider.kmip.object.SymmetricKey;
import com.unbound.provider.kmip.request.DecryptRequest;
import com.unbound.provider.kmip.request.EncryptRequest;
import com.unbound.provider.kmip.request.GetRequest;
import com.unbound.provider.kmip.request.RegisterRequest;
import com.unbound.provider.kmip.response.DecryptResponse;
import com.unbound.provider.kmip.response.EncryptResponse;
import com.unbound.provider.kmip.response.GetResponse;
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.IOException;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.util.ArrayList;
import java.util.Arrays;
public class SecretKeyCipher extends CipherSpi
{
private KeyParameters unwrapKeyParameter = null;
private int kmipAlg;
private boolean aad = false;
private boolean wrap = false;
private boolean encrypt = false;
private boolean padding = false;
private int kmipMode = 0;
private AlgorithmParameterSpec paramSpec = null;
private byte[] auth = null;
private byte[] corr = null;
private UBSecretKey secretKey = null;
private CryptoParams kmipParams = new CryptoParams();
private MessageExt kmipExt = null;
SecretKeyCipher(int kmipAlg)
{
this.kmipAlg = kmipAlg;
}
private void init()
{
auth = null;
corr = null;
}
private void setKmipIV(SecureRandom secureRandom) throws InvalidAlgorithmParameterException
{
if (paramSpec==null && encrypt)
{
if (secureRandom==null) throw new InvalidAlgorithmParameterException("Can't generate IV");
int size = engineGetBlockSize();
byte[] ivData = new byte[size];
secureRandom.nextBytes(ivData);
paramSpec = new IvParameterSpec(ivData);
}
if (paramSpec==null || !(paramSpec instanceof IvParameterSpec)) throw new InvalidAlgorithmParameterException("IvParameterSpec required");
IvParameterSpec ivSpec = (IvParameterSpec)paramSpec;
kmipExt = new MessageExt();
kmipExt.iv = ivSpec.getIV();
}
private ArrayList getAuthParam()
{
if (!aad) return null;
if (auth==null) auth = new byte[0];
ArrayList a = new ArrayList();
a.add(auth);
return a;
}
private int execEncDec(byte[] in, int inOffset, int inLen, byte[] out, int outOffset, boolean doFinal) throws ShortBufferException
{
int outLen = -1;
Log log = Log.func("SecretKeyCipher.execEncDec")
.log("encrypt", encrypt)
.log("doFinal", doFinal)
.log("inOffset", inOffset)
.log("inLen", inLen).end(); try
{
if (secretKey==null) throw new ProviderException("Not initialized");
byte[] result;
if (encrypt)
{
EncryptRequest req = new EncryptRequest();
req.corr = corr;
if (inLen>0) req.data = Arrays.copyOfRange(in, inOffset, inOffset+inLen);
req.initInd = corr==null;
req.finalInd = doFinal;
req.uid = UBObject.uidToStr(secretKey.uid);
req.params = kmipParams;
req.ext = kmipExt;
if (kmipExt!=null)
{
req.ext.auth = getAuthParam();
req.iv = kmipExt.iv;
}
EncryptResponse resp;
try
{
resp = (EncryptResponse) secretKey.partition.transmit(req);
}
catch (IOException e)
{
throw new ProviderException(e);
}
corr = resp.corr;
result = resp.data;
}
else
{
DecryptRequest req = new DecryptRequest();
req.corr = corr;
if (inLen>0) req.data = Arrays.copyOfRange(in, inOffset, inOffset+inLen);
req.initInd = corr==null;
req.finalInd = doFinal;
req.uid = UBObject.uidToStr(secretKey.uid);
req.params = kmipParams;
req.ext = kmipExt;
if (kmipExt!=null)
{
req.ext.auth = getAuthParam();
req.iv = kmipExt.iv;
}
DecryptResponse resp;
try
{
resp = (DecryptResponse) secretKey.partition.transmit(req);
}
catch (IOException e)
{
init();
throw new ProviderException(e);
}
corr = resp.corr;
result = resp.data;
}
if (result.length > out.length-outOffset) { init(); throw new ShortBufferException(); }
System.arraycopy(result, 0, out, outOffset, result.length);
outLen = result.length;
return outLen;
}
catch (Exception e) { log.failed(e); throw e; } finally { log.leavePrint().log("outLen", outLen).end(); }
}
// ------------------------ interface ----------------------------
@Override
protected void engineSetMode(String mode) throws NoSuchAlgorithmException
{
aad = false;
mode = mode.toUpperCase();
if (mode.equalsIgnoreCase("GCM")) { kmipMode = KMIP.BlockCipherMode.GCM; aad = true; }
else if (mode.equalsIgnoreCase("ECB")) { kmipMode = KMIP.BlockCipherMode.ECB; }
else if (mode.equalsIgnoreCase("CBC")) { kmipMode = KMIP.BlockCipherMode.CBC; }
else if (mode.equalsIgnoreCase("CTR")) { kmipMode = KMIP.BlockCipherMode.CTR; }
else if (mode.equalsIgnoreCase("OFB128")) { kmipMode = KMIP.BlockCipherMode.OFB; }
else if (mode.equalsIgnoreCase("CFB128")) { kmipMode = KMIP.BlockCipherMode.CFB; }
else throw new NoSuchAlgorithmException("Mode not supported: " + mode);
}
@Override
protected void engineSetPadding(String padding) throws NoSuchPaddingException
{
if (padding.equalsIgnoreCase("NOPADDING")) this.padding = false;
else if (padding.equalsIgnoreCase("PKCS5PADDING"))
{
if (kmipMode!=KMIP.BlockCipherMode.CBC) throw new NoSuchPaddingException("padding not supported");
this.padding = true;
}
else throw new NoSuchPaddingException("padding not supported");
}
@Override
protected int engineGetBlockSize()
{
return 16; // AES only
}
@Override
protected int engineGetOutputSize(int inputLen)
{
if (kmipMode==KMIP.BlockCipherMode.GCM)
{
int tlen = ((GCMParameterSpec)paramSpec).getTLen()/8;
return encrypt ? (inputLen + tlen) : (inputLen - tlen);
}
return inputLen;
}
@Override
protected byte[] engineGetIV()
{
if (paramSpec==null) return null;
if (paramSpec instanceof IvParameterSpec) return ((IvParameterSpec)paramSpec).getIV();
return null;
}
@Override
protected AlgorithmParameters engineGetParameters()
{
if (paramSpec==null) return null;
try
{
AlgorithmParameters params = AlgorithmParameters.getInstance("AES", "SunJCE");
params.init(paramSpec);
return params;
}
catch (GeneralSecurityException e) { throw new ProviderException("Could not encode parameters", e); }
}
@Override
protected void engineInit(int opmode, Key key, AlgorithmParameterSpec algorithmParameterSpec, SecureRandom secureRandom) throws InvalidKeyException, InvalidAlgorithmParameterException
{
if (algorithmParameterSpec instanceof KeyGenSpec)
{
if (opmode!=Cipher.UNWRAP_MODE) throw new InvalidAlgorithmParameterException("KeyParameter is supported only in UNWRAP_MODE");
unwrapKeyParameter = ((KeyGenSpec)algorithmParameterSpec).getKeyParams();
algorithmParameterSpec = ((KeyGenSpec)algorithmParameterSpec).getOriginal();
}
else unwrapKeyParameter = null;
this.secretKey = null;
init();
if (opmode!=Cipher.WRAP_MODE &&
opmode!=Cipher.UNWRAP_MODE &&
opmode!=Cipher.ENCRYPT_MODE &&
opmode!=Cipher.DECRYPT_MODE) throw new InvalidParameterException("Invalid mode");
if (!(key instanceof UBSecretKey)) throw new InvalidKeyException("Invalid key type");
UBSecretKey secretKey = (UBSecretKey)key;
if (secretKey.getKmipAlg()!=KMIP.CryptographicAlgorithm.AES) throw new InvalidKeyException("Invalid key type");
wrap = (opmode == Cipher.WRAP_MODE) || (opmode == Cipher.UNWRAP_MODE);
encrypt = (opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE);
paramSpec = algorithmParameterSpec;
kmipParams.mode = kmipMode;
kmipParams.padding = padding ? KMIP.PaddingMethod.PKCS5 : KMIP.PaddingMethod.None;
GCMParameterSpec gcm;
int tagBits;
switch (kmipMode)
{
case KMIP.BlockCipherMode.GCM:
if (!(paramSpec instanceof GCMParameterSpec)) throw new InvalidAlgorithmParameterException("GCMParameterSpec required");
gcm = (GCMParameterSpec) paramSpec;
kmipExt = new MessageExt();
kmipExt.iv = gcm.getIV();
tagBits = gcm.getTLen();
if ((tagBits % 8)!=0) throw new InvalidAlgorithmParameterException("Invalid tag length");
kmipParams.tagLength = tagBits / 8;
if (kmipParams.tagLength<1 || kmipParams.tagLength>16) throw new InvalidAlgorithmParameterException("Invalid tag length");
if (kmipExt.iv.length!=12) throw new InvalidAlgorithmParameterException("Invalid IV length");
break;
case KMIP.BlockCipherMode.CTR:
setKmipIV(secureRandom);
if (kmipExt.iv.length!=16) throw new InvalidAlgorithmParameterException("Invalid IV length");
kmipParams.counterLength = 32;
break;
case KMIP.BlockCipherMode.CBC:
case KMIP.BlockCipherMode.OFB:
case KMIP.BlockCipherMode.CFB:
setKmipIV(secureRandom);
if (kmipExt.iv.length!=16) throw new InvalidAlgorithmParameterException("Invalid IV length");
break;
}
this.secretKey = secretKey;
}
@Override
protected void engineInit(int opmode, Key key, AlgorithmParameters algorithmParameters, SecureRandom secureRandom) throws InvalidKeyException, InvalidAlgorithmParameterException
{
AlgorithmParameterSpec spec = null;
Class extends AlgorithmParameterSpec> clazz = IvParameterSpec.class;
if (kmipMode==KMIP.BlockCipherMode.GCM) clazz = GCMParameterSpec.class;
if (algorithmParameters!=null)
{
try { spec = algorithmParameters.getParameterSpec(clazz); }
catch (InvalidParameterSpecException ipse) { throw new InvalidAlgorithmParameterException("Wrong parameter"); }
}
engineInit(opmode, key, spec, secureRandom);
}
@Override
protected void engineInit(int opmode, Key key, SecureRandom secureRandom) throws InvalidKeyException
{
try { engineInit(opmode, key, (AlgorithmParameterSpec)null, secureRandom); }
catch (InvalidAlgorithmParameterException e) { throw new InvalidKeyException(e); }
}
@Override
protected void engineUpdateAAD(byte[] in, int inOffset, int inLen) throws IllegalStateException, UnsupportedOperationException
{
if (!aad) throw new IllegalStateException("Cipher does not accept AAD");
if (auth==null)
{
auth = Arrays.copyOfRange(in, inOffset, inOffset+inLen);
}
else
{
int oldSize = auth.length;
byte[] newBuffer = new byte[oldSize+inLen];
if (oldSize>0) System.arraycopy(auth, 0, newBuffer, 0, oldSize);
System.arraycopy(in, inOffset, newBuffer, oldSize, inLen);
auth = newBuffer;
}
}
@Override
protected byte[] engineUpdate(byte[] in, int inOffset, int inLen)
{
byte[] out = new byte[inLen+32];
int outLen = 0;
try { outLen = engineUpdate(in, inOffset, inLen, out, 0); }
catch (ShortBufferException e) { throw new ProviderException(e); }
return Arrays.copyOf(out, outLen);
}
@Override
protected byte[] engineDoFinal(byte[] in, int inOffset, int inLen) throws IllegalBlockSizeException, BadPaddingException
{
byte[] out = new byte[inLen+32];
int outLen = 0;
try { outLen = engineDoFinal(in, inOffset, inLen, out, 0); }
catch (ShortBufferException e) { throw new ProviderException(e); }
return Arrays.copyOf(out, outLen);
}
@Override
protected int engineUpdate(byte[] in, int inOffset, int inLen, byte[] out, int outOffset) throws ShortBufferException
{
if (inLen==0) return 0;
return execEncDec(in, inOffset, inLen, out, outOffset, false);
}
@Override
protected int engineDoFinal(byte[] in, int inOffset, int inLen, byte[] out, int outOffset) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException
{
if (inLen==0)
{
switch (kmipMode)
{
case KMIP.BlockCipherMode.OFB:
case KMIP.BlockCipherMode.CFB:
case KMIP.BlockCipherMode.CTR:
case KMIP.BlockCipherMode.ECB:
return 0;
case KMIP.BlockCipherMode.CBC:
if (!padding) return 0;
break;
}
}
int outLen = execEncDec(in, inOffset, inLen, out, outOffset, true);
init();
return outLen;
}
@Override
protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException
{
Log log = Log.func("SecretKeyCipher.engineWrap").end(); try
{
if (secretKey==null) throw new ProviderException("Not initialized");
if (key==null) throw new ProviderException("key is null");
if (corr!=null) throw new ProviderException("engineUpdate called");
if (key instanceof UBSecretKey) ;
else if (key instanceof UBRSAPrivateKey) ;
else
{
byte[] encoded = key.getEncoded();
try { return engineDoFinal(encoded, 0, encoded.length); }
catch (BadPaddingException e) { throw new ProviderException(e); }
}
UBObject ubObject = (UBObject)key;
GetRequest req = new GetRequest();
req.uid = UBObject.uidToStr(ubObject.uid);
req.formatType = KMIP.KeyFormatType.Raw;
req.keyWrap = new KeyWrappingSpec();
req.keyWrap.encKey.uid = UBObject.uidToStr(secretKey.uid);
req.keyWrap.encKey.params = kmipParams;
req.ext = kmipExt;
if (kmipExt!=null) req.ext.auth = getAuthParam();
GetResponse resp;
try
{
resp = (GetResponse) secretKey.partition.transmit(req);
}
catch (IOException e)
{
throw new ProviderException(e);
}
init();
if (resp.object instanceof PrivateKey) return ((PrivateKey)resp.object).keyBlock.buf;
if (resp.object instanceof SymmetricKey) return ((SymmetricKey)resp.object).keyBlock.buf;
throw new ProviderException("Invalid managed object returned");
}
catch (Exception e) { log.failed(e); throw e; } finally { log.leave(); }
}
@Override
protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException
{
Log log = Log.func("SecretKeyCipher.engineUnwrap")
.log("wrappedKey.length", wrappedKey.length)
.log("wrappedKeyAlgorithm", wrappedKeyAlgorithm)
.log("wrappedKeyType", wrappedKeyType).end(); try
{
if (secretKey==null) throw new ProviderException("Not initialized");
if (corr!=null) throw new ProviderException("engineUpdate called");
int kmipAlg = 0;
UBPrivateKey newPrivateKey;
UBSecretKey newSecretKey;
RegisterRequest registerRequest = new RegisterRequest();
registerRequest.ext = kmipExt;
if (kmipExt!=null) registerRequest.ext.auth = getAuthParam();
switch (wrappedKeyType)
{
case Cipher.PRIVATE_KEY:
if (wrappedKeyAlgorithm.equalsIgnoreCase("RSA")) newPrivateKey = new UBRSAPrivateKey(secretKey.partition);
else if (wrappedKeyAlgorithm.equalsIgnoreCase("EC")) newPrivateKey = new UBECPrivateKey(secretKey.partition);
else throw new InvalidKeyException("Unsupported wrappedKeyAlgorithm " + wrappedKeyAlgorithm);
try { newPrivateKey.unwrap(unwrapKeyParameter, registerRequest, secretKey.uid, kmipParams, wrappedKey); }
catch (IOException | InvalidKeySpecException e) { throw new ProviderException(e); }
return newPrivateKey;
case Cipher.SECRET_KEY:
if (wrappedKeyAlgorithm.equalsIgnoreCase("AES")) kmipAlg = KMIP.CryptographicAlgorithm.AES;
else if (wrappedKeyAlgorithm.equalsIgnoreCase("HMAC")) kmipAlg = KMIP.CryptographicAlgorithm.HMAC_SHA256;
else throw new InvalidKeyException("Unsupported wrappedKeyAlgorithm " + wrappedKeyAlgorithm);
newSecretKey = new UBSecretKey(secretKey.partition, kmipAlg);
try { newSecretKey.unwrap(unwrapKeyParameter, registerRequest, secretKey.uid, kmipParams, wrappedKey); }
catch (IOException e) { throw new ProviderException(e); }
return newSecretKey;
}
throw new InvalidKeyException("Unsupported wrappedKeyType");
}
catch (Exception e) { log.failed(e); throw e; } finally { log.leave(); }
}
// ----------------------------- Sub-classes -----------------------
public static final class AES extends SecretKeyCipher
{
public AES() { super(KMIP.CryptographicAlgorithm.AES); }
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy