SHA1.java
- /*
- * Copyright (C) 2022, Matthias Sohn <matthias.sohn@sap.com> and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- package org.eclipse.jgit.util.sha1;
- import java.io.IOException;
- import java.security.MessageDigest;
- import org.eclipse.jgit.errors.ConfigInvalidException;
- import org.eclipse.jgit.lib.ConfigConstants;
- import org.eclipse.jgit.lib.MutableObjectId;
- import org.eclipse.jgit.lib.ObjectId;
- import org.eclipse.jgit.util.SystemReader;
- /**
- * SHA-1 interface from FIPS 180-1 / RFC 3174 with optional collision detection.
- * Some implementations may not support collision detection.
- * <p>
- * See <a href="https://tools.ietf.org/html/rfc3174">RFC 3174</a>.
- */
- public abstract class SHA1 {
- /**
- * SHA1 implementations available in JGit
- *
- * @since 5.13.2
- */
- public enum Sha1Implementation {
- /**
- * {@link SHA1Java} implemented in Java, supports collision detection.
- */
- JAVA(SHA1Java.class),
- /**
- * Native implementation based on JDK's {@link MessageDigest}.
- */
- JDKNATIVE(SHA1Native.class);
- private final String implClassName;
- private Sha1Implementation(Class implClass) {
- this.implClassName = implClass.getName();
- }
- @Override
- public String toString() {
- return implClassName;
- }
- }
- private static final Sha1Implementation SHA1_IMPLEMENTATION = fromConfig();
- private static Sha1Implementation fromConfig() {
- try {
- return SystemReader.getInstance().getUserConfig().getEnum(
- ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.SHA1_IMPLEMENTATION,
- Sha1Implementation.JAVA);
- } catch (ConfigInvalidException | IOException e) {
- return Sha1Implementation.JAVA;
- }
- }
- private static Sha1Implementation getImplementation() {
- String fromSystemProperty = System
- .getProperty("org.eclipse.jgit.util.sha1.implementation"); //$NON-NLS-1$
- if (fromSystemProperty == null) {
- return SHA1_IMPLEMENTATION;
- }
- if (fromSystemProperty
- .equalsIgnoreCase(Sha1Implementation.JAVA.name())) {
- return Sha1Implementation.JAVA;
- }
- if (fromSystemProperty
- .equalsIgnoreCase(Sha1Implementation.JDKNATIVE.name())) {
- return Sha1Implementation.JDKNATIVE;
- }
- return SHA1_IMPLEMENTATION;
- }
- /**
- * Create a new context to compute a SHA-1 hash of data.
- * <p>
- * If {@code core.sha1Implementation = jdkNative} in the user level global
- * git configuration or the system property
- * {@code org.eclipse.jgit.util.sha1.implementation = jdkNative} it will
- * create an object using the implementation in the JDK. If both are set the
- * system property takes precedence. Otherwise the pure Java implementation
- * will be used which supports collision detection but is slower.
- *
- * @return a new context to compute a SHA-1 hash of data.
- */
- public static SHA1 newInstance() {
- if (getImplementation() == Sha1Implementation.JDKNATIVE) {
- return new SHA1Native();
- }
- return new SHA1Java();
- }
- /**
- * Update the digest computation by adding a byte.
- *
- * @param b a byte.
- */
- public abstract void update(byte b);
- /**
- * Update the digest computation by adding bytes to the message.
- *
- * @param in
- * input array of bytes.
- */
- public abstract void update(byte[] in);
- /**
- * Update the digest computation by adding bytes to the message.
- *
- * @param in
- * input array of bytes.
- * @param p
- * offset to start at from {@code in}.
- * @param len
- * number of bytes to hash.
- */
- public abstract void update(byte[] in, int p, int len);
- /**
- * Finish the digest and return the resulting hash.
- * <p>
- * Once {@code digest()} is called, this instance should be discarded.
- *
- * @return the bytes for the resulting hash.
- * @throws org.eclipse.jgit.util.sha1.Sha1CollisionException
- * if a collision was detected and safeHash is false.
- */
- public abstract byte[] digest() throws Sha1CollisionException;
- /**
- * Finish the digest and return the resulting hash.
- * <p>
- * Once {@code digest()} is called, this instance should be discarded.
- *
- * @return the ObjectId for the resulting hash.
- * @throws org.eclipse.jgit.util.sha1.Sha1CollisionException
- * if a collision was detected and safeHash is false.
- */
- public abstract ObjectId toObjectId() throws Sha1CollisionException;
- /**
- * Finish the digest and return the resulting hash.
- * <p>
- * Once {@code digest()} is called, this instance should be discarded.
- *
- * @param id
- * destination to copy the digest to.
- * @throws org.eclipse.jgit.util.sha1.Sha1CollisionException
- * if a collision was detected and safeHash is false.
- */
- public abstract void digest(MutableObjectId id)
- throws Sha1CollisionException;
- /**
- * Reset this instance to compute another hash.
- *
- * @return {@code this}.
- */
- public abstract SHA1 reset();
- /**
- * Enable likely collision detection.
- * <p>
- * Default for implementations supporting collision detection is
- * {@code true}.
- * <p>
- * Implementations not supporting collision detection ignore calls to this
- * method.
- *
- * @param detect
- * a boolean.
- * @return {@code this}
- */
- public abstract SHA1 setDetectCollision(boolean detect);
- /**
- * Check if a collision was detected. This method only returns an accurate
- * result after the digest was obtained through {@link #digest()},
- * {@link #digest(MutableObjectId)} or {@link #toObjectId()}, as the hashing
- * function must finish processing to know the final state.
- * <p>
- * Implementations not supporting collision detection always return
- * {@code false}.
- * <p>
- *
- * @return {@code true} if a likely collision was detected.
- */
- public abstract boolean hasCollision();
- }