Poly1305 { static byte[] computeMac(final byte[] key, byte[] data) { if (key.length != MAC_KEY_SIZE_IN_BYTES) { throw new IllegalArgumentException("The key length in bytes must be 32."); } long h0 = 0; long h1 = 0; long h2 = 0; long h3 = 0; long h4 = 0; long d0; long d1; long d2; long d3; long d4; long c; long r0 = load26(key, 0, 0) & 0x3ffffff; long r1 = load26(key, 3, 2) & 0x3ffff03; long r2 = load26(key, 6, 4) & 0x3ffc0ff; long r3 = load26(key, 9, 6) & 0x3f03fff; long r4 = load26(key, 12, 8) & 0x00fffff; long s1 = r1 * 5; long s2 = r2 * 5; long s3 = r3 * 5; long s4 = r4 * 5; byte[] buf = new byte[MAC_TAG_SIZE_IN_BYTES + 1]; for (int i = 0; i < data.length; i += MAC_TAG_SIZE_IN_BYTES) { copyBlockSize(buf, data, i); h0 += load26(buf, 0, 0); h1 += load26(buf, 3, 2); h2 += load26(buf, 6, 4); h3 += load26(buf, 9, 6); h4 += load26(buf, 12, 8) | (buf[MAC_TAG_SIZE_IN_BYTES] << 24); d0 = h0 * r0 + h1 * s4 + h2 * s3 + h3 * s2 + h4 * s1; d1 = h0 * r1 + h1 * r0 + h2 * s4 + h3 * s3 + h4 * s2; d2 = h0 * r2 + h1 * r1 + h2 * r0 + h3 * s4 + h4 * s3; d3 = h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * s4; d4 = h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0; c = d0 >> 26; h0 = d0 & 0x3ffffff; d1 += c; c = d1 >> 26; h1 = d1 & 0x3ffffff; d2 += c; c = d2 >> 26; h2 = d2 & 0x3ffffff; d3 += c; c = d3 >> 26; h3 = d3 & 0x3ffffff; d4 += c; c = d4 >> 26; h4 = d4 & 0x3ffffff; h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; h1 += c; } c = h1 >> 26; h1 = h1 & 0x3ffffff; h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; h1 += c; long g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; long g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; long g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; long g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; long g4 = h4 + c - (1 << 26); long mask = g4 >> 63; h0 &= mask; h1 &= mask; h2 &= mask; h3 &= mask; h4 &= mask; mask = ~mask; h0 |= g0 & mask; h1 |= g1 & mask; h2 |= g2 & mask; h3 |= g3 & mask; h4 |= g4 & mask; h0 = (h0 | (h1 << 26)) & 0xffffffffL; h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffffL; h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffffL; h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffffL; c = h0 + load32(key, 16); h0 = c & 0xffffffffL; c = h1 + load32(key, 20) + (c >> 32); h1 = c & 0xffffffffL; c = h2 + load32(key, 24) + (c >> 32); h2 = c & 0xffffffffL; c = h3 + load32(key, 28) + (c >> 32); h3 = c & 0xffffffffL; byte[] mac = new byte[MAC_TAG_SIZE_IN_BYTES]; toByteArray(mac, h0, 0); toByteArray(mac, h1, 4); toByteArray(mac, h2, 8); toByteArray(mac, h3, 12); return mac; } private  Poly1305();  static final int MAC_TAG_SIZE_IN_BYTES; static final int MAC_KEY_SIZE_IN_BYTES; }
@Test public void testPoly1305ComputeMacThrowsIllegalArgExpWhenKeyLenIsGreaterThan32() { try { Poly1305.computeMac(new byte[MAC_KEY_SIZE_IN_BYTES + 1], new byte[0]); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException e) { Truth.assertThat(e).hasMessageThat().containsMatch("The key length in bytes must be 32."); } }
@Test public void testPoly1305ComputeMacThrowsIllegalArgExpWhenKeyLenIsLessThan32() { try { Poly1305.computeMac(new byte[MAC_KEY_SIZE_IN_BYTES - 1], new byte[0]); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException e) { Truth.assertThat(e).hasMessageThat().containsMatch("The key length in bytes must be 32."); } }
@Test public void testPoly1305TestVector1() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "00000000000000000000000000000000" + "00000000000000000000000000000000"); byte[] in = TestUtil.hexDecode("" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000"); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "00000000000000000000000000000000")); }
@Test public void testPoly1305TestVector2() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "00000000000000000000000000000000" + "36e5f6b5c5e06070f0efca96227a863e"); byte[] in = ( "Any submission to the IETF intended by the Contributor for publication as all or " + "part of an IETF Internet-Draft or RFC and any statement made within the context " + "of an IETF activity is considered an \"IETF Contribution\". Such statements " + "include oral statements in IETF sessions, as well as written and electronic " + "communications made at any time or place, which are addressed to") .getBytes(UTF_8); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "36e5f6b5c5e06070f0efca96227a863e")); }
@Test public void testPoly1305TestVector3() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "36e5f6b5c5e06070f0efca96227a863e" + "00000000000000000000000000000000"); byte[] in = ( "Any submission to the IETF intended by the Contributor for publication as all or " + "part of an IETF Internet-Draft or RFC and any statement made within the context " + "of an IETF activity is considered an \"IETF Contribution\". Such statements " + "include oral statements in IETF sessions, as well as written and electronic " + "communications made at any time or place, which are addressed to") .getBytes(UTF_8); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "f3477e7cd95417af89a6b8794c310cf0")); }
@Test public void testPoly1305TestVector4() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "1c9240a5eb55d38af333888604f6b5f0" + "473917c1402b80099dca5cbc207075c0"); byte[] in = TestUtil.hexDecode("" + "2754776173206272696c6c69672c2061" + "6e642074686520736c6974687920746f" + "7665730a446964206779726520616e64" + "2067696d626c6520696e207468652077" + "6162653a0a416c6c206d696d73792077" + "6572652074686520626f726f676f7665" + "732c0a416e6420746865206d6f6d6520" + "7261746873206f757467726162652e"); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "4541669a7eaaee61e708dc7cbcc5eb62")); }
@Test public void testPoly1305TestVector5() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "02000000000000000000000000000000" + "00000000000000000000000000000000"); byte[] in = TestUtil.hexDecode("" + "ffffffffffffffffffffffffffffffff"); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "03000000000000000000000000000000")); }
@Test public void testPoly1305TestVector6() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "02000000000000000000000000000000" + "ffffffffffffffffffffffffffffffff"); byte[] in = TestUtil.hexDecode("" + "02000000000000000000000000000000"); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "03000000000000000000000000000000")); }
@Test public void testPoly1305TestVector7() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "01000000000000000000000000000000" + "00000000000000000000000000000000"); byte[] in = TestUtil.hexDecode("" + "ffffffffffffffffffffffffffffffff" + "f0ffffffffffffffffffffffffffffff" + "11000000000000000000000000000000"); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "05000000000000000000000000000000")); }
@Test public void testPoly1305TestVector8() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "01000000000000000000000000000000" + "00000000000000000000000000000000"); byte[] in = TestUtil.hexDecode("" + "ffffffffffffffffffffffffffffffff" + "fbfefefefefefefefefefefefefefefe" + "01010101010101010101010101010101"); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "00000000000000000000000000000000")); }
@Test public void testPoly1305TestVector9() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "02000000000000000000000000000000" + "00000000000000000000000000000000"); byte[] in = TestUtil.hexDecode("" + "fdffffffffffffffffffffffffffffff"); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "faffffffffffffffffffffffffffffff")); }
@Test public void testPoly1305TestVector10() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "01000000000000000400000000000000" + "00000000000000000000000000000000"); byte[] in = TestUtil.hexDecode("" + "e33594d7505e43b90000000000000000" + "3394d7505e4379cd0100000000000000" + "00000000000000000000000000000000" + "01000000000000000000000000000000"); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "14000000000000005500000000000000")); }
@Test public void testPoly1305TestVector11() throws GeneralSecurityException { byte[] key = TestUtil.hexDecode("" + "01000000000000000400000000000000" + "00000000000000000000000000000000"); byte[] in = TestUtil.hexDecode("" + "e33594d7505e43b90000000000000000" + "3394d7505e4379cd0100000000000000" + "00000000000000000000000000000000"); Truth.assertThat(Poly1305.computeMac(key, in)).isEqualTo(TestUtil.hexDecode("" + "13000000000000000000000000000000")); }