All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.mmm.crypto.asymmetric.key.AbstractAsymmetricKeyCreator Maven / Gradle / Ivy

package io.github.mmm.crypto.asymmetric.key;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.github.mmm.crypto.CryptoBinaryFormat;
import io.github.mmm.crypto.algorithm.CryptoAlgorithmImplWithRandom;
import io.github.mmm.crypto.asymmetric.key.generic.AsymmetricKeyPairFactoryEncoded;
import io.github.mmm.crypto.key.KeyCreator;
import io.github.mmm.crypto.provider.SecurityProvider;
import io.github.mmm.crypto.random.RandomFactory;

/**
 * Abstract base implementation of {@link KeyCreator}.
 *
 * @param  type of wrapped {@link PrivateKey}.
 * @param  type of wrapped {@link PublicKey}.
 * @param  type of {@link AsymmetricKeyPair}.
 * @since 1.0.0
 */
public abstract class AbstractAsymmetricKeyCreator>
    extends CryptoAlgorithmImplWithRandom implements AsymmetricKeyCreator {

  private final Map> format2factoryMap;

  private final List formatOrderList;

  private final int keyLength;

  /**
   * The constructor.
   *
   * @param keyFactory the {@link KeyFactory}.
   * @param keyLength the {@link #getKeyLength() key length}.
   * @param provider the security {@link Provider}.
   * @param randomFactory the {@link RandomFactory}.
   */
  public AbstractAsymmetricKeyCreator(KeyFactory keyFactory, int keyLength, SecurityProvider provider,
      RandomFactory randomFactory) {

    super(keyFactory.getAlgorithm(), provider, randomFactory);
    this.keyLength = keyLength;
    this.format2factoryMap = new HashMap<>();
    this.formatOrderList = new ArrayList<>();
    this.format2factoryMap.put(CryptoBinaryFormat.FORMAT_ENCODED, new AsymmetricKeyPairFactoryEncoded<>(keyFactory, this));
  }

  @Override
  public int getKeyLength() {

    return this.keyLength;
  }

  /**
   * Please register in proper order of trials for auto-detection.
   *
   * @param factory the {@link AsymmetricKeyPairFactory} to register.
   */
  protected void register(AsymmetricKeyPairFactory factory) {

    register(factory, CryptoBinaryFormat.FORMAT_COMPACT);
  }

  /**
   * Please register in proper order of trials for auto-detection.
   *
   * @param factory the {@link AsymmetricKeyPairFactory} to register.
   * @param format the format to register as.
   */
  protected void register(AsymmetricKeyPairFactory factory, String format) {

    AsymmetricKeyPairFactory old = this.format2factoryMap.put(format, factory);
    if (old != null) {
      throw new IllegalStateException("Duplicate format " + format + " registered!");
    }
    this.formatOrderList.add(format);
  }

  private List getFormatOrderList() {

    if (this.formatOrderList.size() < this.format2factoryMap.size()) {
      this.formatOrderList.add(CryptoBinaryFormat.FORMAT_ENCODED);
    }
    return this.formatOrderList;
  }

  private AsymmetricKeyPairFactory getKeyPairFactory(String format) {

    AsymmetricKeyPairFactory factory = this.format2factoryMap.get(format);
    if (factory == null) {
      if (CryptoBinaryFormat.FORMAT_COMPACT.equals(format)) {
        factory = this.format2factoryMap.get(CryptoBinaryFormat.FORMAT_ENCODED);
      }
      if (factory == null) {
        throw new IllegalArgumentException(format);
      }
    }
    return factory;
  }

  @Override
  public PR createPrivateKey(byte[] data, String format) {

    if (format == null) {
      for (String format2detect : getFormatOrderList()) {
        PR privateKey = createPrivateKey(data, format2detect);
        if (privateKey != null) {
          return privateKey;
        }
      }
      throw new IllegalStateException();
    }
    return getKeyPairFactory(format).createPrivateKey(data);
  }

  @Override
  public byte[] asData(PR privateKey, String format) {

    return getKeyPairFactory(format).asData(privateKey);
  }

  @Override
  public PU createPublicKey(byte[] data, String format) {

    if (format == null) {
      for (String format2detect : getFormatOrderList()) {
        PU publicKey = createPublicKey(data, format2detect);
        if (publicKey != null) {
          return publicKey;
        }
      }
      throw new IllegalStateException();
    }
    return getKeyPairFactory(format).createPublicKey(data);
  }

  @Override
  public byte[] asData(PU publicKey, String format) {

    return getKeyPairFactory(format).asData(publicKey);
  }

  @Override
  public PAIR createKeyPair(byte[] data, String format) {

    if (format == null) {
      for (String format2detect : getFormatOrderList()) {
        PAIR keyPair = createKeyPair(data, format2detect);
        if (keyPair != null) {
          return keyPair;
        }
      }
      throw new IllegalStateException();
    }
    return getKeyPairFactory(format).createKeyPair(data);
  }

  @Override
  public byte[] asData(PAIR keyPair, String format) {

    return getKeyPairFactory(format).asData(keyPair);
  }

  @SuppressWarnings("unchecked")
  @Override
  public PAIR generateKeyPair() {

    try {
      KeyPairGenerator keyPairGenerator = getProvider().createKeyPairGenerator(getAlgorithm());
      init(keyPairGenerator);
      KeyPair key = keyPairGenerator.generateKeyPair();
      PR privateKey = (PR) key.getPrivate();
      PU publicKey = (PU) key.getPublic();
      return createKeyPair(privateKey, publicKey);
    } catch (Exception e) {
      throw creationFailedException(e, KeyPair.class);
    }
  }

  /**
   * @param keyPairGenerator the {@link KeyPairGenerator} to {@link KeyPairGenerator#initialize(int) initialize}.
   * @throws Exception on error.
   */
  protected void init(KeyPairGenerator keyPairGenerator) throws Exception {

    keyPairGenerator.initialize(this.keyLength, createSecureRandom());
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy