org.bouncycastle.pqc.jcajce.provider.bike.BIKECipherSpi Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-ext-debug-jdk18on Show documentation
Show all versions of bcprov-ext-debug-jdk18on Show documentation
The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for Java 1.8 and later with debug enabled.
The newest version!
package org.bouncycastle.pqc.jcajce.provider.bike;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherSpi;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.DestroyFailedException;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.SecretWithEncapsulation;
import org.bouncycastle.crypto.Wrapper;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jcajce.spec.KEMParameterSpec;
import org.bouncycastle.jcajce.spec.KTSParameterSpec;
import org.bouncycastle.pqc.crypto.bike.BIKEKEMExtractor;
import org.bouncycastle.pqc.crypto.bike.BIKEKEMGenerator;
import org.bouncycastle.pqc.crypto.bike.BIKEParameters;
import org.bouncycastle.pqc.jcajce.provider.util.WrapUtil;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Exceptions;
import org.bouncycastle.util.Strings;
class BIKECipherSpi
extends CipherSpi
{
private final String algorithmName;
private BIKEKEMGenerator kemGen;
private KTSParameterSpec kemParameterSpec;
private BCBIKEPublicKey wrapKey;
private BCBIKEPrivateKey unwrapKey;
private AlgorithmParameters engineParams;
private BIKEParameters bikeParameters;
BIKECipherSpi(String algorithmName)
throws NoSuchAlgorithmException
{
this.bikeParameters = null;
this.algorithmName = algorithmName;
}
BIKECipherSpi(BIKEParameters bikeParameters)
{
this.bikeParameters = bikeParameters;
this.algorithmName = Strings.toUpperCase(bikeParameters.getName());
}
@Override
protected void engineSetMode(String mode)
throws NoSuchAlgorithmException
{
throw new NoSuchAlgorithmException("Cannot support mode " + mode);
}
@Override
protected void engineSetPadding(String padding)
throws NoSuchPaddingException
{
throw new NoSuchPaddingException("Padding " + padding + " unknown");
}
protected int engineGetKeySize(
Key key)
{
return 2048; // TODO
//throw new IllegalArgumentException("not an valid key!");
}
@Override
protected int engineGetBlockSize()
{
return 0;
}
@Override
protected int engineGetOutputSize(int i)
{
return -1; // can't use with update/doFinal
}
@Override
protected byte[] engineGetIV()
{
return null;
}
@Override
protected AlgorithmParameters engineGetParameters()
{
if (engineParams == null)
{
try
{
engineParams = AlgorithmParameters.getInstance(algorithmName, "BCPQC");
engineParams.init(kemParameterSpec);
}
catch (Exception e)
{
throw Exceptions.illegalStateException(e.toString(), e);
}
}
return engineParams;
}
@Override
protected void engineInit(int opmode, Key key, SecureRandom random)
throws InvalidKeyException
{
try
{
engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
}
catch (InvalidAlgorithmParameterException e)
{
throw Exceptions.illegalArgumentException(e.getMessage(), e);
}
}
@Override
protected void engineInit(int opmode, Key key, AlgorithmParameterSpec paramSpec, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
if (paramSpec == null)
{
// TODO: default should probably use shake.
kemParameterSpec = new KEMParameterSpec("AES-KWP");
}
else
{
if (!(paramSpec instanceof KTSParameterSpec))
{
throw new InvalidAlgorithmParameterException(algorithmName + " can only accept KTSParameterSpec");
}
kemParameterSpec = (KTSParameterSpec)paramSpec;
}
if (opmode == Cipher.WRAP_MODE)
{
if (key instanceof BCBIKEPublicKey)
{
wrapKey = (BCBIKEPublicKey)key;
kemGen = new BIKEKEMGenerator(CryptoServicesRegistrar.getSecureRandom(random));
}
else
{
throw new InvalidKeyException("Only a " + algorithmName + " public key can be used for wrapping");
}
}
else if (opmode == Cipher.UNWRAP_MODE)
{
if (key instanceof BCBIKEPrivateKey)
{
unwrapKey = (BCBIKEPrivateKey)key;
}
else
{
throw new InvalidKeyException("Only a " + algorithmName + " private key can be used for unwrapping");
}
}
else
{
throw new InvalidParameterException("Cipher only valid for wrapping/unwrapping");
}
if (bikeParameters != null)
{
String canonicalAlgName = Strings.toUpperCase(bikeParameters.getName());
if (!canonicalAlgName.equals(key.getAlgorithm()))
{
throw new InvalidKeyException("cipher locked to " + canonicalAlgName + " " + key.getAlgorithm());
}
}
}
@Override
protected void engineInit(int opmode, Key key, AlgorithmParameters algorithmParameters, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
AlgorithmParameterSpec paramSpec = null;
if (algorithmParameters != null)
{
try
{
paramSpec = algorithmParameters.getParameterSpec(KEMParameterSpec.class);
}
catch (Exception e)
{
throw new InvalidAlgorithmParameterException("can't handle parameter " + algorithmParameters.toString());
}
}
engineInit(opmode, key, paramSpec, random);
}
@Override
protected byte[] engineUpdate(byte[] bytes, int i, int i1)
{
throw new IllegalStateException("Not supported in a wrapping mode");
}
@Override
protected int engineUpdate(byte[] bytes, int i, int i1, byte[] bytes1, int i2)
throws ShortBufferException
{
throw new IllegalStateException("Not supported in a wrapping mode");
}
@Override
protected byte[] engineDoFinal(byte[] bytes, int i, int i1)
throws IllegalBlockSizeException, BadPaddingException
{
throw new IllegalStateException("Not supported in a wrapping mode");
}
@Override
protected int engineDoFinal(byte[] bytes, int i, int i1, byte[] bytes1, int i2)
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException
{
throw new IllegalStateException("Not supported in a wrapping mode");
}
protected byte[] engineWrap(
Key key)
throws IllegalBlockSizeException, InvalidKeyException
{
byte[] encoded = key.getEncoded();
if (encoded == null)
{
throw new InvalidKeyException("Cannot wrap key, null encoding.");
}
try
{
SecretWithEncapsulation secEnc = kemGen.generateEncapsulated(wrapKey.getKeyParams());
Wrapper kWrap = WrapUtil.getWrapper(kemParameterSpec.getKeyAlgorithmName());
KeyParameter keyParameter = new KeyParameter(secEnc.getSecret());
kWrap.init(true, keyParameter);
byte[] encapsulation = secEnc.getEncapsulation();
secEnc.destroy();
byte[] keyToWrap = key.getEncoded();
byte[] rv = Arrays.concatenate(encapsulation, kWrap.wrap(keyToWrap, 0, keyToWrap.length));
Arrays.clear(keyToWrap);
return rv;
}
catch (IllegalArgumentException e)
{
throw new IllegalBlockSizeException("unable to generate KTS secret: " + e.getMessage());
}
catch (DestroyFailedException e)
{
throw new IllegalBlockSizeException("unable to destroy interim values: " + e.getMessage());
}
}
protected Key engineUnwrap(
byte[] wrappedKey,
String wrappedKeyAlgorithm,
int wrappedKeyType)
throws InvalidKeyException, NoSuchAlgorithmException
{
// TODO: add support for other types.
if (wrappedKeyType != Cipher.SECRET_KEY)
{
throw new InvalidKeyException("only SECRET_KEY supported");
}
try
{
BIKEKEMExtractor kemExt = new BIKEKEMExtractor(unwrapKey.getKeyParams());
byte[] secret = kemExt.extractSecret(Arrays.copyOfRange(wrappedKey, 0, kemExt.getEncapsulationLength()));
Wrapper kWrap = WrapUtil.getWrapper(kemParameterSpec.getKeyAlgorithmName());
KeyParameter keyParameter = new KeyParameter(secret);
Arrays.clear(secret);
kWrap.init(false, keyParameter);
byte[] keyEncBytes = Arrays.copyOfRange(wrappedKey, kemExt.getEncapsulationLength(), wrappedKey.length);
SecretKey rv = new SecretKeySpec(kWrap.unwrap(keyEncBytes, 0, keyEncBytes.length), wrappedKeyAlgorithm);
Arrays.clear(keyParameter.getKey());
return rv;
}
catch (IllegalArgumentException e)
{
throw new NoSuchAlgorithmException("unable to extract KTS secret: " + e.getMessage());
}
catch (InvalidCipherTextException e)
{
throw new InvalidKeyException("unable to extract KTS secret: " + e.getMessage());
}
}
public static class Base
extends BIKECipherSpi
{
public Base()
throws NoSuchAlgorithmException
{
super("BIKE");
}
}
public static class BIKE128
extends BIKECipherSpi
{
public BIKE128()
{
super(BIKEParameters.bike128);
}
}
public static class BIKE192
extends BIKECipherSpi
{
public BIKE192()
{
super(BIKEParameters.bike192);
}
}
public static class BIKE256
extends BIKECipherSpi
{
public BIKE256()
{
super(BIKEParameters.bike256);
}
}
}