org.bouncycastle.jcajce.provider.asymmetric.ec.GMCipherSpi 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.jcajce.provider.asymmetric.ec;
import java.io.ByteArrayOutputStream;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
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.ShortBufferException;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.digests.Blake2sDigest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.digests.WhirlpoolDigest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.util.BadBlockException;
import org.bouncycastle.jcajce.util.BCJcaJceHelper;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.jce.interfaces.ECKey;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;
public class GMCipherSpi
extends CipherSpi
{
private final JcaJceHelper helper = new BCJcaJceHelper();
private SM2Engine engine;
private int state = -1;
private ErasableOutputStream buffer = new ErasableOutputStream();
private AsymmetricKeyParameter key;
private SecureRandom random;
public GMCipherSpi(SM2Engine engine)
{
this.engine = engine;
}
public int engineGetBlockSize()
{
return 0;
}
public int engineGetKeySize(Key key)
{
if (key instanceof ECKey)
{
return ((ECKey)key).getParameters().getCurve().getFieldSize();
}
else
{
throw new IllegalArgumentException("not an EC key");
}
}
public byte[] engineGetIV()
{
return null;
}
public AlgorithmParameters engineGetParameters()
{
return null;
}
public void engineSetMode(String mode)
throws NoSuchAlgorithmException
{
String modeName = Strings.toUpperCase(mode);
if (!modeName.equals("NONE"))
{
throw new IllegalArgumentException("can't support mode " + mode);
}
}
public int engineGetOutputSize(int inputLen)
{
if (state == Cipher.ENCRYPT_MODE || state == Cipher.WRAP_MODE)
{
return engine.getOutputSize(inputLen);
}
else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
{
return engine.getOutputSize(inputLen);
}
else
{
throw new IllegalStateException("cipher not initialised");
}
}
public void engineSetPadding(String padding)
throws NoSuchPaddingException
{
String paddingName = Strings.toUpperCase(padding);
// TDOD: make this meaningful...
if (!paddingName.equals("NOPADDING"))
{
throw new NoSuchPaddingException("padding not available with IESCipher");
}
}
// Initialisation methods
public void engineInit(
int opmode,
Key key,
AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
AlgorithmParameterSpec paramSpec = null;
if (params != null)
{
throw new InvalidAlgorithmParameterException("cannot recognise parameters: " + params.getClass().getName());
}
engineInit(opmode, key, paramSpec, random);
}
public void engineInit(
int opmode,
Key key,
AlgorithmParameterSpec engineSpec,
SecureRandom random)
throws InvalidAlgorithmParameterException, InvalidKeyException
{
// Parse the recipient's key
if (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE)
{
if (key instanceof PublicKey)
{
this.key = ECUtils.generatePublicKeyParameter((PublicKey)key);
}
else
{
throw new InvalidKeyException("must be passed public EC key for encryption");
}
}
else if (opmode == Cipher.DECRYPT_MODE || opmode == Cipher.UNWRAP_MODE)
{
if (key instanceof PrivateKey)
{
this.key = ECUtil.generatePrivateKeyParameter((PrivateKey)key);
}
else
{
throw new InvalidKeyException("must be passed private EC key for decryption");
}
}
else
{
throw new InvalidKeyException("must be passed EC key");
}
if (random != null)
{
this.random = random;
}
else
{
this.random = CryptoServicesRegistrar.getSecureRandom();
}
this.state = opmode;
buffer.reset();
}
public void engineInit(
int opmode,
Key key,
SecureRandom random)
throws InvalidKeyException
{
try
{
engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
}
catch (InvalidAlgorithmParameterException e)
{
throw new IllegalArgumentException("cannot handle supplied parameter spec: " + e.getMessage());
}
}
// Update methods - buffer the input
public byte[] engineUpdate(
byte[] input,
int inputOffset,
int inputLen)
{
buffer.write(input, inputOffset, inputLen);
return null;
}
public int engineUpdate(
byte[] input,
int inputOffset,
int inputLen,
byte[] output,
int outputOffset)
{
buffer.write(input, inputOffset, inputLen);
return 0;
}
// Finalisation methods
public byte[] engineDoFinal(
byte[] input,
int inputOffset,
int inputLen)
throws IllegalBlockSizeException, BadPaddingException
{
if (inputLen != 0)
{
buffer.write(input, inputOffset, inputLen);
}
try
{
if (state == Cipher.ENCRYPT_MODE || state == Cipher.WRAP_MODE)
{
// Encrypt the buffer
try
{
engine.init(true, new ParametersWithRandom(key, random));
return engine.processBlock(buffer.getBuf(), 0, buffer.size());
}
catch (final Exception e)
{
throw new BadBlockException("unable to process block", e);
}
}
else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
{
// Decrypt the buffer
try
{
engine.init(false, key);
return engine.processBlock(buffer.getBuf(), 0, buffer.size());
}
catch (final Exception e)
{
throw new BadBlockException("unable to process block", e);
}
}
else
{
throw new IllegalStateException("cipher not initialised");
}
}
finally
{
buffer.erase();
}
}
public int engineDoFinal(
byte[] input,
int inputOffset,
int inputLength,
byte[] output,
int outputOffset)
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException
{
byte[] buf = engineDoFinal(input, inputOffset, inputLength);
System.arraycopy(buf, 0, output, outputOffset, buf.length);
return buf.length;
}
/**
* Classes that inherit from us
*/
static public class SM2
extends GMCipherSpi
{
public SM2()
{
super(new SM2Engine());
}
}
static public class SM2withBlake2b
extends GMCipherSpi
{
public SM2withBlake2b()
{
super(new SM2Engine(new Blake2bDigest(512)));
}
}
static public class SM2withBlake2s
extends GMCipherSpi
{
public SM2withBlake2s()
{
super(new SM2Engine(new Blake2sDigest(256)));
}
}
static public class SM2withWhirlpool
extends GMCipherSpi
{
public SM2withWhirlpool()
{
super(new SM2Engine(new WhirlpoolDigest()));
}
}
static public class SM2withMD5
extends GMCipherSpi
{
public SM2withMD5()
{
super(new SM2Engine(new MD5Digest()));
}
}
static public class SM2withRMD
extends GMCipherSpi
{
public SM2withRMD()
{
super(new SM2Engine(new RIPEMD160Digest()));
}
}
static public class SM2withSha1
extends GMCipherSpi
{
public SM2withSha1()
{
super(new SM2Engine(new SHA1Digest()));
}
}
static public class SM2withSha224
extends GMCipherSpi
{
public SM2withSha224()
{
super(new SM2Engine(new SHA224Digest()));
}
}
static public class SM2withSha256
extends GMCipherSpi
{
public SM2withSha256()
{
super(new SM2Engine(SHA256Digest.newInstance()));
}
}
static public class SM2withSha384
extends GMCipherSpi
{
public SM2withSha384()
{
super(new SM2Engine(new SHA384Digest()));
}
}
static public class SM2withSha512
extends GMCipherSpi
{
public SM2withSha512()
{
super(new SM2Engine(new SHA512Digest()));
}
}
protected static final class ErasableOutputStream
extends ByteArrayOutputStream
{
public ErasableOutputStream()
{
}
public byte[] getBuf()
{
return buf;
}
public void erase()
{
Arrays.fill(this.buf, (byte)0);
reset();
}
}
}