| package org.bouncycastle.jcajce.provider.asymmetric.ecgost; |
| |
| import java.security.InvalidAlgorithmParameterException; |
| import java.security.InvalidKeyException; |
| import java.security.Key; |
| import java.security.PrivateKey; |
| import java.security.PublicKey; |
| import java.security.SecureRandom; |
| import java.security.spec.AlgorithmParameterSpec; |
| |
| import org.bouncycastle.asn1.x9.X9IntegerConverter; |
| import org.bouncycastle.crypto.CipherParameters; |
| import org.bouncycastle.crypto.DerivationFunction; |
| import org.bouncycastle.crypto.agreement.ECVKOAgreement; |
| import org.bouncycastle.crypto.digests.GOST3411Digest; |
| import org.bouncycastle.crypto.params.AsymmetricKeyParameter; |
| import org.bouncycastle.crypto.params.ECDomainParameters; |
| import org.bouncycastle.crypto.params.ECPrivateKeyParameters; |
| import org.bouncycastle.crypto.params.ParametersWithUKM; |
| import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; |
| import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi; |
| import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; |
| import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec; |
| import org.bouncycastle.jce.interfaces.ECPrivateKey; |
| import org.bouncycastle.jce.interfaces.ECPublicKey; |
| |
| public class KeyAgreementSpi |
| extends BaseAgreementSpi |
| { |
| private static final X9IntegerConverter converter = new X9IntegerConverter(); |
| |
| private String kaAlgorithm; |
| |
| private ECDomainParameters parameters; |
| private ECVKOAgreement agreement; |
| |
| private byte[] result; |
| |
| protected KeyAgreementSpi( |
| String kaAlgorithm, |
| ECVKOAgreement agreement, |
| DerivationFunction kdf) |
| { |
| super(kaAlgorithm, kdf); |
| |
| this.kaAlgorithm = kaAlgorithm; |
| this.agreement = agreement; |
| } |
| |
| 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 (!(key instanceof PublicKey)) |
| { |
| throw new InvalidKeyException(kaAlgorithm + " key agreement requires " |
| + getSimpleName(ECPublicKey.class) + " for doPhase"); |
| } |
| |
| pubKey = generatePublicKeyParameter((PublicKey)key); |
| } |
| |
| try |
| { |
| result = agreement.calculateAgreement(pubKey); |
| } |
| catch (final Exception e) |
| { |
| throw new InvalidKeyException("calculation failed: " + e.getMessage()) |
| { |
| public Throwable getCause() |
| { |
| return e; |
| } |
| }; |
| } |
| |
| return null; |
| } |
| |
| protected void engineInit( |
| Key key, |
| AlgorithmParameterSpec params, |
| SecureRandom random) |
| throws InvalidKeyException, InvalidAlgorithmParameterException |
| { |
| if (params != null && !(params instanceof UserKeyingMaterialSpec)) |
| { |
| throw new InvalidAlgorithmParameterException("No algorithm parameters supported"); |
| } |
| |
| initFromKey(key, params); |
| } |
| |
| protected void engineInit( |
| Key key, |
| SecureRandom random) |
| throws InvalidKeyException |
| { |
| initFromKey(key, null); |
| } |
| |
| private void initFromKey(Key key, AlgorithmParameterSpec parameterSpec) |
| throws InvalidKeyException |
| { |
| { |
| if (!(key instanceof PrivateKey)) |
| { |
| throw new InvalidKeyException(kaAlgorithm + " key agreement requires " |
| + getSimpleName(ECPrivateKey.class) + " for initialisation"); |
| } |
| |
| ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)ECUtil.generatePrivateKeyParameter((PrivateKey)key); |
| this.parameters = privKey.getParameters(); |
| ukmParameters = (parameterSpec instanceof UserKeyingMaterialSpec) ? ((UserKeyingMaterialSpec)parameterSpec).getUserKeyingMaterial() : null; |
| agreement.init(new ParametersWithUKM(privKey, ukmParameters)); |
| } |
| } |
| |
| private static String getSimpleName(Class clazz) |
| { |
| String fullName = clazz.getName(); |
| |
| return fullName.substring(fullName.lastIndexOf('.') + 1); |
| } |
| |
| protected byte[] calcSecret() |
| { |
| return result; |
| } |
| |
| static AsymmetricKeyParameter generatePublicKeyParameter( |
| PublicKey key) |
| throws InvalidKeyException |
| { |
| return (key instanceof BCECPublicKey) ? ((BCECGOST3410PublicKey)key).engineGetKeyParameters() : ECUtil.generatePublicKeyParameter(key); |
| } |
| |
| public static class ECVKO |
| extends KeyAgreementSpi |
| { |
| public ECVKO() |
| { |
| super("ECGOST3410", new ECVKOAgreement(new GOST3411Digest()), null); |
| } |
| } |
| } |