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

net.sf.mmm.crypto.asymmetric.sign.SignatureAlgorithm Maven / Gradle / Ivy

The newest version!
package net.sf.mmm.crypto.asymmetric.sign;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import net.sf.mmm.crypto.algorithm.CryptoAlgorithm;
import net.sf.mmm.crypto.hash.HashConfig;

/**
 * Little helper to workaround quirks in JCE/JCA for {@link java.security.Signature#getAlgorithm() signature algorithm}
 * names.
 *
 * @since 1.0.0
 */
public final class SignatureAlgorithm implements CryptoAlgorithm {

  private static final String SEPARATOR = "with";

  private static final Map DIGEST2SIGNATURE_MAP = new HashMap<>();

  private static final Map SIGNATURE2DIGEST_MAP = new HashMap<>();

  static {
    register("SHA-224");
    register("SHA-256");
    register("SHA-384");
    register("SHA-512");
    register("SHA-512/224");
    register("SHA-512/256");
  }

  private final String hashAlgorithm;

  private final String signingAlgorithm;

  private final String algorithm;

  private SignatureAlgorithm(String hashAlgorithm, String signingAlgorithm, String algorithm) {

    super();
    this.hashAlgorithm = hashAlgorithm;
    this.signingAlgorithm = signingAlgorithm;
    this.algorithm = algorithm;
  }

  private static void register(String digest) {

    register(digest, digest.replace("SHA-", "SHA"));
  }

  private static void register(String digest, String signaturePrefix) {

    DIGEST2SIGNATURE_MAP.put(digest, signaturePrefix);
    SIGNATURE2DIGEST_MAP.put(signaturePrefix, digest);
  }

  private static String require(String value, String name) {

    if ((value == null) || value.isEmpty()) {
      throw new IllegalArgumentException("Value for " + name + " is required and must not be '" + value + "'!");
    }
    return value;
  }

  @Override
  public String getAlgorithm() {

    return this.algorithm;
  }

  /**
   * @return the hash algorithm to perform of the message payload before signing.
   */
  public String getHashAlgorithm() {

    return this.hashAlgorithm;
  }

  /**
   * @return {@code true} if {@link #getHashAlgorithm() hash algorithm} is {@link HashConfig#ALGORITHM_NONE
   *         NONE}.
   */
  public boolean isNoHashing() {

    return HashConfig.ALGORITHM_NONE.equals(this.hashAlgorithm);
  }

  /**
   * @return the raw signing algorithm (e.g. RSA, DSA, or ECDSA).
   */
  public String getSigningAlgorithm() {

    return this.signingAlgorithm;
  }

  @Override
  public int hashCode() {

    return this.algorithm.hashCode();
  }

  @Override
  public boolean equals(Object obj) {

    if (this == obj) {
      return true;
    }
    if ((obj == null) || (getClass() != obj.getClass())) {
      return false;
    }
    SignatureAlgorithm other = (SignatureAlgorithm) obj;
    if (!Objects.equals(this.algorithm, other.algorithm)) {
      return false;
    }
    return true;
  }

  @Override
  public String toString() {

    return this.algorithm;
  }

  /**
   * @param hashAlgorithm the {@link #getHashAlgorithm()}.
   * @param signingAlgorithm the {@link #getSigningAlgorithm()}.
   * @return the {@link SignatureAlgorithm} instance.
   */
  public static SignatureAlgorithm of(String hashAlgorithm, String signingAlgorithm) {

    register(signingAlgorithm, "signingAlgorithm");
    String algorithm;
    if (hashAlgorithm == null) {
      algorithm = signingAlgorithm;
    } else {
      algorithm = hash2sign(hashAlgorithm) + SEPARATOR + signingAlgorithm;
    }
    return new SignatureAlgorithm(hashAlgorithm, signingAlgorithm, algorithm);
  }

  private static String hash2sign(String hashingAlgorithm) {

    String signaturePrefix = DIGEST2SIGNATURE_MAP.get(hashingAlgorithm);
    if (signaturePrefix != null) {
      return signaturePrefix;
    }
    return hashingAlgorithm;
  }

  /**
   * @param algorithm the {@link #getAlgorithm() signature algorithm}.
   * @return the {@link SignatureAlgorithm} instance.
   */
  public static SignatureAlgorithm of(String algorithm) {

    require(algorithm, "algorithm");
    int separatorStartIndex = algorithm.indexOf(SEPARATOR);
    String hashAlgorithm;
    String signingAlgorithm;
    String signatureAlgorithm;
    if (separatorStartIndex < 0) {
      hashAlgorithm = null;
      signingAlgorithm = algorithm;
      signatureAlgorithm = algorithm;
    } else {
      assert (separatorStartIndex > 0);
      hashAlgorithm = sign2hash(algorithm.substring(0, separatorStartIndex));
      signingAlgorithm = algorithm.substring(separatorStartIndex + SEPARATOR.length());
      signatureAlgorithm = hash2sign(hashAlgorithm) + SEPARATOR + signingAlgorithm;
    }
    return new SignatureAlgorithm(hashAlgorithm, signingAlgorithm, signatureAlgorithm);
  }

  private static String sign2hash(String signaturePrefix) {

    String hashing = SIGNATURE2DIGEST_MAP.get(signaturePrefix);
    if (hashing != null) {
      return hashing;
    }
    return signaturePrefix;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy