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

io.github.mmm.crypto.asymmetric.key.rsa.AsymmetricKeyPairFactoryRsaCompact Maven / Gradle / Ivy

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

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import io.github.mmm.crypto.CryptoBinaryFormat;
import io.github.mmm.crypto.asymmetric.key.AbstractAsymmetricKeyPairFactory;

/**
 * Implementation of {@link AbstractAsymmetricKeyPairFactory} for RSA in
 * {@link CryptoBinaryFormat#FORMAT_COMPACT compact format}.
 *
 * @since 1.0.0
 */
public class AsymmetricKeyPairFactoryRsaCompact
    extends AbstractAsymmetricKeyPairFactory {

  private static final byte BYTE_OFFSET = 8;

  private static final int[] BYTE2POWER = new int[128];

  private static final byte[] HEADER_ENCODED_PUBLIC_KEY = new byte[] { 48, -126, 2, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1,
  5, 0, 3, -126, 2, 15, 0, 48, -126, 2, 10, 2, -126, 2, 1, 0 };

  static {
    int power = 1 << BYTE_OFFSET;
    for (int i = 0; i < BYTE2POWER.length; i++) {
      BYTE2POWER[i] = power;
      power = power + power;
    }
  }

  /**
   * The constructor.
   */
  public AsymmetricKeyPairFactoryRsaCompact() {

    super(AsymmetricKeyPairRsa.getKeyFactory());
  }

  /**
   * The constructor.
   *
   * @param keyFactory the {@link KeyFactory}.
   */
  public AsymmetricKeyPairFactoryRsaCompact(KeyFactory keyFactory) {

    super(keyFactory);
  }

  private Byte length2byte(int length) {

    for (byte i = 0; i < BYTE2POWER.length; i++) {
      int power = BYTE2POWER[i];
      if (power == length) {
        return Byte.valueOf(i);
      } else if (power > length) {
        break;
      }
    }
    return null;
  }

  @Override
  public byte[] asData(RSAPrivateKey privateKey) {

    BigInteger modulus = privateKey.getModulus();
    BigInteger privateExponent = privateKey.getPrivateExponent();
    byte[] modulusBytes = modulus.toByteArray();
    byte[] privateExponentBytes = privateExponent.toByteArray();
    int length = modulusBytes.length + privateExponentBytes.length;
    byte[] data = new byte[length];
    Byte modulusLength = length2byte(modulusBytes.length - 1);
    if (modulusLength == null) {
      throw new IllegalStateException("Not implemented for bit-length " + modulus.bitLength() + " that is not a power of 2!");
    }
    data[0] = modulusLength.byteValue();
    System.arraycopy(modulusBytes, 1, data, 1, modulusBytes.length - 1);
    System.arraycopy(privateExponentBytes, 0, data, modulusBytes.length, privateExponentBytes.length);
    return data;
  }

  @Override
  public RSAPrivateKey createPrivateKey(byte[] data) {

    int modulusLengthByte = data[0];
    if (modulusLengthByte >= BYTE2POWER.length) {
      throw new IllegalArgumentException("Invalid encoded modulus length: " + modulusLengthByte);
    }
    int modulusLength = BYTE2POWER[modulusLengthByte];
    if (modulusLength == 0) { // TODO
      return null;
    }
    byte[] modulusBytes = new byte[modulusLength];
    System.arraycopy(data, 1, modulusBytes, 0, modulusLength);
    BigInteger modulus = new BigInteger(1, modulusBytes);
    int privateExponentLength = data.length - modulusLength - 1;
    byte[] privateExponentBytes = new byte[privateExponentLength];
    System.arraycopy(data, modulusLength + 1, privateExponentBytes, 0, privateExponentLength);
    BigInteger privateExponent = new BigInteger(privateExponentBytes);
    return AsymmetricKeyPairRsa.createPrivateKey(modulus, privateExponent);
  }

  @Override
  public byte[] asData(RSAPublicKey publicKey) {

    BigInteger publicExponent = publicKey.getPublicExponent();
    boolean defaultPublicExponent = publicExponent.equals(AsymmetricKeyPairRsa.PUBLIC_EXPONENT);
    if (!defaultPublicExponent) {
      throw new IllegalStateException("Not implemented for non-default public exponent!");
    }
    byte[] data = publicKey.getModulus().toByteArray();
    return data;
  }

  @Override
  public RSAPublicKey createPublicKey(byte[] data) {

    //
    if (data.length > HEADER_ENCODED_PUBLIC_KEY.length) {
      boolean headerMatch = true;
      for (int i = 0; i < HEADER_ENCODED_PUBLIC_KEY.length; i++) {
        if (data[i] != HEADER_ENCODED_PUBLIC_KEY[i]) {
          headerMatch = false;
          break;
        }
      }
      if (headerMatch) {
        return null;
      }
    }
    BigInteger modulus = new BigInteger(data);
    return AsymmetricKeyPairRsa.createPublicKey(modulus);
  }

  @Override
  public byte[] asData(AsymmetricKeyPairRsa keyPair) {

    BigInteger publicExponent = keyPair.getPublicKey().getPublicExponent();
    boolean defaultPublicExponent = publicExponent.equals(AsymmetricKeyPairRsa.PUBLIC_EXPONENT);
    if (!defaultPublicExponent) {
      throw new IllegalStateException("Not implemented for non-default public exponent!");
    }
    return asData(keyPair.getPrivateKey());
  }

  @Override
  public AsymmetricKeyPairRsa createKeyPair(byte[] data) {

    RSAPrivateKey privateKey = createPrivateKey(data);
    RSAPublicKey publicKey = AsymmetricKeyPairRsa.createPublicKey(privateKey.getModulus());
    return new AsymmetricKeyPairRsa(privateKey, publicKey);
  }

  @Override
  public AsymmetricKeyPairRsa createKeyPair(RSAPrivateKey privateKey, RSAPublicKey publicKey) {

    return new AsymmetricKeyPairRsa(privateKey, publicKey);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy