Merge "SHA-1: collision detection support"
This commit is contained in:
commit
45f62576de
Binary file not shown.
Binary file not shown.
|
@ -44,12 +44,20 @@
|
||||||
package org.eclipse.jgit.util.sha1;
|
package org.eclipse.jgit.util.sha1;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.util.IO;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class SHA1Test {
|
public class SHA1Test {
|
||||||
|
@ -124,4 +132,107 @@ public void test2() throws NoSuchAlgorithmException {
|
||||||
assertEquals(exp, s1);
|
assertEquals(exp, s1);
|
||||||
assertEquals(exp, s2);
|
assertEquals(exp, s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shatteredCollision()
|
||||||
|
throws IOException, NoSuchAlgorithmException {
|
||||||
|
byte[] pdf1 = read("shattered-1.pdf", 422435);
|
||||||
|
byte[] pdf2 = read("shattered-2.pdf", 422435);
|
||||||
|
MessageDigest md;
|
||||||
|
SHA1 s;
|
||||||
|
|
||||||
|
// SHAttered attack generated these PDFs to have identical SHA-1.
|
||||||
|
ObjectId bad = ObjectId
|
||||||
|
.fromString("38762cf7f55934b34d179ae6a4c80cadccbb7f0a");
|
||||||
|
md = MessageDigest.getInstance("SHA-1");
|
||||||
|
md.update(pdf1);
|
||||||
|
assertEquals("shattered-1 collides", bad,
|
||||||
|
ObjectId.fromRaw(md.digest()));
|
||||||
|
s = SHA1.newInstance().setDetectCollision(false);
|
||||||
|
s.update(pdf1);
|
||||||
|
assertEquals("shattered-1 collides", bad, s.toObjectId());
|
||||||
|
|
||||||
|
md = MessageDigest.getInstance("SHA-1");
|
||||||
|
md.update(pdf2);
|
||||||
|
assertEquals("shattered-2 collides", bad,
|
||||||
|
ObjectId.fromRaw(md.digest()));
|
||||||
|
s = SHA1.newInstance().setDetectCollision(false);
|
||||||
|
s.update(pdf2);
|
||||||
|
assertEquals("shattered-2 collides", bad, s.toObjectId());
|
||||||
|
|
||||||
|
// SHA1 with detectCollision shouldn't be fooled.
|
||||||
|
s = SHA1.newInstance().setDetectCollision(true);
|
||||||
|
s.update(pdf1);
|
||||||
|
try {
|
||||||
|
s.digest();
|
||||||
|
fail("expected " + Sha1CollisionException.class.getSimpleName());
|
||||||
|
} catch (Sha1CollisionException e) {
|
||||||
|
assertEquals(e.getMessage(),
|
||||||
|
"SHA-1 collision detected on " + bad.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
s = SHA1.newInstance().setDetectCollision(true);
|
||||||
|
s.update(pdf2);
|
||||||
|
try {
|
||||||
|
s.digest();
|
||||||
|
fail("expected " + Sha1CollisionException.class.getSimpleName());
|
||||||
|
} catch (Sha1CollisionException e) {
|
||||||
|
assertEquals(e.getMessage(),
|
||||||
|
"SHA-1 collision detected on " + bad.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shatteredStoredInGitBlob() throws IOException {
|
||||||
|
byte[] pdf1 = read("shattered-1.pdf", 422435);
|
||||||
|
byte[] pdf2 = read("shattered-2.pdf", 422435);
|
||||||
|
|
||||||
|
// Although the prior test detects the chance of a collision, adding
|
||||||
|
// the Git blob header permutes the data enough for this specific
|
||||||
|
// attack example to not be detected as a collision. (A different file
|
||||||
|
// pair that takes the Git header into account however, would.)
|
||||||
|
ObjectId id1 = blob(pdf1, SHA1.newInstance().setDetectCollision(true));
|
||||||
|
ObjectId id2 = blob(pdf2, SHA1.newInstance().setDetectCollision(true));
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
ObjectId.fromString("ba9aaa145ccd24ef760cf31c74d8f7ca1a2e47b0"),
|
||||||
|
id1);
|
||||||
|
assertEquals(
|
||||||
|
ObjectId.fromString("b621eeccd5c7edac9b7dcba35a8d5afd075e24f2"),
|
||||||
|
id2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void detectsShatteredByDefault() throws IOException {
|
||||||
|
assumeTrue(System.getProperty("org.eclipse.jgit.util.sha1.detectCollision") == null);
|
||||||
|
assumeTrue(System.getProperty("org.eclipse.jgit.util.sha1.safeHash") == null);
|
||||||
|
|
||||||
|
byte[] pdf1 = read("shattered-1.pdf", 422435);
|
||||||
|
SHA1 s = SHA1.newInstance();
|
||||||
|
s.update(pdf1);
|
||||||
|
try {
|
||||||
|
s.digest();
|
||||||
|
fail("expected " + Sha1CollisionException.class.getSimpleName());
|
||||||
|
} catch (Sha1CollisionException e) {
|
||||||
|
assertTrue("shattered-1 detected", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ObjectId blob(byte[] pdf1, SHA1 s) {
|
||||||
|
s.update(Constants.encodedTypeString(Constants.OBJ_BLOB));
|
||||||
|
s.update((byte) ' ');
|
||||||
|
s.update(Constants.encodeASCII(pdf1.length));
|
||||||
|
s.update((byte) 0);
|
||||||
|
s.update(pdf1);
|
||||||
|
return s.toObjectId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] read(String name, int sizeHint) throws IOException {
|
||||||
|
try (InputStream in = getClass().getResourceAsStream(name)) {
|
||||||
|
ByteBuffer buf = IO.readWholeStream(in, sizeHint);
|
||||||
|
byte[] r = new byte[buf.remaining()];
|
||||||
|
buf.get(r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
margin-top: 0.05em;
|
margin-top: 0.05em;
|
||||||
margin-bottom: 0.05em;
|
margin-bottom: 0.05em;
|
||||||
}
|
}
|
||||||
|
.ubc-name {
|
||||||
|
margin-left: 0.5in;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
@ -54,6 +58,39 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.</p>
|
POSSIBILITY OF SUCH DAMAGE.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<p><b>SHA-1 UbcCheck - MIT</b></p>
|
||||||
|
|
||||||
|
<p>Copyright (c) 2017:</p>
|
||||||
|
<div class="ubc-name">
|
||||||
|
Marc Stevens
|
||||||
|
Cryptology Group
|
||||||
|
Centrum Wiskunde & Informatica
|
||||||
|
P.O. Box 94079, 1090 GB Amsterdam, Netherlands
|
||||||
|
marc@marc-stevens.nl
|
||||||
|
</div>
|
||||||
|
<div class="ubc-name">
|
||||||
|
Dan Shumow
|
||||||
|
Microsoft Research
|
||||||
|
danshu@microsoft.com
|
||||||
|
</div>
|
||||||
|
<p>Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
</p>
|
||||||
|
<ul><li>The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.</li></ul>
|
||||||
|
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.</p>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -564,6 +564,7 @@ selectingCommits=Selecting commits
|
||||||
sequenceTooLargeForDiffAlgorithm=Sequence too large for difference algorithm.
|
sequenceTooLargeForDiffAlgorithm=Sequence too large for difference algorithm.
|
||||||
serviceNotEnabledNoName=Service not enabled
|
serviceNotEnabledNoName=Service not enabled
|
||||||
serviceNotPermitted={0} not permitted
|
serviceNotPermitted={0} not permitted
|
||||||
|
sha1CollisionDetected1=SHA-1 collision detected on {0}
|
||||||
shallowCommitsAlreadyInitialized=Shallow commits have already been initialized
|
shallowCommitsAlreadyInitialized=Shallow commits have already been initialized
|
||||||
shallowPacksRequireDepthWalk=Shallow packs require a DepthWalk
|
shallowPacksRequireDepthWalk=Shallow packs require a DepthWalk
|
||||||
shortCompressedStreamAt=Short compressed stream at {0}
|
shortCompressedStreamAt=Short compressed stream at {0}
|
||||||
|
|
|
@ -623,6 +623,7 @@ public static JGitText get() {
|
||||||
/***/ public String sequenceTooLargeForDiffAlgorithm;
|
/***/ public String sequenceTooLargeForDiffAlgorithm;
|
||||||
/***/ public String serviceNotEnabledNoName;
|
/***/ public String serviceNotEnabledNoName;
|
||||||
/***/ public String serviceNotPermitted;
|
/***/ public String serviceNotPermitted;
|
||||||
|
/***/ public String sha1CollisionDetected1;
|
||||||
/***/ public String shallowCommitsAlreadyInitialized;
|
/***/ public String shallowCommitsAlreadyInitialized;
|
||||||
/***/ public String shallowPacksRequireDepthWalk;
|
/***/ public String shallowPacksRequireDepthWalk;
|
||||||
/***/ public String shortCompressedStreamAt;
|
/***/ public String shortCompressedStreamAt;
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/* Template for compress method; run through cpp. */
|
||||||
|
|
||||||
|
#define ROUND1_STEP(a, b, c, d, e, T) e += s1(a,b,c,d,w[T]); b = rotateLeft(b, 30)
|
||||||
|
#define ROUND2_STEP(a, b, c, d, e, T) e += s2(a,b,c,d,w[T]); b = rotateLeft(b, 30)
|
||||||
|
#define ROUND3_STEP(a, b, c, d, e, T) e += s3(a,b,c,d,w[T]); b = rotateLeft(b, 30)
|
||||||
|
#define ROUND4_STEP(a, b, c, d, e, T) e += s4(a,b,c,d,w[T]); b = rotateLeft(b, 30)
|
||||||
|
|
||||||
|
ROUND1_STEP(a, b, c, d, e, 0);
|
||||||
|
ROUND1_STEP(e, a, b, c, d, 1);
|
||||||
|
ROUND1_STEP(d, e, a, b, c, 2);
|
||||||
|
ROUND1_STEP(c, d, e, a, b, 3);
|
||||||
|
ROUND1_STEP(b, c, d, e, a, 4);
|
||||||
|
ROUND1_STEP(a, b, c, d, e, 5);
|
||||||
|
ROUND1_STEP(e, a, b, c, d, 6);
|
||||||
|
ROUND1_STEP(d, e, a, b, c, 7);
|
||||||
|
ROUND1_STEP(c, d, e, a, b, 8);
|
||||||
|
ROUND1_STEP(b, c, d, e, a, 9);
|
||||||
|
ROUND1_STEP(a, b, c, d, e, 10);
|
||||||
|
ROUND1_STEP(e, a, b, c, d, 11);
|
||||||
|
ROUND1_STEP(d, e, a, b, c, 12);
|
||||||
|
ROUND1_STEP(c, d, e, a, b, 13);
|
||||||
|
ROUND1_STEP(b, c, d, e, a, 14);
|
||||||
|
ROUND1_STEP(a, b, c, d, e, 15);
|
||||||
|
ROUND1_STEP(e, a, b, c, d, 16);
|
||||||
|
ROUND1_STEP(d, e, a, b, c, 17);
|
||||||
|
ROUND1_STEP(c, d, e, a, b, 18);
|
||||||
|
ROUND1_STEP(b, c, d, e, a, 19);
|
||||||
|
|
||||||
|
ROUND2_STEP(a, b, c, d, e, 20);
|
||||||
|
ROUND2_STEP(e, a, b, c, d, 21);
|
||||||
|
ROUND2_STEP(d, e, a, b, c, 22);
|
||||||
|
ROUND2_STEP(c, d, e, a, b, 23);
|
||||||
|
ROUND2_STEP(b, c, d, e, a, 24);
|
||||||
|
ROUND2_STEP(a, b, c, d, e, 25);
|
||||||
|
ROUND2_STEP(e, a, b, c, d, 26);
|
||||||
|
ROUND2_STEP(d, e, a, b, c, 27);
|
||||||
|
ROUND2_STEP(c, d, e, a, b, 28);
|
||||||
|
ROUND2_STEP(b, c, d, e, a, 29);
|
||||||
|
ROUND2_STEP(a, b, c, d, e, 30);
|
||||||
|
ROUND2_STEP(e, a, b, c, d, 31);
|
||||||
|
ROUND2_STEP(d, e, a, b, c, 32);
|
||||||
|
ROUND2_STEP(c, d, e, a, b, 33);
|
||||||
|
ROUND2_STEP(b, c, d, e, a, 34);
|
||||||
|
ROUND2_STEP(a, b, c, d, e, 35);
|
||||||
|
ROUND2_STEP(e, a, b, c, d, 36);
|
||||||
|
ROUND2_STEP(d, e, a, b, c, 37);
|
||||||
|
ROUND2_STEP(c, d, e, a, b, 38);
|
||||||
|
ROUND2_STEP(b, c, d, e, a, 39);
|
||||||
|
|
||||||
|
ROUND3_STEP(a, b, c, d, e, 40);
|
||||||
|
ROUND3_STEP(e, a, b, c, d, 41);
|
||||||
|
ROUND3_STEP(d, e, a, b, c, 42);
|
||||||
|
ROUND3_STEP(c, d, e, a, b, 43);
|
||||||
|
ROUND3_STEP(b, c, d, e, a, 44);
|
||||||
|
ROUND3_STEP(a, b, c, d, e, 45);
|
||||||
|
ROUND3_STEP(e, a, b, c, d, 46);
|
||||||
|
ROUND3_STEP(d, e, a, b, c, 47);
|
||||||
|
ROUND3_STEP(c, d, e, a, b, 48);
|
||||||
|
ROUND3_STEP(b, c, d, e, a, 49);
|
||||||
|
ROUND3_STEP(a, b, c, d, e, 50);
|
||||||
|
ROUND3_STEP(e, a, b, c, d, 51);
|
||||||
|
ROUND3_STEP(d, e, a, b, c, 52);
|
||||||
|
ROUND3_STEP(c, d, e, a, b, 53);
|
||||||
|
ROUND3_STEP(b, c, d, e, a, 54);
|
||||||
|
ROUND3_STEP(a, b, c, d, e, 55);
|
||||||
|
ROUND3_STEP(e, a, b, c, d, 56);
|
||||||
|
ROUND3_STEP(d, e, a, b, c, 57);
|
||||||
|
state58.save(a, b, c, d, e);
|
||||||
|
ROUND3_STEP(c, d, e, a, b, 58);
|
||||||
|
ROUND3_STEP(b, c, d, e, a, 59);
|
||||||
|
|
||||||
|
ROUND4_STEP(a, b, c, d, e, 60);
|
||||||
|
ROUND4_STEP(e, a, b, c, d, 61);
|
||||||
|
ROUND4_STEP(d, e, a, b, c, 62);
|
||||||
|
ROUND4_STEP(c, d, e, a, b, 63);
|
||||||
|
ROUND4_STEP(b, c, d, e, a, 64);
|
||||||
|
state65.save(a, b, c, d, e);
|
||||||
|
ROUND4_STEP(a, b, c, d, e, 65);
|
||||||
|
ROUND4_STEP(e, a, b, c, d, 66);
|
||||||
|
ROUND4_STEP(d, e, a, b, c, 67);
|
||||||
|
ROUND4_STEP(c, d, e, a, b, 68);
|
||||||
|
ROUND4_STEP(b, c, d, e, a, 69);
|
||||||
|
ROUND4_STEP(a, b, c, d, e, 70);
|
||||||
|
ROUND4_STEP(e, a, b, c, d, 71);
|
||||||
|
ROUND4_STEP(d, e, a, b, c, 72);
|
||||||
|
ROUND4_STEP(c, d, e, a, b, 73);
|
||||||
|
ROUND4_STEP(b, c, d, e, a, 74);
|
||||||
|
ROUND4_STEP(a, b, c, d, e, 75);
|
||||||
|
ROUND4_STEP(e, a, b, c, d, 76);
|
||||||
|
ROUND4_STEP(d, e, a, b, c, 77);
|
||||||
|
ROUND4_STEP(c, d, e, a, b, 78);
|
||||||
|
ROUND4_STEP(b, c, d, e, a, 79);
|
|
@ -43,31 +43,54 @@
|
||||||
|
|
||||||
package org.eclipse.jgit.util.sha1;
|
package org.eclipse.jgit.util.sha1;
|
||||||
|
|
||||||
|
import static java.lang.Integer.lowestOneBit;
|
||||||
|
import static java.lang.Integer.numberOfTrailingZeros;
|
||||||
|
import static java.lang.Integer.rotateLeft;
|
||||||
|
import static java.lang.Integer.rotateRight;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.MutableObjectId;
|
import org.eclipse.jgit.lib.MutableObjectId;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.util.NB;
|
import org.eclipse.jgit.util.NB;
|
||||||
|
import org.eclipse.jgit.util.SystemReader;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure Java implementation of SHA-1 from FIPS 180-1 / RFC 3174.
|
* Pure Java implementation of SHA-1 from FIPS 180-1 / RFC 3174.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="https://tools.ietf.org/html/rfc3174">RFC 3174</a>.
|
* See <a href="https://tools.ietf.org/html/rfc3174">RFC 3174</a>.
|
||||||
|
* <p>
|
||||||
|
* Unlike MessageDigest, this implementation includes the algorithm used by
|
||||||
|
* {@code sha1dc} to detect cryptanalytic collision attacks against SHA-1, such
|
||||||
|
* as the one used by <a href="https://shattered.it/">SHAttered</a>. See
|
||||||
|
* <a href="https://github.com/cr-marcstevens/sha1collisiondetection">
|
||||||
|
* sha1collisiondetection</a> for more information.
|
||||||
|
* <p>
|
||||||
|
* When detectCollision is true (default), this implementation throws
|
||||||
|
* {@link Sha1CollisionException} from any digest method if a potential
|
||||||
|
* collision was detected.
|
||||||
*
|
*
|
||||||
* @since 4.7
|
* @since 4.7
|
||||||
*/
|
*/
|
||||||
public class SHA1 {
|
public class SHA1 {
|
||||||
|
private static Logger LOG = LoggerFactory.getLogger(SHA1.class);
|
||||||
|
private static final boolean DETECT_COLLISIONS;
|
||||||
|
|
||||||
|
static {
|
||||||
|
SystemReader sr = SystemReader.getInstance();
|
||||||
|
String v = sr.getProperty("org.eclipse.jgit.util.sha1.detectCollision"); //$NON-NLS-1$
|
||||||
|
DETECT_COLLISIONS = v != null ? Boolean.parseBoolean(v) : true;
|
||||||
|
}
|
||||||
|
|
||||||
/** @return a new context to compute a SHA-1 hash of data. */
|
/** @return a new context to compute a SHA-1 hash of data. */
|
||||||
public static SHA1 newInstance() {
|
public static SHA1 newInstance() {
|
||||||
return new SHA1();
|
return new SHA1();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int h0;
|
private final State h = new State();
|
||||||
private int h1;
|
|
||||||
private int h2;
|
|
||||||
private int h3;
|
|
||||||
private int h4;
|
|
||||||
private final int[] w = new int[80];
|
private final int[] w = new int[80];
|
||||||
|
|
||||||
/** Buffer to accumulate partial blocks to 64 byte alignment. */
|
/** Buffer to accumulate partial blocks to 64 byte alignment. */
|
||||||
|
@ -76,30 +99,35 @@ public static SHA1 newInstance() {
|
||||||
/** Total number of bytes in the message. */
|
/** Total number of bytes in the message. */
|
||||||
private long length;
|
private long length;
|
||||||
|
|
||||||
|
private boolean detectCollision = DETECT_COLLISIONS;
|
||||||
|
private boolean foundCollision;
|
||||||
|
|
||||||
|
private final int[] w2 = new int[80];
|
||||||
|
private final State state58 = new State();
|
||||||
|
private final State state65 = new State();
|
||||||
|
private final State hIn = new State();
|
||||||
|
private final State hTmp = new State();
|
||||||
|
|
||||||
private SHA1() {
|
private SHA1() {
|
||||||
init();
|
h.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset this instance to compute another hash.
|
* Enable likely collision detection.
|
||||||
|
* <p>
|
||||||
|
* Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* May also be set by system property:
|
||||||
|
* {@code -Dorg.eclipse.jgit.util.sha1.detectCollision=true}.
|
||||||
*
|
*
|
||||||
* @return {@code this}.
|
* @param detect
|
||||||
|
* @return {@code this}
|
||||||
*/
|
*/
|
||||||
public SHA1 reset() {
|
public SHA1 setDetectCollision(boolean detect) {
|
||||||
init();
|
detectCollision = detect;
|
||||||
length = 0;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
|
||||||
// Magic initialization constants defined by FIPS180.
|
|
||||||
h0 = 0x67452301;
|
|
||||||
h1 = 0xEFCDAB89;
|
|
||||||
h2 = 0x98BADCFE;
|
|
||||||
h3 = 0x10325476;
|
|
||||||
h4 = 0xC3D2E1F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the digest computation by adding a byte.
|
* Update the digest computation by adding a byte.
|
||||||
*
|
*
|
||||||
|
@ -161,83 +189,283 @@ public void update(byte[] in, int p, int len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compress(byte[] block, int p) {
|
private void compress(byte[] block, int p) {
|
||||||
// Method 1 from RFC 3174 section 6.1.
|
initBlock(block, p);
|
||||||
// Method 2 (circular queue of 16 words) is slower.
|
int ubcDvMask = detectCollision ? UbcCheck.check(w) : 0;
|
||||||
int a = h0, b = h1, c = h2, d = h3, e = h4;
|
compress();
|
||||||
|
|
||||||
// Round 1: 0 <= t <= 15 comes from the input block.
|
while (ubcDvMask != 0) {
|
||||||
|
int b = numberOfTrailingZeros(lowestOneBit(ubcDvMask));
|
||||||
|
UbcCheck.DvInfo dv = UbcCheck.DV[b];
|
||||||
|
for (int i = 0; i < 80; i++) {
|
||||||
|
w2[i] = w[i] ^ dv.dm[i];
|
||||||
|
}
|
||||||
|
recompress(dv.testt);
|
||||||
|
if (eq(hTmp, h)) {
|
||||||
|
foundCollision = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ubcDvMask &= ~(1 << b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initBlock(byte[] block, int p) {
|
||||||
for (int t = 0; t < 16; t++) {
|
for (int t = 0; t < 16; t++) {
|
||||||
int temp = NB.decodeInt32(block, p + (t << 2));
|
w[t] = NB.decodeInt32(block, p + (t << 2));
|
||||||
w[t] = temp;
|
|
||||||
temp += ((a << 5) | (a >>> 27)) // S^5(A)
|
|
||||||
+ (((c ^ d) & b) ^ d) // f: 0 <= t <= 19
|
|
||||||
+ e + 0x5A827999;
|
|
||||||
e = d;
|
|
||||||
d = c;
|
|
||||||
c = (b << 30) | (b >>> 2); // S^30(B)
|
|
||||||
b = a;
|
|
||||||
a = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC 3174 6.1.b, extend state vector to 80 words.
|
// RFC 3174 6.1.b, extend state vector to 80 words.
|
||||||
for (int t = 16; t < 80; t++) {
|
for (int t = 16; t < 80; t++) {
|
||||||
int x = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];
|
int x = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];
|
||||||
w[t] = (x << 1) | (x >>> 31); // S^1(...)
|
w[t] = rotateLeft(x, 1); // S^1(...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round 1: tail
|
private void compress() {
|
||||||
for (int t = 16; t < 20; t++) {
|
// Method 1 from RFC 3174 section 6.1.
|
||||||
int temp = ((a << 5) | (a >>> 27)) // S^5(A)
|
// Method 2 (circular queue of 16 words) is slower.
|
||||||
+ (((c ^ d) & b) ^ d) // f: 0 <= t <= 19
|
int a = h.a, b = h.b, c = h.c, d = h.d, e = h.e;
|
||||||
+ e + w[t] + 0x5A827999;
|
|
||||||
e = d;
|
// @formatter:off
|
||||||
d = c;
|
e += s1(a, b, c, d,w[ 0]); b = rotateLeft( b, 30);
|
||||||
c = (b << 30) | (b >>> 2); // S^30(B)
|
d += s1(e, a, b, c,w[ 1]); a = rotateLeft( a, 30);
|
||||||
b = a;
|
c += s1(d, e, a, b,w[ 2]); e = rotateLeft( e, 30);
|
||||||
a = temp;
|
b += s1(c, d, e, a,w[ 3]); d = rotateLeft( d, 30);
|
||||||
|
a += s1(b, c, d, e,w[ 4]); c = rotateLeft( c, 30);
|
||||||
|
e += s1(a, b, c, d,w[ 5]); b = rotateLeft( b, 30);
|
||||||
|
d += s1(e, a, b, c,w[ 6]); a = rotateLeft( a, 30);
|
||||||
|
c += s1(d, e, a, b,w[ 7]); e = rotateLeft( e, 30);
|
||||||
|
b += s1(c, d, e, a,w[ 8]); d = rotateLeft( d, 30);
|
||||||
|
a += s1(b, c, d, e,w[ 9]); c = rotateLeft( c, 30);
|
||||||
|
e += s1(a, b, c, d,w[ 10]); b = rotateLeft( b, 30);
|
||||||
|
d += s1(e, a, b, c,w[ 11]); a = rotateLeft( a, 30);
|
||||||
|
c += s1(d, e, a, b,w[ 12]); e = rotateLeft( e, 30);
|
||||||
|
b += s1(c, d, e, a,w[ 13]); d = rotateLeft( d, 30);
|
||||||
|
a += s1(b, c, d, e,w[ 14]); c = rotateLeft( c, 30);
|
||||||
|
e += s1(a, b, c, d,w[ 15]); b = rotateLeft( b, 30);
|
||||||
|
d += s1(e, a, b, c,w[ 16]); a = rotateLeft( a, 30);
|
||||||
|
c += s1(d, e, a, b,w[ 17]); e = rotateLeft( e, 30);
|
||||||
|
b += s1(c, d, e, a,w[ 18]); d = rotateLeft( d, 30);
|
||||||
|
a += s1(b, c, d, e,w[ 19]); c = rotateLeft( c, 30);
|
||||||
|
|
||||||
|
e += s2(a, b, c, d,w[ 20]); b = rotateLeft( b, 30);
|
||||||
|
d += s2(e, a, b, c,w[ 21]); a = rotateLeft( a, 30);
|
||||||
|
c += s2(d, e, a, b,w[ 22]); e = rotateLeft( e, 30);
|
||||||
|
b += s2(c, d, e, a,w[ 23]); d = rotateLeft( d, 30);
|
||||||
|
a += s2(b, c, d, e,w[ 24]); c = rotateLeft( c, 30);
|
||||||
|
e += s2(a, b, c, d,w[ 25]); b = rotateLeft( b, 30);
|
||||||
|
d += s2(e, a, b, c,w[ 26]); a = rotateLeft( a, 30);
|
||||||
|
c += s2(d, e, a, b,w[ 27]); e = rotateLeft( e, 30);
|
||||||
|
b += s2(c, d, e, a,w[ 28]); d = rotateLeft( d, 30);
|
||||||
|
a += s2(b, c, d, e,w[ 29]); c = rotateLeft( c, 30);
|
||||||
|
e += s2(a, b, c, d,w[ 30]); b = rotateLeft( b, 30);
|
||||||
|
d += s2(e, a, b, c,w[ 31]); a = rotateLeft( a, 30);
|
||||||
|
c += s2(d, e, a, b,w[ 32]); e = rotateLeft( e, 30);
|
||||||
|
b += s2(c, d, e, a,w[ 33]); d = rotateLeft( d, 30);
|
||||||
|
a += s2(b, c, d, e,w[ 34]); c = rotateLeft( c, 30);
|
||||||
|
e += s2(a, b, c, d,w[ 35]); b = rotateLeft( b, 30);
|
||||||
|
d += s2(e, a, b, c,w[ 36]); a = rotateLeft( a, 30);
|
||||||
|
c += s2(d, e, a, b,w[ 37]); e = rotateLeft( e, 30);
|
||||||
|
b += s2(c, d, e, a,w[ 38]); d = rotateLeft( d, 30);
|
||||||
|
a += s2(b, c, d, e,w[ 39]); c = rotateLeft( c, 30);
|
||||||
|
|
||||||
|
e += s3(a, b, c, d,w[ 40]); b = rotateLeft( b, 30);
|
||||||
|
d += s3(e, a, b, c,w[ 41]); a = rotateLeft( a, 30);
|
||||||
|
c += s3(d, e, a, b,w[ 42]); e = rotateLeft( e, 30);
|
||||||
|
b += s3(c, d, e, a,w[ 43]); d = rotateLeft( d, 30);
|
||||||
|
a += s3(b, c, d, e,w[ 44]); c = rotateLeft( c, 30);
|
||||||
|
e += s3(a, b, c, d,w[ 45]); b = rotateLeft( b, 30);
|
||||||
|
d += s3(e, a, b, c,w[ 46]); a = rotateLeft( a, 30);
|
||||||
|
c += s3(d, e, a, b,w[ 47]); e = rotateLeft( e, 30);
|
||||||
|
b += s3(c, d, e, a,w[ 48]); d = rotateLeft( d, 30);
|
||||||
|
a += s3(b, c, d, e,w[ 49]); c = rotateLeft( c, 30);
|
||||||
|
e += s3(a, b, c, d,w[ 50]); b = rotateLeft( b, 30);
|
||||||
|
d += s3(e, a, b, c,w[ 51]); a = rotateLeft( a, 30);
|
||||||
|
c += s3(d, e, a, b,w[ 52]); e = rotateLeft( e, 30);
|
||||||
|
b += s3(c, d, e, a,w[ 53]); d = rotateLeft( d, 30);
|
||||||
|
a += s3(b, c, d, e,w[ 54]); c = rotateLeft( c, 30);
|
||||||
|
e += s3(a, b, c, d,w[ 55]); b = rotateLeft( b, 30);
|
||||||
|
d += s3(e, a, b, c,w[ 56]); a = rotateLeft( a, 30);
|
||||||
|
c += s3(d, e, a, b,w[ 57]); e = rotateLeft( e, 30);
|
||||||
|
state58.save(a, b, c, d, e);
|
||||||
|
b += s3(c, d, e, a,w[ 58]); d = rotateLeft( d, 30);
|
||||||
|
a += s3(b, c, d, e,w[ 59]); c = rotateLeft( c, 30);
|
||||||
|
|
||||||
|
e += s4(a, b, c, d,w[ 60]); b = rotateLeft( b, 30);
|
||||||
|
d += s4(e, a, b, c,w[ 61]); a = rotateLeft( a, 30);
|
||||||
|
c += s4(d, e, a, b,w[ 62]); e = rotateLeft( e, 30);
|
||||||
|
b += s4(c, d, e, a,w[ 63]); d = rotateLeft( d, 30);
|
||||||
|
a += s4(b, c, d, e,w[ 64]); c = rotateLeft( c, 30);
|
||||||
|
state65.save(a, b, c, d, e);
|
||||||
|
e += s4(a, b, c, d,w[ 65]); b = rotateLeft( b, 30);
|
||||||
|
d += s4(e, a, b, c,w[ 66]); a = rotateLeft( a, 30);
|
||||||
|
c += s4(d, e, a, b,w[ 67]); e = rotateLeft( e, 30);
|
||||||
|
b += s4(c, d, e, a,w[ 68]); d = rotateLeft( d, 30);
|
||||||
|
a += s4(b, c, d, e,w[ 69]); c = rotateLeft( c, 30);
|
||||||
|
e += s4(a, b, c, d,w[ 70]); b = rotateLeft( b, 30);
|
||||||
|
d += s4(e, a, b, c,w[ 71]); a = rotateLeft( a, 30);
|
||||||
|
c += s4(d, e, a, b,w[ 72]); e = rotateLeft( e, 30);
|
||||||
|
b += s4(c, d, e, a,w[ 73]); d = rotateLeft( d, 30);
|
||||||
|
a += s4(b, c, d, e,w[ 74]); c = rotateLeft( c, 30);
|
||||||
|
e += s4(a, b, c, d,w[ 75]); b = rotateLeft( b, 30);
|
||||||
|
d += s4(e, a, b, c,w[ 76]); a = rotateLeft( a, 30);
|
||||||
|
c += s4(d, e, a, b,w[ 77]); e = rotateLeft( e, 30);
|
||||||
|
b += s4(c, d, e, a,w[ 78]); d = rotateLeft( d, 30);
|
||||||
|
a += s4(b, c, d, e,w[ 79]); c = rotateLeft( c, 30);
|
||||||
|
|
||||||
|
// @formatter:on
|
||||||
|
h.save(h.a + a, h.b + b, h.c + c, h.d + d, h.e + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round 2
|
private void recompress(int t) {
|
||||||
for (int t = 20; t < 40; t++) {
|
State s;
|
||||||
int temp = ((a << 5) | (a >>> 27)) // S^5(A)
|
if (t == 58) {
|
||||||
+ (b ^ c ^ d) // f: 20 <= t <= 39
|
s = state58;
|
||||||
+ e + w[t] + 0x6ED9EBA1;
|
} else if (t == 65) {
|
||||||
e = d;
|
s = state65;
|
||||||
d = c;
|
} else {
|
||||||
c = (b << 30) | (b >>> 2); // S^30(B)
|
throw new IllegalStateException();
|
||||||
b = a;
|
}
|
||||||
a = temp;
|
int a = s.a, b = s.b, c = s.c, d = s.d, e = s.e;
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
if (t == 65) {
|
||||||
|
{ c = rotateRight( c, 30); a -= s4(b, c, d, e,w2[ 64]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s4(c, d, e, a,w2[ 63]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s4(d, e, a, b,w2[ 62]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s4(e, a, b, c,w2[ 61]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s4(a, b, c, d,w2[ 60]);}
|
||||||
|
|
||||||
|
{ c = rotateRight( c, 30); a -= s3(b, c, d, e,w2[ 59]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s3(c, d, e, a,w2[ 58]);}
|
||||||
|
}
|
||||||
|
{ e = rotateRight( e, 30); c -= s3(d, e, a, b,w2[ 57]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s3(e, a, b, c,w2[ 56]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s3(a, b, c, d,w2[ 55]);}
|
||||||
|
{ c = rotateRight( c, 30); a -= s3(b, c, d, e,w2[ 54]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s3(c, d, e, a,w2[ 53]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s3(d, e, a, b,w2[ 52]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s3(e, a, b, c,w2[ 51]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s3(a, b, c, d,w2[ 50]);}
|
||||||
|
{ c = rotateRight( c, 30); a -= s3(b, c, d, e,w2[ 49]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s3(c, d, e, a,w2[ 48]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s3(d, e, a, b,w2[ 47]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s3(e, a, b, c,w2[ 46]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s3(a, b, c, d,w2[ 45]);}
|
||||||
|
{ c = rotateRight( c, 30); a -= s3(b, c, d, e,w2[ 44]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s3(c, d, e, a,w2[ 43]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s3(d, e, a, b,w2[ 42]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s3(e, a, b, c,w2[ 41]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s3(a, b, c, d,w2[ 40]);}
|
||||||
|
|
||||||
|
{ c = rotateRight( c, 30); a -= s2(b, c, d, e,w2[ 39]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s2(c, d, e, a,w2[ 38]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s2(d, e, a, b,w2[ 37]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s2(e, a, b, c,w2[ 36]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s2(a, b, c, d,w2[ 35]);}
|
||||||
|
{ c = rotateRight( c, 30); a -= s2(b, c, d, e,w2[ 34]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s2(c, d, e, a,w2[ 33]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s2(d, e, a, b,w2[ 32]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s2(e, a, b, c,w2[ 31]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s2(a, b, c, d,w2[ 30]);}
|
||||||
|
{ c = rotateRight( c, 30); a -= s2(b, c, d, e,w2[ 29]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s2(c, d, e, a,w2[ 28]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s2(d, e, a, b,w2[ 27]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s2(e, a, b, c,w2[ 26]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s2(a, b, c, d,w2[ 25]);}
|
||||||
|
{ c = rotateRight( c, 30); a -= s2(b, c, d, e,w2[ 24]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s2(c, d, e, a,w2[ 23]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s2(d, e, a, b,w2[ 22]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s2(e, a, b, c,w2[ 21]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s2(a, b, c, d,w2[ 20]);}
|
||||||
|
|
||||||
|
{ c = rotateRight( c, 30); a -= s1(b, c, d, e,w2[ 19]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s1(c, d, e, a,w2[ 18]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s1(d, e, a, b,w2[ 17]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s1(e, a, b, c,w2[ 16]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s1(a, b, c, d,w2[ 15]);}
|
||||||
|
{ c = rotateRight( c, 30); a -= s1(b, c, d, e,w2[ 14]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s1(c, d, e, a,w2[ 13]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s1(d, e, a, b,w2[ 12]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s1(e, a, b, c,w2[ 11]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s1(a, b, c, d,w2[ 10]);}
|
||||||
|
{ c = rotateRight( c, 30); a -= s1(b, c, d, e,w2[ 9]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s1(c, d, e, a,w2[ 8]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s1(d, e, a, b,w2[ 7]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s1(e, a, b, c,w2[ 6]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s1(a, b, c, d,w2[ 5]);}
|
||||||
|
{ c = rotateRight( c, 30); a -= s1(b, c, d, e,w2[ 4]);}
|
||||||
|
{ d = rotateRight( d, 30); b -= s1(c, d, e, a,w2[ 3]);}
|
||||||
|
{ e = rotateRight( e, 30); c -= s1(d, e, a, b,w2[ 2]);}
|
||||||
|
{ a = rotateRight( a, 30); d -= s1(e, a, b, c,w2[ 1]);}
|
||||||
|
{ b = rotateRight( b, 30); e -= s1(a, b, c, d,w2[ 0]);}
|
||||||
|
|
||||||
|
hIn.save(a, b, c, d, e);
|
||||||
|
a = s.a; b = s.b; c = s.c; d = s.d; e = s.e;
|
||||||
|
|
||||||
|
if (t == 58) {
|
||||||
|
{ b += s3(c, d, e, a,w2[ 58]); d = rotateLeft( d, 30);}
|
||||||
|
{ a += s3(b, c, d, e,w2[ 59]); c = rotateLeft( c, 30);}
|
||||||
|
|
||||||
|
{ e += s4(a, b, c, d,w2[ 60]); b = rotateLeft( b, 30);}
|
||||||
|
{ d += s4(e, a, b, c,w2[ 61]); a = rotateLeft( a, 30);}
|
||||||
|
{ c += s4(d, e, a, b,w2[ 62]); e = rotateLeft( e, 30);}
|
||||||
|
{ b += s4(c, d, e, a,w2[ 63]); d = rotateLeft( d, 30);}
|
||||||
|
{ a += s4(b, c, d, e,w2[ 64]); c = rotateLeft( c, 30);}
|
||||||
|
}
|
||||||
|
{ e += s4(a, b, c, d,w2[ 65]); b = rotateLeft( b, 30);}
|
||||||
|
{ d += s4(e, a, b, c,w2[ 66]); a = rotateLeft( a, 30);}
|
||||||
|
{ c += s4(d, e, a, b,w2[ 67]); e = rotateLeft( e, 30);}
|
||||||
|
{ b += s4(c, d, e, a,w2[ 68]); d = rotateLeft( d, 30);}
|
||||||
|
{ a += s4(b, c, d, e,w2[ 69]); c = rotateLeft( c, 30);}
|
||||||
|
{ e += s4(a, b, c, d,w2[ 70]); b = rotateLeft( b, 30);}
|
||||||
|
{ d += s4(e, a, b, c,w2[ 71]); a = rotateLeft( a, 30);}
|
||||||
|
{ c += s4(d, e, a, b,w2[ 72]); e = rotateLeft( e, 30);}
|
||||||
|
{ b += s4(c, d, e, a,w2[ 73]); d = rotateLeft( d, 30);}
|
||||||
|
{ a += s4(b, c, d, e,w2[ 74]); c = rotateLeft( c, 30);}
|
||||||
|
{ e += s4(a, b, c, d,w2[ 75]); b = rotateLeft( b, 30);}
|
||||||
|
{ d += s4(e, a, b, c,w2[ 76]); a = rotateLeft( a, 30);}
|
||||||
|
{ c += s4(d, e, a, b,w2[ 77]); e = rotateLeft( e, 30);}
|
||||||
|
{ b += s4(c, d, e, a,w2[ 78]); d = rotateLeft( d, 30);}
|
||||||
|
{ a += s4(b, c, d, e,w2[ 79]); c = rotateLeft( c, 30);}
|
||||||
|
|
||||||
|
// @formatter:on
|
||||||
|
hTmp.save(hIn.a + a, hIn.b + b, hIn.c + c, hIn.d + d, hIn.e + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round 3
|
private static int s1(int a, int b, int c, int d, int w_t) {
|
||||||
for (int t = 40; t < 60; t++) {
|
return rotateLeft(a, 5)
|
||||||
int temp = ((a << 5) | (a >>> 27)) // S^5(A)
|
// f: 0 <= t <= 19
|
||||||
+ ((b & c) | (d & (b | c))) // f: 40 <= t <= 59
|
+ ((b & c) | ((~b) & d))
|
||||||
+ e + w[t] + 0x8F1BBCDC;
|
+ 0x5A827999 + w_t;
|
||||||
e = d;
|
|
||||||
d = c;
|
|
||||||
c = (b << 30) | (b >>> 2); // S^30(B)
|
|
||||||
b = a;
|
|
||||||
a = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round 4
|
private static int s2(int a, int b, int c, int d, int w_t) {
|
||||||
for (int t = 60; t < 80; t++) {
|
return rotateLeft(a, 5)
|
||||||
int temp = ((a << 5) | (a >>> 27)) // S^5(A)
|
// f: 20 <= t <= 39
|
||||||
+ (b ^ c ^ d) // f: 60 <= t <= 79
|
+ (b ^ c ^ d)
|
||||||
+ e + w[t] + 0xCA62C1D6;
|
+ 0x6ED9EBA1 + w_t;
|
||||||
e = d;
|
|
||||||
d = c;
|
|
||||||
c = (b << 30) | (b >>> 2); // S^30(B)
|
|
||||||
b = a;
|
|
||||||
a = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h0 += a;
|
private static int s3(int a, int b, int c, int d, int w_t) {
|
||||||
h1 += b;
|
return rotateLeft(a, 5)
|
||||||
h2 += c;
|
// f: 40 <= t <= 59
|
||||||
h3 += d;
|
+ ((b & c) | (b & d) | (c & d))
|
||||||
h4 += e;
|
+ 0x8F1BBCDC + w_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int s4(int a, int b, int c, int d, int w_t) {
|
||||||
|
return rotateLeft(a, 5)
|
||||||
|
// f: 60 <= t <= 79
|
||||||
|
+ (b ^ c ^ d)
|
||||||
|
+ 0xCA62C1D6 + w_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean eq(State q, State r) {
|
||||||
|
return q.a == r.a
|
||||||
|
&& q.b == r.b
|
||||||
|
&& q.c == r.c
|
||||||
|
&& q.d == r.d
|
||||||
|
&& q.e == r.e;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finish() {
|
private void finish() {
|
||||||
|
@ -261,6 +489,12 @@ private void finish() {
|
||||||
NB.encodeInt32(buffer, 56, (int) (length >>> (32 - 3)));
|
NB.encodeInt32(buffer, 56, (int) (length >>> (32 - 3)));
|
||||||
NB.encodeInt32(buffer, 60, (int) (length << 3));
|
NB.encodeInt32(buffer, 60, (int) (length << 3));
|
||||||
compress(buffer, 0);
|
compress(buffer, 0);
|
||||||
|
|
||||||
|
if (foundCollision) {
|
||||||
|
ObjectId id = h.toObjectId();
|
||||||
|
LOG.warn("possible SHA-1 collision " + id.name()); //$NON-NLS-1$
|
||||||
|
throw new Sha1CollisionException(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -269,16 +503,18 @@ private void finish() {
|
||||||
* Once {@code digest()} is called, this instance should be discarded.
|
* Once {@code digest()} is called, this instance should be discarded.
|
||||||
*
|
*
|
||||||
* @return the bytes for the resulting hash.
|
* @return the bytes for the resulting hash.
|
||||||
|
* @throws Sha1CollisionException
|
||||||
|
* if a collision was detected and safeHash is false.
|
||||||
*/
|
*/
|
||||||
public byte[] digest() {
|
public byte[] digest() throws Sha1CollisionException {
|
||||||
finish();
|
finish();
|
||||||
|
|
||||||
byte[] b = new byte[20];
|
byte[] b = new byte[20];
|
||||||
NB.encodeInt32(b, 0, h0);
|
NB.encodeInt32(b, 0, h.a);
|
||||||
NB.encodeInt32(b, 4, h1);
|
NB.encodeInt32(b, 4, h.b);
|
||||||
NB.encodeInt32(b, 8, h2);
|
NB.encodeInt32(b, 8, h.c);
|
||||||
NB.encodeInt32(b, 12, h3);
|
NB.encodeInt32(b, 12, h.d);
|
||||||
NB.encodeInt32(b, 16, h4);
|
NB.encodeInt32(b, 16, h.e);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,10 +524,12 @@ public byte[] digest() {
|
||||||
* Once {@code digest()} is called, this instance should be discarded.
|
* Once {@code digest()} is called, this instance should be discarded.
|
||||||
*
|
*
|
||||||
* @return the ObjectId for the resulting hash.
|
* @return the ObjectId for the resulting hash.
|
||||||
|
* @throws Sha1CollisionException
|
||||||
|
* if a collision was detected and safeHash is false.
|
||||||
*/
|
*/
|
||||||
public ObjectId toObjectId() {
|
public ObjectId toObjectId() throws Sha1CollisionException {
|
||||||
finish();
|
finish();
|
||||||
return new ObjectId(h0, h1, h2, h3, h4);
|
return h.toObjectId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -301,9 +539,63 @@ public ObjectId toObjectId() {
|
||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
* destination to copy the digest to.
|
* destination to copy the digest to.
|
||||||
|
* @throws Sha1CollisionException
|
||||||
|
* if a collision was detected and safeHash is false.
|
||||||
*/
|
*/
|
||||||
public void digest(MutableObjectId id) {
|
public void digest(MutableObjectId id) throws Sha1CollisionException {
|
||||||
finish();
|
finish();
|
||||||
id.set(h0, h1, h2, h3, h4);
|
id.set(h.a, h.b, h.c, h.d, h.e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a collision was detected.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @return {@code true} if a likely collision was detected.
|
||||||
|
*/
|
||||||
|
public boolean hasCollision() {
|
||||||
|
return foundCollision;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset this instance to compute another hash.
|
||||||
|
*
|
||||||
|
* @return {@code this}.
|
||||||
|
*/
|
||||||
|
public SHA1 reset() {
|
||||||
|
h.init();
|
||||||
|
length = 0;
|
||||||
|
foundCollision = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class State {
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
int c;
|
||||||
|
int d;
|
||||||
|
int e;
|
||||||
|
|
||||||
|
final void init() {
|
||||||
|
// Magic initialization constants defined by FIPS180.
|
||||||
|
save(0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0);
|
||||||
|
}
|
||||||
|
|
||||||
|
final void save(int a1, int b1, int c1, int d1, int e1) {
|
||||||
|
a = a1;
|
||||||
|
b = b1;
|
||||||
|
c = c1;
|
||||||
|
d = d1;
|
||||||
|
e = e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectId toObjectId() {
|
||||||
|
return new ObjectId(a, b, c, d, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
/* Template for recompress method; run through cpp. */
|
||||||
|
|
||||||
|
#define ROUND1_STEP(a, b, c, d, e, T) {e += s1(a,b,c,d,w2[T]); b = rotateLeft(b, 30);}
|
||||||
|
#define ROUND2_STEP(a, b, c, d, e, T) {e += s2(a,b,c,d,w2[T]); b = rotateLeft(b, 30);}
|
||||||
|
#define ROUND3_STEP(a, b, c, d, e, T) {e += s3(a,b,c,d,w2[T]); b = rotateLeft(b, 30);}
|
||||||
|
#define ROUND4_STEP(a, b, c, d, e, T) {e += s4(a,b,c,d,w2[T]); b = rotateLeft(b, 30);}
|
||||||
|
|
||||||
|
#define ROUND1_STEP_BW(a, b, c, d, e, T) {b = rotateRight(b, 30); e -= s1(a,b,c,d,w2[T]);}
|
||||||
|
#define ROUND2_STEP_BW(a, b, c, d, e, T) {b = rotateRight(b, 30); e -= s2(a,b,c,d,w2[T]);}
|
||||||
|
#define ROUND3_STEP_BW(a, b, c, d, e, T) {b = rotateRight(b, 30); e -= s3(a,b,c,d,w2[T]);}
|
||||||
|
#define ROUND4_STEP_BW(a, b, c, d, e, T) {b = rotateRight(b, 30); e -= s4(a,b,c,d,w2[T]);}
|
||||||
|
|
||||||
|
/* Condition to go backwards: if (t > step) */
|
||||||
|
/* t=80-66 have no identified DV; skip.
|
||||||
|
ROUND4_STEP_BW(b, c, d, e, a, 79)
|
||||||
|
ROUND4_STEP_BW(c, d, e, a, b, 78)
|
||||||
|
ROUND4_STEP_BW(d, e, a, b, c, 77)
|
||||||
|
ROUND4_STEP_BW(e, a, b, c, d, 76)
|
||||||
|
ROUND4_STEP_BW(a, b, c, d, e, 75)
|
||||||
|
ROUND4_STEP_BW(b, c, d, e, a, 74)
|
||||||
|
ROUND4_STEP_BW(c, d, e, a, b, 73)
|
||||||
|
ROUND4_STEP_BW(d, e, a, b, c, 72)
|
||||||
|
ROUND4_STEP_BW(e, a, b, c, d, 71)
|
||||||
|
ROUND4_STEP_BW(a, b, c, d, e, 70)
|
||||||
|
ROUND4_STEP_BW(b, c, d, e, a, 69)
|
||||||
|
ROUND4_STEP_BW(c, d, e, a, b, 68)
|
||||||
|
ROUND4_STEP_BW(d, e, a, b, c, 67)
|
||||||
|
ROUND4_STEP_BW(e, a, b, c, d, 66)
|
||||||
|
ROUND4_STEP_BW(a, b, c, d, e, 65)
|
||||||
|
*/
|
||||||
|
if (t == 65) {
|
||||||
|
ROUND4_STEP_BW(b, c, d, e, a, 64)
|
||||||
|
ROUND4_STEP_BW(c, d, e, a, b, 63)
|
||||||
|
ROUND4_STEP_BW(d, e, a, b, c, 62)
|
||||||
|
ROUND4_STEP_BW(e, a, b, c, d, 61)
|
||||||
|
ROUND4_STEP_BW(a, b, c, d, e, 60)
|
||||||
|
|
||||||
|
ROUND3_STEP_BW(b, c, d, e, a, 59)
|
||||||
|
ROUND3_STEP_BW(c, d, e, a, b, 58)
|
||||||
|
}
|
||||||
|
ROUND3_STEP_BW(d, e, a, b, c, 57)
|
||||||
|
ROUND3_STEP_BW(e, a, b, c, d, 56)
|
||||||
|
ROUND3_STEP_BW(a, b, c, d, e, 55)
|
||||||
|
ROUND3_STEP_BW(b, c, d, e, a, 54)
|
||||||
|
ROUND3_STEP_BW(c, d, e, a, b, 53)
|
||||||
|
ROUND3_STEP_BW(d, e, a, b, c, 52)
|
||||||
|
ROUND3_STEP_BW(e, a, b, c, d, 51)
|
||||||
|
ROUND3_STEP_BW(a, b, c, d, e, 50)
|
||||||
|
ROUND3_STEP_BW(b, c, d, e, a, 49)
|
||||||
|
ROUND3_STEP_BW(c, d, e, a, b, 48)
|
||||||
|
ROUND3_STEP_BW(d, e, a, b, c, 47)
|
||||||
|
ROUND3_STEP_BW(e, a, b, c, d, 46)
|
||||||
|
ROUND3_STEP_BW(a, b, c, d, e, 45)
|
||||||
|
ROUND3_STEP_BW(b, c, d, e, a, 44)
|
||||||
|
ROUND3_STEP_BW(c, d, e, a, b, 43)
|
||||||
|
ROUND3_STEP_BW(d, e, a, b, c, 42)
|
||||||
|
ROUND3_STEP_BW(e, a, b, c, d, 41)
|
||||||
|
ROUND3_STEP_BW(a, b, c, d, e, 40)
|
||||||
|
|
||||||
|
ROUND2_STEP_BW(b, c, d, e, a, 39)
|
||||||
|
ROUND2_STEP_BW(c, d, e, a, b, 38)
|
||||||
|
ROUND2_STEP_BW(d, e, a, b, c, 37)
|
||||||
|
ROUND2_STEP_BW(e, a, b, c, d, 36)
|
||||||
|
ROUND2_STEP_BW(a, b, c, d, e, 35)
|
||||||
|
ROUND2_STEP_BW(b, c, d, e, a, 34)
|
||||||
|
ROUND2_STEP_BW(c, d, e, a, b, 33)
|
||||||
|
ROUND2_STEP_BW(d, e, a, b, c, 32)
|
||||||
|
ROUND2_STEP_BW(e, a, b, c, d, 31)
|
||||||
|
ROUND2_STEP_BW(a, b, c, d, e, 30)
|
||||||
|
ROUND2_STEP_BW(b, c, d, e, a, 29)
|
||||||
|
ROUND2_STEP_BW(c, d, e, a, b, 28)
|
||||||
|
ROUND2_STEP_BW(d, e, a, b, c, 27)
|
||||||
|
ROUND2_STEP_BW(e, a, b, c, d, 26)
|
||||||
|
ROUND2_STEP_BW(a, b, c, d, e, 25)
|
||||||
|
ROUND2_STEP_BW(b, c, d, e, a, 24)
|
||||||
|
ROUND2_STEP_BW(c, d, e, a, b, 23)
|
||||||
|
ROUND2_STEP_BW(d, e, a, b, c, 22)
|
||||||
|
ROUND2_STEP_BW(e, a, b, c, d, 21)
|
||||||
|
ROUND2_STEP_BW(a, b, c, d, e, 20)
|
||||||
|
|
||||||
|
ROUND1_STEP_BW(b, c, d, e, a, 19)
|
||||||
|
ROUND1_STEP_BW(c, d, e, a, b, 18)
|
||||||
|
ROUND1_STEP_BW(d, e, a, b, c, 17)
|
||||||
|
ROUND1_STEP_BW(e, a, b, c, d, 16)
|
||||||
|
ROUND1_STEP_BW(a, b, c, d, e, 15)
|
||||||
|
ROUND1_STEP_BW(b, c, d, e, a, 14)
|
||||||
|
ROUND1_STEP_BW(c, d, e, a, b, 13)
|
||||||
|
ROUND1_STEP_BW(d, e, a, b, c, 12)
|
||||||
|
ROUND1_STEP_BW(e, a, b, c, d, 11)
|
||||||
|
ROUND1_STEP_BW(a, b, c, d, e, 10)
|
||||||
|
ROUND1_STEP_BW(b, c, d, e, a, 9)
|
||||||
|
ROUND1_STEP_BW(c, d, e, a, b, 8)
|
||||||
|
ROUND1_STEP_BW(d, e, a, b, c, 7)
|
||||||
|
ROUND1_STEP_BW(e, a, b, c, d, 6)
|
||||||
|
ROUND1_STEP_BW(a, b, c, d, e, 5)
|
||||||
|
ROUND1_STEP_BW(b, c, d, e, a, 4)
|
||||||
|
ROUND1_STEP_BW(c, d, e, a, b, 3)
|
||||||
|
ROUND1_STEP_BW(d, e, a, b, c, 2)
|
||||||
|
ROUND1_STEP_BW(e, a, b, c, d, 1)
|
||||||
|
ROUND1_STEP_BW(a, b, c, d, e, 0)
|
||||||
|
|
||||||
|
hIn.save(a, b, c, d, e);
|
||||||
|
a = s.a; b = s.b; c = s.c; d = s.d; e = s.e;
|
||||||
|
|
||||||
|
/* Condition to go fowards: if (t <= step) */
|
||||||
|
/* Earliest restart is T=58; skip.
|
||||||
|
ROUND1_STEP(a, b, c, d, e, 0)
|
||||||
|
ROUND1_STEP(e, a, b, c, d, 1)
|
||||||
|
ROUND1_STEP(d, e, a, b, c, 2)
|
||||||
|
ROUND1_STEP(c, d, e, a, b, 3)
|
||||||
|
ROUND1_STEP(b, c, d, e, a, 4)
|
||||||
|
ROUND1_STEP(a, b, c, d, e, 5)
|
||||||
|
ROUND1_STEP(e, a, b, c, d, 6)
|
||||||
|
ROUND1_STEP(d, e, a, b, c, 7)
|
||||||
|
ROUND1_STEP(c, d, e, a, b, 8)
|
||||||
|
ROUND1_STEP(b, c, d, e, a, 9)
|
||||||
|
ROUND1_STEP(a, b, c, d, e, 10)
|
||||||
|
ROUND1_STEP(e, a, b, c, d, 11)
|
||||||
|
ROUND1_STEP(d, e, a, b, c, 12)
|
||||||
|
ROUND1_STEP(c, d, e, a, b, 13)
|
||||||
|
ROUND1_STEP(b, c, d, e, a, 14)
|
||||||
|
ROUND1_STEP(a, b, c, d, e, 15)
|
||||||
|
ROUND1_STEP(e, a, b, c, d, 16)
|
||||||
|
ROUND1_STEP(d, e, a, b, c, 17)
|
||||||
|
ROUND1_STEP(c, d, e, a, b, 18)
|
||||||
|
ROUND1_STEP(b, c, d, e, a, 19)
|
||||||
|
|
||||||
|
ROUND2_STEP(a, b, c, d, e, 20)
|
||||||
|
ROUND2_STEP(e, a, b, c, d, 21)
|
||||||
|
ROUND2_STEP(d, e, a, b, c, 22)
|
||||||
|
ROUND2_STEP(c, d, e, a, b, 23)
|
||||||
|
ROUND2_STEP(b, c, d, e, a, 24)
|
||||||
|
ROUND2_STEP(a, b, c, d, e, 25)
|
||||||
|
ROUND2_STEP(e, a, b, c, d, 26)
|
||||||
|
ROUND2_STEP(d, e, a, b, c, 27)
|
||||||
|
ROUND2_STEP(c, d, e, a, b, 28)
|
||||||
|
ROUND2_STEP(b, c, d, e, a, 29)
|
||||||
|
ROUND2_STEP(a, b, c, d, e, 30)
|
||||||
|
ROUND2_STEP(e, a, b, c, d, 31)
|
||||||
|
ROUND2_STEP(d, e, a, b, c, 32)
|
||||||
|
ROUND2_STEP(c, d, e, a, b, 33)
|
||||||
|
ROUND2_STEP(b, c, d, e, a, 34)
|
||||||
|
ROUND2_STEP(a, b, c, d, e, 35)
|
||||||
|
ROUND2_STEP(e, a, b, c, d, 36)
|
||||||
|
ROUND2_STEP(d, e, a, b, c, 37)
|
||||||
|
ROUND2_STEP(c, d, e, a, b, 38)
|
||||||
|
ROUND2_STEP(b, c, d, e, a, 39)
|
||||||
|
|
||||||
|
ROUND3_STEP(a, b, c, d, e, 40)
|
||||||
|
ROUND3_STEP(e, a, b, c, d, 41)
|
||||||
|
ROUND3_STEP(d, e, a, b, c, 42)
|
||||||
|
ROUND3_STEP(c, d, e, a, b, 43)
|
||||||
|
ROUND3_STEP(b, c, d, e, a, 44)
|
||||||
|
ROUND3_STEP(a, b, c, d, e, 45)
|
||||||
|
ROUND3_STEP(e, a, b, c, d, 46)
|
||||||
|
ROUND3_STEP(d, e, a, b, c, 47)
|
||||||
|
ROUND3_STEP(c, d, e, a, b, 48)
|
||||||
|
ROUND3_STEP(b, c, d, e, a, 49)
|
||||||
|
ROUND3_STEP(a, b, c, d, e, 50)
|
||||||
|
ROUND3_STEP(e, a, b, c, d, 51)
|
||||||
|
ROUND3_STEP(d, e, a, b, c, 52)
|
||||||
|
ROUND3_STEP(c, d, e, a, b, 53)
|
||||||
|
ROUND3_STEP(b, c, d, e, a, 54)
|
||||||
|
ROUND3_STEP(a, b, c, d, e, 55)
|
||||||
|
ROUND3_STEP(e, a, b, c, d, 56)
|
||||||
|
ROUND3_STEP(d, e, a, b, c, 57)
|
||||||
|
*/
|
||||||
|
if (t == 58) {
|
||||||
|
ROUND3_STEP(c, d, e, a, b, 58)
|
||||||
|
ROUND3_STEP(b, c, d, e, a, 59)
|
||||||
|
|
||||||
|
ROUND4_STEP(a, b, c, d, e, 60)
|
||||||
|
ROUND4_STEP(e, a, b, c, d, 61)
|
||||||
|
ROUND4_STEP(d, e, a, b, c, 62)
|
||||||
|
ROUND4_STEP(c, d, e, a, b, 63)
|
||||||
|
ROUND4_STEP(b, c, d, e, a, 64)
|
||||||
|
}
|
||||||
|
ROUND4_STEP(a, b, c, d, e, 65)
|
||||||
|
ROUND4_STEP(e, a, b, c, d, 66)
|
||||||
|
ROUND4_STEP(d, e, a, b, c, 67)
|
||||||
|
ROUND4_STEP(c, d, e, a, b, 68)
|
||||||
|
ROUND4_STEP(b, c, d, e, a, 69)
|
||||||
|
ROUND4_STEP(a, b, c, d, e, 70)
|
||||||
|
ROUND4_STEP(e, a, b, c, d, 71)
|
||||||
|
ROUND4_STEP(d, e, a, b, c, 72)
|
||||||
|
ROUND4_STEP(c, d, e, a, b, 73)
|
||||||
|
ROUND4_STEP(b, c, d, e, a, 74)
|
||||||
|
ROUND4_STEP(a, b, c, d, e, 75)
|
||||||
|
ROUND4_STEP(e, a, b, c, d, 76)
|
||||||
|
ROUND4_STEP(d, e, a, b, c, 77)
|
||||||
|
ROUND4_STEP(c, d, e, a, b, 78)
|
||||||
|
ROUND4_STEP(b, c, d, e, a, 79)
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017, Google Inc.
|
||||||
|
* and other copyright owners as documented in the project's IP log.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available
|
||||||
|
* under the terms of the Eclipse Distribution License v1.0 which
|
||||||
|
* accompanies this distribution, is reproduced below, and is
|
||||||
|
* available at http://www.eclipse.org/org/documents/edl-v10.php
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or
|
||||||
|
* without modification, are permitted provided that the following
|
||||||
|
* conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* - Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials provided
|
||||||
|
* with the distribution.
|
||||||
|
*
|
||||||
|
* - Neither the name of the Eclipse Foundation, Inc. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior
|
||||||
|
* written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.eclipse.jgit.util.sha1;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.internal.JGitText;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown by {@link SHA1} if it detects a likely hash collision.
|
||||||
|
*
|
||||||
|
* @since 4.7
|
||||||
|
*/
|
||||||
|
public class Sha1CollisionException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize with default message.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* object whose contents are a hash collision.
|
||||||
|
*/
|
||||||
|
public Sha1CollisionException(ObjectId id) {
|
||||||
|
super(MessageFormat.format(
|
||||||
|
JGitText.get().sha1CollisionDetected1,
|
||||||
|
id.name()));
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue