Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java')
-rw-r--r--prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java317
1 files changed, 317 insertions, 0 deletions
diff --git a/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java b/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
new file mode 100644
index 00000000..27c2eed1
--- /dev/null
+++ b/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
@@ -0,0 +1,317 @@
+package org.spongycastle.jcajce.provider.asymmetric.ec;
+
+import java.math.BigInteger;
+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 java.util.Hashtable;
+
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x9.X9IntegerConverter;
+import org.spongycastle.crypto.BasicAgreement;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
+import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
+import org.spongycastle.crypto.agreement.ECMQVBasicAgreement;
+import org.spongycastle.crypto.agreement.kdf.DHKDFParameters;
+import org.spongycastle.crypto.agreement.kdf.ECDHKEKGenerator;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.MQVPrivateParameters;
+import org.spongycastle.crypto.params.MQVPublicParameters;
+import org.spongycastle.jcajce.provider.asymmetric.util.ECUtil;
+import org.spongycastle.jce.interfaces.ECPrivateKey;
+import org.spongycastle.jce.interfaces.ECPublicKey;
+import org.spongycastle.jce.interfaces.MQVPrivateKey;
+import org.spongycastle.jce.interfaces.MQVPublicKey;
+import org.spongycastle.util.Integers;
+
+/**
+ * Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363
+ * both the simple one, and the simple one with cofactors are supported.
+ *
+ * Also, MQV key agreement per SEC-1
+ */
+public class KeyAgreementSpi
+ extends javax.crypto.KeyAgreementSpi
+{
+ private static final X9IntegerConverter converter = new X9IntegerConverter();
+ private static final Hashtable algorithms = new Hashtable();
+
+ static
+ {
+ Integer i128 = Integers.valueOf(128);
+ Integer i192 = Integers.valueOf(192);
+ Integer i256 = Integers.valueOf(256);
+
+ algorithms.put(NISTObjectIdentifiers.id_aes128_CBC.getId(), i128);
+ algorithms.put(NISTObjectIdentifiers.id_aes192_CBC.getId(), i192);
+ algorithms.put(NISTObjectIdentifiers.id_aes256_CBC.getId(), i256);
+ algorithms.put(NISTObjectIdentifiers.id_aes128_wrap.getId(), i128);
+ algorithms.put(NISTObjectIdentifiers.id_aes192_wrap.getId(), i192);
+ algorithms.put(NISTObjectIdentifiers.id_aes256_wrap.getId(), i256);
+ algorithms.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), i192);
+ }
+
+ private String kaAlgorithm;
+ private BigInteger result;
+ private ECDomainParameters parameters;
+ private BasicAgreement agreement;
+ private DerivationFunction kdf;
+
+ private byte[] bigIntToBytes(
+ BigInteger r)
+ {
+ return converter.integerToBytes(r, converter.getByteLength(parameters.getG().getX()));
+ }
+
+ protected KeyAgreementSpi(
+ String kaAlgorithm,
+ BasicAgreement agreement,
+ DerivationFunction kdf)
+ {
+ this.kaAlgorithm = kaAlgorithm;
+ this.agreement = agreement;
+ this.kdf = kdf;
+ }
+
+ protected Key engineDoPhase(
+ Key key,
+ boolean lastPhase)
+ throws InvalidKeyException, IllegalStateException
+ {
+ if (parameters == null)
+ {
+ throw new IllegalStateException(kaAlgorithm + " not initialised.");
+ }
+
+ if (!lastPhase)
+ {
+ throw new IllegalStateException(kaAlgorithm + " can only be between two parties.");
+ }
+
+ CipherParameters pubKey;
+ if (agreement instanceof ECMQVBasicAgreement)
+ {
+ if (!(key instanceof MQVPublicKey))
+ {
+ throw new InvalidKeyException(kaAlgorithm + " key agreement requires "
+ + getSimpleName(MQVPublicKey.class) + " for doPhase");
+ }
+
+ MQVPublicKey mqvPubKey = (MQVPublicKey)key;
+ ECPublicKeyParameters staticKey = (ECPublicKeyParameters)
+ ECUtil.generatePublicKeyParameter(mqvPubKey.getStaticKey());
+ ECPublicKeyParameters ephemKey = (ECPublicKeyParameters)
+ ECUtil.generatePublicKeyParameter(mqvPubKey.getEphemeralKey());
+
+ pubKey = new MQVPublicParameters(staticKey, ephemKey);
+
+ // TODO Validate that all the keys are using the same parameters?
+ }
+ else
+ {
+ if (!(key instanceof ECPublicKey))
+ {
+ throw new InvalidKeyException(kaAlgorithm + " key agreement requires "
+ + getSimpleName(ECPublicKey.class) + " for doPhase");
+ }
+
+ pubKey = ECUtil.generatePublicKeyParameter((PublicKey)key);
+
+ // TODO Validate that all the keys are using the same parameters?
+ }
+
+ result = agreement.calculateAgreement(pubKey);
+
+ return null;
+ }
+
+ protected byte[] engineGenerateSecret()
+ throws IllegalStateException
+ {
+ if (kdf != null)
+ {
+ throw new UnsupportedOperationException(
+ "KDF can only be used when algorithm is known");
+ }
+
+ return bigIntToBytes(result);
+ }
+
+ protected int engineGenerateSecret(
+ byte[] sharedSecret,
+ int offset)
+ throws IllegalStateException, ShortBufferException
+ {
+ byte[] secret = engineGenerateSecret();
+
+ if (sharedSecret.length - offset < secret.length)
+ {
+ throw new ShortBufferException(kaAlgorithm + " key agreement: need " + secret.length + " bytes");
+ }
+
+ System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
+
+ return secret.length;
+ }
+
+ protected SecretKey engineGenerateSecret(
+ String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ byte[] secret = bigIntToBytes(result);
+
+ if (kdf != null)
+ {
+ if (!algorithms.containsKey(algorithm))
+ {
+ throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm);
+ }
+
+ int keySize = ((Integer)algorithms.get(algorithm)).intValue();
+
+ DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(algorithm), keySize, secret);
+
+ byte[] keyBytes = new byte[keySize / 8];
+ kdf.init(params);
+ kdf.generateBytes(keyBytes, 0, keyBytes.length);
+ secret = keyBytes;
+ }
+ else
+ {
+ // TODO Should we be ensuring the key is the right length?
+ }
+
+ return new SecretKeySpec(secret, algorithm);
+ }
+
+ protected void engineInit(
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ initFromKey(key);
+ }
+
+ protected void engineInit(
+ Key key,
+ SecureRandom random)
+ throws InvalidKeyException
+ {
+ initFromKey(key);
+ }
+
+ private void initFromKey(Key key)
+ throws InvalidKeyException
+ {
+ if (agreement instanceof ECMQVBasicAgreement)
+ {
+ if (!(key instanceof MQVPrivateKey))
+ {
+ throw new InvalidKeyException(kaAlgorithm + " key agreement requires "
+ + getSimpleName(MQVPrivateKey.class) + " for initialisation");
+ }
+
+ MQVPrivateKey mqvPrivKey = (MQVPrivateKey)key;
+ ECPrivateKeyParameters staticPrivKey = (ECPrivateKeyParameters)
+ ECUtil.generatePrivateKeyParameter(mqvPrivKey.getStaticPrivateKey());
+ ECPrivateKeyParameters ephemPrivKey = (ECPrivateKeyParameters)
+ ECUtil.generatePrivateKeyParameter(mqvPrivKey.getEphemeralPrivateKey());
+
+ ECPublicKeyParameters ephemPubKey = null;
+ if (mqvPrivKey.getEphemeralPublicKey() != null)
+ {
+ ephemPubKey = (ECPublicKeyParameters)
+ ECUtil.generatePublicKeyParameter(mqvPrivKey.getEphemeralPublicKey());
+ }
+
+ MQVPrivateParameters localParams = new MQVPrivateParameters(staticPrivKey, ephemPrivKey, ephemPubKey);
+ this.parameters = staticPrivKey.getParameters();
+
+ // TODO Validate that all the keys are using the same parameters?
+
+ agreement.init(localParams);
+ }
+ else
+ {
+ if (!(key instanceof ECPrivateKey))
+ {
+ throw new InvalidKeyException(kaAlgorithm + " key agreement requires "
+ + getSimpleName(ECPrivateKey.class) + " for initialisation");
+ }
+
+ ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)ECUtil.generatePrivateKeyParameter((PrivateKey)key);
+ this.parameters = privKey.getParameters();
+
+ agreement.init(privKey);
+ }
+ }
+
+ private static String getSimpleName(Class clazz)
+ {
+ String fullName = clazz.getName();
+
+ return fullName.substring(fullName.lastIndexOf('.') + 1);
+ }
+
+ public static class DH
+ extends KeyAgreementSpi
+ {
+ public DH()
+ {
+ super("ECDH", new ECDHBasicAgreement(), null);
+ }
+ }
+
+ public static class DHC
+ extends KeyAgreementSpi
+ {
+ public DHC()
+ {
+ super("ECDHC", new ECDHCBasicAgreement(), null);
+ }
+ }
+
+ public static class MQV
+ extends KeyAgreementSpi
+ {
+ public MQV()
+ {
+ super("ECMQV", new ECMQVBasicAgreement(), null);
+ }
+ }
+
+ public static class DHwithSHA1KDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA1KDF()
+ {
+ super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest()));
+ }
+ }
+
+ public static class MQVwithSHA1KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA1KDF()
+ {
+ super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest()));
+ }
+ }
+}