Merge "SHA-1: collision detection support"

This commit is contained in:
Jonathan Nieder 2017-03-02 13:26:42 -05:00 committed by Gerrit Code Review @ Eclipse.org
commit 45f62576de
11 changed files with 1929 additions and 93 deletions

View File

@ -44,12 +44,20 @@
package org.eclipse.jgit.util.sha1;
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.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.util.IO;
import org.junit.Test;
public class SHA1Test {
@ -124,4 +132,107 @@ public void test2() throws NoSuchAlgorithmException {
assertEquals(exp, s1);
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;
}
}
}

View File

@ -21,6 +21,10 @@
margin-top: 0.05em;
margin-bottom: 0.05em;
}
.ubc-name {
margin-left: 0.5in;
white-space: pre;
}
</style>
</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
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>
</html>

View File

@ -564,6 +564,7 @@ selectingCommits=Selecting commits
sequenceTooLargeForDiffAlgorithm=Sequence too large for difference algorithm.
serviceNotEnabledNoName=Service not enabled
serviceNotPermitted={0} not permitted
sha1CollisionDetected1=SHA-1 collision detected on {0}
shallowCommitsAlreadyInitialized=Shallow commits have already been initialized
shallowPacksRequireDepthWalk=Shallow packs require a DepthWalk
shortCompressedStreamAt=Short compressed stream at {0}

View File

@ -623,6 +623,7 @@ public static JGitText get() {
/***/ public String sequenceTooLargeForDiffAlgorithm;
/***/ public String serviceNotEnabledNoName;
/***/ public String serviceNotPermitted;
/***/ public String sha1CollisionDetected1;
/***/ public String shallowCommitsAlreadyInitialized;
/***/ public String shallowPacksRequireDepthWalk;
/***/ public String shortCompressedStreamAt;

View File

@ -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);

View File

@ -43,31 +43,54 @@
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 org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
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.
*
* <p>
* 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
*/
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. */
public static SHA1 newInstance() {
return new SHA1();
}
private int h0;
private int h1;
private int h2;
private int h3;
private int h4;
private final State h = new State();
private final int[] w = new int[80];
/** Buffer to accumulate partial blocks to 64 byte alignment. */
@ -76,30 +99,35 @@ public static SHA1 newInstance() {
/** Total number of bytes in the message. */
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() {
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() {
init();
length = 0;
public SHA1 setDetectCollision(boolean detect) {
detectCollision = detect;
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.
*
@ -161,83 +189,283 @@ public void update(byte[] in, int p, int len) {
}
private void compress(byte[] block, int p) {
// Method 1 from RFC 3174 section 6.1.
// Method 2 (circular queue of 16 words) is slower.
int a = h0, b = h1, c = h2, d = h3, e = h4;
initBlock(block, p);
int ubcDvMask = detectCollision ? UbcCheck.check(w) : 0;
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++) {
int temp = 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;
w[t] = NB.decodeInt32(block, p + (t << 2));
}
// RFC 3174 6.1.b, extend state vector to 80 words.
for (int t = 16; t < 80; t++) {
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
for (int t = 16; t < 20; t++) {
int temp = ((a << 5) | (a >>> 27)) // S^5(A)
+ (((c ^ d) & b) ^ d) // f: 0 <= t <= 19
+ e + w[t] + 0x5A827999;
e = d;
d = c;
c = (b << 30) | (b >>> 2); // S^30(B)
b = a;
a = temp;
private void compress() {
// Method 1 from RFC 3174 section 6.1.
// Method 2 (circular queue of 16 words) is slower.
int a = h.a, b = h.b, c = h.c, d = h.d, e = h.e;
// @formatter:off
e += s1(a, b, c, d,w[ 0]); b = rotateLeft( b, 30);
d += s1(e, a, b, c,w[ 1]); a = rotateLeft( a, 30);
c += s1(d, e, a, b,w[ 2]); e = rotateLeft( e, 30);
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);
}
private void recompress(int t) {
State s;
if (t == 58) {
s = state58;
} else if (t == 65) {
s = state65;
} else {
throw new IllegalStateException();
}
int a = s.a, b = s.b, c = s.c, d = s.d, e = s.e;
// Round 2
for (int t = 20; t < 40; t++) {
int temp = ((a << 5) | (a >>> 27)) // S^5(A)
+ (b ^ c ^ d) // f: 20 <= t <= 39
+ e + w[t] + 0x6ED9EBA1;
e = d;
d = c;
c = (b << 30) | (b >>> 2); // S^30(B)
b = a;
a = temp;
}
// @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]);}
// Round 3
for (int t = 40; t < 60; t++) {
int temp = ((a << 5) | (a >>> 27)) // S^5(A)
+ ((b & c) | (d & (b | c))) // f: 40 <= t <= 59
+ e + w[t] + 0x8F1BBCDC;
e = d;
d = c;
c = (b << 30) | (b >>> 2); // S^30(B)
b = a;
a = temp;
}
{ 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]);}
// Round 4
for (int t = 60; t < 80; t++) {
int temp = ((a << 5) | (a >>> 27)) // S^5(A)
+ (b ^ c ^ d) // f: 60 <= t <= 79
+ e + w[t] + 0xCA62C1D6;
e = d;
d = c;
c = (b << 30) | (b >>> 2); // S^30(B)
b = a;
a = temp;
}
{ 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]);}
h0 += a;
h1 += b;
h2 += c;
h3 += d;
h4 += e;
{ 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);
}
private static int s1(int a, int b, int c, int d, int w_t) {
return rotateLeft(a, 5)
// f: 0 <= t <= 19
+ ((b & c) | ((~b) & d))
+ 0x5A827999 + w_t;
}
private static int s2(int a, int b, int c, int d, int w_t) {
return rotateLeft(a, 5)
// f: 20 <= t <= 39
+ (b ^ c ^ d)
+ 0x6ED9EBA1 + w_t;
}
private static int s3(int a, int b, int c, int d, int w_t) {
return rotateLeft(a, 5)
// f: 40 <= t <= 59
+ ((b & c) | (b & d) | (c & d))
+ 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() {
@ -261,6 +489,12 @@ private void finish() {
NB.encodeInt32(buffer, 56, (int) (length >>> (32 - 3)));
NB.encodeInt32(buffer, 60, (int) (length << 3));
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.
*
* @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();
byte[] b = new byte[20];
NB.encodeInt32(b, 0, h0);
NB.encodeInt32(b, 4, h1);
NB.encodeInt32(b, 8, h2);
NB.encodeInt32(b, 12, h3);
NB.encodeInt32(b, 16, h4);
NB.encodeInt32(b, 0, h.a);
NB.encodeInt32(b, 4, h.b);
NB.encodeInt32(b, 8, h.c);
NB.encodeInt32(b, 12, h.d);
NB.encodeInt32(b, 16, h.e);
return b;
}
@ -288,10 +524,12 @@ public byte[] digest() {
* Once {@code digest()} is called, this instance should be discarded.
*
* @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();
return new ObjectId(h0, h1, h2, h3, h4);
return h.toObjectId();
}
/**
@ -301,9 +539,63 @@ public ObjectId toObjectId() {
*
* @param id
* 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();
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);
}
}
}

View File

@ -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)

View File

@ -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