From 152abde2bd974b0fa35a40c5a2d8fd33f46dfb86 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Tue, 1 Sep 2020 19:08:54 +0300 Subject: [PATCH 01/28] Bump version to 0.5.6 --- README.md | 2 +- build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5c61ea918..4f641cc0d 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can io.libp2p jvm-libp2p-minimal - 0.5.5-RELEASE + 0.5.6-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index 54a4ffecb..46076c6f8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.5.5-RELEASE" +version = "0.5.6-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 5bff190c1c60078860b866013e864ef93ff050a9 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Tue, 1 Sep 2020 19:16:45 +0300 Subject: [PATCH 02/28] Fix versions in develop branch --- README.md | 2 +- build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5c61ea918..4f641cc0d 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can io.libp2p jvm-libp2p-minimal - 0.5.5-RELEASE + 0.5.6-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index 54a4ffecb..3442bee48 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.5.5-RELEASE" +version = "0.6.0-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 187a68a794a59ce7a7b41f3e5c8ac1cc9ffd1278 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Tue, 8 Sep 2020 15:22:39 +0300 Subject: [PATCH 03/28] Bump version to 0.5.7 --- README.md | 2 +- build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4f641cc0d..d2bd23bd3 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can io.libp2p jvm-libp2p-minimal - 0.5.6-RELEASE + 0.5.7-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index 379f00279..e09d8ff09 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.6.0-RELEASE" +version = "0.5.7-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From b643203c4e1cd854b6a005cbc182e79b25304993 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Tue, 27 Oct 2020 21:04:39 +0300 Subject: [PATCH 04/28] Release 0.5.8 (#149) * #142 Add behaviourPenaltyThreshold Gossip 1.1 param * #144 External Noise lib * #145 Add seenTTL gossip parameter and its handling * #146 Fix misc QuantStamp issues * #147 Add build info to README.md * #148 Less verbosity when failed to decrypt message from remote --- README.md | 23 +- build.gradle.kts | 36 +- settings.gradle | 8 +- .../noise/crypto/Blake2bMessageDigest.java | 243 --- .../noise/crypto/Blake2sMessageDigest.java | 233 --- .../noise/crypto/ChaChaCore.java | 200 -- .../noise/crypto/Curve25519.java | 531 ------ .../southernstorm/noise/crypto/Curve448.java | 622 ------- .../com/southernstorm/noise/crypto/GHASH.java | 204 --- .../southernstorm/noise/crypto/NewHope.java | 1602 ----------------- .../noise/crypto/NewHopeTor.java | 982 ---------- .../southernstorm/noise/crypto/Poly1305.java | 327 ---- .../noise/crypto/RijndaelAES.java | 1099 ----------- .../noise/crypto/SHA256MessageDigest.java | 244 --- .../noise/crypto/SHA512MessageDigest.java | 265 --- .../noise/crypto/package-info.java | 12 - .../protocol/AESGCMFallbackCipherState.java | 264 --- .../protocol/AESGCMOnCtrCipherState.java | 330 ---- .../noise/protocol/ChaChaPolyCipherState.java | 289 --- .../noise/protocol/CipherState.java | 158 -- .../noise/protocol/CipherStatePair.java | 106 -- .../noise/protocol/Curve25519DHState.java | 156 -- .../noise/protocol/Curve448DHState.java | 156 -- .../southernstorm/noise/protocol/DHState.java | 156 -- .../noise/protocol/DHStateHybrid.java | 60 - .../noise/protocol/Destroyable.java | 43 - .../noise/protocol/HandshakeState.java | 1259 ------------- .../noise/protocol/NewHopeDHState.java | 340 ---- .../southernstorm/noise/protocol/Noise.java | 236 --- .../southernstorm/noise/protocol/Pattern.java | 835 --------- .../noise/protocol/SymmetricState.java | 483 ----- .../noise/protocol/package-info.java | 7 - .../io/libp2p/discovery/mdns/ServiceInfo.java | 10 +- .../libp2p/discovery/mdns/impl/DNSRecord.java | 22 +- .../libp2p/discovery/mdns/impl/JmDNSImpl.java | 87 +- .../discovery/mdns/impl/ServiceInfoImpl.java | 24 +- .../kotlin/io/libp2p/pubsub/AbstractRouter.kt | 6 +- .../io/libp2p/pubsub/gossip/GossipParams.kt | 14 +- .../io/libp2p/pubsub/gossip/GossipRouter.kt | 13 + .../io/libp2p/pubsub/gossip/GossipScore.kt | 5 +- .../gossip/builders/GossipParamsBuilder.kt | 7 + .../io/libp2p/security/SecureChannelError.kt | 7 +- .../io/libp2p/security/noise/NoiseXXCodec.kt | 8 +- .../libp2p/pubsub/gossip/GossipScoreTest.kt | 58 + .../libp2p/pubsub/gossip/GossipV1_1Tests.kt | 27 + 45 files changed, 268 insertions(+), 11529 deletions(-) delete mode 100644 src/main/java/com/southernstorm/noise/crypto/Blake2bMessageDigest.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/Blake2sMessageDigest.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/ChaChaCore.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/Curve25519.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/Curve448.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/GHASH.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/NewHope.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/NewHopeTor.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/Poly1305.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/RijndaelAES.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/SHA256MessageDigest.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/SHA512MessageDigest.java delete mode 100644 src/main/java/com/southernstorm/noise/crypto/package-info.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/AESGCMFallbackCipherState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/AESGCMOnCtrCipherState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/ChaChaPolyCipherState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/CipherState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/CipherStatePair.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/Curve25519DHState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/Curve448DHState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/DHState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/DHStateHybrid.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/Destroyable.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/HandshakeState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/NewHopeDHState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/Noise.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/Pattern.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/SymmetricState.java delete mode 100644 src/main/java/com/southernstorm/noise/protocol/package-info.java create mode 100644 src/test/kotlin/io/libp2p/pubsub/gossip/GossipScoreTest.kt diff --git a/README.md b/README.md index d2bd23bd3..674cdf005 100644 --- a/README.md +++ b/README.md @@ -69,20 +69,39 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can jcenter() } - implementation 'io.libp2p:jvm-libp2p-minimal:0.5.5-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.5.8-RELEASE' ``` ### Using Maven ``` io.libp2p jvm-libp2p-minimal - 0.5.7-RELEASE + 0.5.8-RELEASE pom ``` +## Building the project +To build the library you will need just +- JDK (Java Development Kit) of version 8 or higher + +For building a stable release version clone the `master` branch: +```bash +> git clone https://github.com/libp2p/jvm-libp2p -b master +``` +For building a version with the latest updates clone the `develop` (default) branch: +```bash +> git clone https://github.com/libp2p/jvm-libp2p +``` + +To build the library: +```bash +> cd jvm-libp2p +> ./gradlew build +``` +After the build is complete you may find the library `.jar` file here: `jvm-libp2p/build/libs/jvm-libp2p-minimal-0.x.y-RELEASE.jar` ## License diff --git a/build.gradle.kts b/build.gradle.kts index e09d8ff09..68ea6e7fc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,6 +2,7 @@ import com.google.protobuf.gradle.proto import com.google.protobuf.gradle.protobuf import com.google.protobuf.gradle.protoc import com.jfrog.bintray.gradle.BintrayExtension +import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.net.URL @@ -12,7 +13,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.5.7-RELEASE" +version = "0.5.8-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { @@ -38,20 +39,23 @@ val log4j2Version = "2.11.2" dependencies { implementation(kotlin("stdlib-jdk8")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0-M1") - compile("io.netty:netty-all:4.1.36.Final") - compile("com.google.guava:guava:27.1-jre") - compile("org.bouncycastle:bcprov-jdk15on:1.62") - compile("org.bouncycastle:bcpkix-jdk15on:1.62") - compile("com.google.protobuf:protobuf-java:3.11.0") - compile("commons-codec:commons-codec:1.13") + implementation("tech.pegasys.teku:noise-java:0.1.0") - compile("org.apache.logging.log4j:log4j-api:${log4j2Version}") - compile("org.apache.logging.log4j:log4j-core:${log4j2Version}") - compile("javax.xml.bind:jaxb-api:2.3.1") + implementation("io.netty:netty-all:4.1.36.Final") + implementation("com.google.guava:guava:27.1-jre") + implementation("org.bouncycastle:bcprov-jdk15on:1.62") + implementation("org.bouncycastle:bcpkix-jdk15on:1.62") + implementation("com.google.protobuf:protobuf-java:3.11.0") + implementation("commons-codec:commons-codec:1.13") - testCompile("org.junit.jupiter:junit-jupiter-api:5.4.2") - testCompile("org.junit.jupiter:junit-jupiter-params:5.4.2") - testRuntime("org.junit.jupiter:junit-jupiter-engine:5.4.2") + implementation("org.apache.logging.log4j:log4j-api:${log4j2Version}") + implementation("org.apache.logging.log4j:log4j-core:${log4j2Version}") + implementation("javax.xml.bind:jaxb-api:2.3.1") + + testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.2") + testImplementation("org.junit.jupiter:junit-jupiter-params:5.4.2") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.4.2") + testImplementation("io.mockk:mockk:1.10.0") } sourceSets { @@ -92,7 +96,11 @@ tasks.test { } testLogging { - events("PASSED", "FAILED", "SKIPPED") + events("FAILED") + exceptionFormat = TestExceptionFormat.FULL + showCauses = true + showExceptions = true + showStackTraces = true } // disabling the parallel test runs for the time being due to port collisions diff --git a/settings.gradle b/settings.gradle index c9212bda8..b8a5d1463 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,7 @@ -rootProject.name = 'jvm-libp2p-minimal' \ No newline at end of file +rootProject.name = 'jvm-libp2p-minimal' + +sourceControl { + gitRepository("https://github.com/ConsenSys/noise-java") { + producesModule("tech.pegasys.teku:noise-java") + } +} diff --git a/src/main/java/com/southernstorm/noise/crypto/Blake2bMessageDigest.java b/src/main/java/com/southernstorm/noise/crypto/Blake2bMessageDigest.java deleted file mode 100644 index a93126fa5..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/Blake2bMessageDigest.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.crypto; - -import com.southernstorm.noise.protocol.Destroyable; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.util.Arrays; - -/** - * Fallback implementation of BLAKE2b for the Noise library. - * - * This implementation only supports message digesting with an output - * length of 64 bytes and a limit of 2^64 - 1 bytes of input. - * Keyed hashing and variable-length digests are not supported. - */ -public class Blake2bMessageDigest extends MessageDigest implements Destroyable { - - private long[] h; - private byte[] block; - private long[] m; - private long[] v; - private long length; - private int posn; - - /** - * Constructs a new BLAKE2b message digest object. - */ - public Blake2bMessageDigest() { - super("BLAKE2B-512"); - h = new long [8]; - block = new byte [128]; - m = new long [16]; - v = new long [16]; - engineReset(); - } - - @Override - protected byte[] engineDigest() { - byte[] digest = new byte [64]; - try { - engineDigest(digest, 0, 64); - } catch (DigestException e) { - // Shouldn't happen, but just in case. - Arrays.fill(digest, (byte)0); - } - return digest; - } - - @Override - protected int engineDigest(byte[] buf, int offset, int len) throws DigestException - { - if (len < 64) - throw new DigestException("Invalid digest length for BLAKE2b"); - Arrays.fill(block, posn, 128, (byte)0); - transform(-1); - for (int index = 0; index < 8; ++index) { - long value = h[index]; - buf[offset++] = (byte)value; - buf[offset++] = (byte)(value >> 8); - buf[offset++] = (byte)(value >> 16); - buf[offset++] = (byte)(value >> 24); - buf[offset++] = (byte)(value >> 32); - buf[offset++] = (byte)(value >> 40); - buf[offset++] = (byte)(value >> 48); - buf[offset++] = (byte)(value >> 56); - } - return 32; - } - - @Override - protected int engineGetDigestLength() { - return 64; - } - - @Override - protected void engineReset() { - h[0] = 0x6a09e667f3bcc908L ^ 0x01010040; - h[1] = 0xbb67ae8584caa73bL; - h[2] = 0x3c6ef372fe94f82bL; - h[3] = 0xa54ff53a5f1d36f1L; - h[4] = 0x510e527fade682d1L; - h[5] = 0x9b05688c2b3e6c1fL; - h[6] = 0x1f83d9abfb41bd6bL; - h[7] = 0x5be0cd19137e2179L; - length = 0; - posn = 0; - } - - @Override - protected void engineUpdate(byte input) { - if (posn >= 128) { - transform(0); - posn = 0; - } - block[posn++] = input; - ++length; - } - - @Override - protected void engineUpdate(byte[] input, int offset, int len) { - while (len > 0) { - if (posn >= 128) { - transform(0); - posn = 0; - } - int temp = (128 - posn); - if (temp > len) - temp = len; - System.arraycopy(input, offset, block, posn, temp); - posn += temp; - length += temp; - offset += temp; - len -= temp; - } - } - - // Permutation on the message input state for BLAKE2b. - static final byte[][] sigma = { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, - {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, - { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, - { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, - { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, - {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, - {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, - { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, - {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, - }; - - private void transform(long f0) - { - int index; - int offset; - - // Unpack the input block from little-endian into host-endian. - for (index = 0, offset = 0; index < 16; ++index, offset += 8) { - m[index] = (block[offset] & 0xFFL) | - ((block[offset + 1] & 0xFFL) << 8) | - ((block[offset + 2] & 0xFFL) << 16) | - ((block[offset + 3] & 0xFFL) << 24) | - ((block[offset + 4] & 0xFFL) << 32) | - ((block[offset + 5] & 0xFFL) << 40) | - ((block[offset + 6] & 0xFFL) << 48) | - ((block[offset + 7] & 0xFFL) << 56); - } - - // Format the block to be hashed. - for (index = 0; index < 8; ++index) - v[index] = h[index]; - v[8] = 0x6a09e667f3bcc908L; - v[9] = 0xbb67ae8584caa73bL; - v[10] = 0x3c6ef372fe94f82bL; - v[11] = 0xa54ff53a5f1d36f1L; - v[12] = 0x510e527fade682d1L ^ length; - v[13] = 0x9b05688c2b3e6c1fL; - v[14] = 0x1f83d9abfb41bd6bL ^ f0; - v[15] = 0x5be0cd19137e2179L; - - // Perform the 12 BLAKE2b rounds. - for (index = 0; index < 12; ++index) { - // Column round. - quarterRound(0, 4, 8, 12, 0, index); - quarterRound(1, 5, 9, 13, 1, index); - quarterRound(2, 6, 10, 14, 2, index); - quarterRound(3, 7, 11, 15, 3, index); - - // Diagonal round. - quarterRound(0, 5, 10, 15, 4, index); - quarterRound(1, 6, 11, 12, 5, index); - quarterRound(2, 7, 8, 13, 6, index); - quarterRound(3, 4, 9, 14, 7, index); - } - - // Combine the new and old hash values. - for (index = 0; index < 8; ++index) - h[index] ^= (v[index] ^ v[index + 8]); - } - - private static long rightRotate32(long v) - { - return v << 32 | (v >>> 32); - } - - private static long rightRotate24(long v) - { - return v << 40 | (v >>> 24); - } - - private static long rightRotate16(long v) - { - return v << 48 | (v >>> 16); - } - - private static long rightRotate63(long v) - { - return v << 1 | (v >>> 63); - } - - private void quarterRound(int a, int b, int c, int d, int i, int row) - { - v[a] += v[b] + m[sigma[row][2 * i]]; - v[d] = rightRotate32(v[d] ^ v[a]); - v[c] += v[d]; - v[b] = rightRotate24(v[b] ^ v[c]); - v[a] += v[b] + m[sigma[row][2 * i + 1]]; - v[d] = rightRotate16(v[d] ^ v[a]); - v[c] += v[d]; - v[b] = rightRotate63(v[b] ^ v[c]); - } - - @Override - public void destroy() { - Arrays.fill(h, (long)0); - Arrays.fill(block, (byte)0); - Arrays.fill(m, (long)0); - Arrays.fill(v, (long)0); - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/Blake2sMessageDigest.java b/src/main/java/com/southernstorm/noise/crypto/Blake2sMessageDigest.java deleted file mode 100644 index 5a0e0838d..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/Blake2sMessageDigest.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.crypto; - -import com.southernstorm.noise.protocol.Destroyable; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.util.Arrays; - -/** - * Fallback implementation of BLAKE2s for the Noise library. - * - * This implementation only supports message digesting with an output - * length of 32 bytes. Keyed hashing and variable-length digests are - * not supported. - */ -public class Blake2sMessageDigest extends MessageDigest implements Destroyable { - - private int[] h; - private byte[] block; - private int[] m; - private int[] v; - private long length; - private int posn; - - /** - * Constructs a new BLAKE2s message digest object. - */ - public Blake2sMessageDigest() { - super("BLAKE2S-256"); - h = new int [8]; - block = new byte [64]; - m = new int [16]; - v = new int [16]; - engineReset(); - } - - @Override - protected byte[] engineDigest() { - byte[] digest = new byte [32]; - try { - engineDigest(digest, 0, 32); - } catch (DigestException e) { - // Shouldn't happen, but just in case. - Arrays.fill(digest, (byte)0); - } - return digest; - } - - @Override - protected int engineDigest(byte[] buf, int offset, int len) throws DigestException - { - if (len < 32) - throw new DigestException("Invalid digest length for BLAKE2s"); - Arrays.fill(block, posn, 64, (byte)0); - transform(-1); - for (int index = 0; index < 8; ++index) { - int value = h[index]; - buf[offset++] = (byte)value; - buf[offset++] = (byte)(value >> 8); - buf[offset++] = (byte)(value >> 16); - buf[offset++] = (byte)(value >> 24); - } - return 32; - } - - @Override - protected int engineGetDigestLength() { - return 32; - } - - @Override - protected void engineReset() { - h[0] = 0x6A09E667 ^ 0x01010020; - h[1] = 0xBB67AE85; - h[2] = 0x3C6EF372; - h[3] = 0xA54FF53A; - h[4] = 0x510E527F; - h[5] = 0x9B05688C; - h[6] = 0x1F83D9AB; - h[7] = 0x5BE0CD19; - length = 0; - posn = 0; - } - - @Override - protected void engineUpdate(byte input) { - if (posn >= 64) { - transform(0); - posn = 0; - } - block[posn++] = input; - ++length; - } - - @Override - protected void engineUpdate(byte[] input, int offset, int len) { - while (len > 0) { - if (posn >= 64) { - transform(0); - posn = 0; - } - int temp = (64 - posn); - if (temp > len) - temp = len; - System.arraycopy(input, offset, block, posn, temp); - posn += temp; - length += temp; - offset += temp; - len -= temp; - } - } - - // Permutation on the message input state for BLAKE2s. - static final byte[][] sigma = { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, - {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, - { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, - { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, - { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, - {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, - {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, - { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, - {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0} - }; - - private void transform(int f0) - { - int index; - int offset; - - // Unpack the input block from little-endian into host-endian. - for (index = 0, offset = 0; index < 16; ++index, offset += 4) { - m[index] = (block[offset] & 0xFF) | - ((block[offset + 1] & 0xFF) << 8) | - ((block[offset + 2] & 0xFF) << 16) | - ((block[offset + 3] & 0xFF) << 24); - } - - // Format the block to be hashed. - for (index = 0; index < 8; ++index) - v[index] = h[index]; - v[8] = 0x6A09E667; - v[9] = 0xBB67AE85; - v[10] = 0x3C6EF372; - v[11] = 0xA54FF53A; - v[12] = 0x510E527F ^ (int)length; - v[13] = 0x9B05688C ^ (int)(length >> 32); - v[14] = 0x1F83D9AB ^ f0; - v[15] = 0x5BE0CD19; - - // Perform the 10 BLAKE2s rounds. - for (index = 0; index < 10; ++index) { - // Column round. - quarterRound(0, 4, 8, 12, 0, index); - quarterRound(1, 5, 9, 13, 1, index); - quarterRound(2, 6, 10, 14, 2, index); - quarterRound(3, 7, 11, 15, 3, index); - - // Diagonal round. - quarterRound(0, 5, 10, 15, 4, index); - quarterRound(1, 6, 11, 12, 5, index); - quarterRound(2, 7, 8, 13, 6, index); - quarterRound(3, 4, 9, 14, 7, index); - } - - // Combine the new and old hash values. - for (index = 0; index < 8; ++index) - h[index] ^= (v[index] ^ v[index + 8]); - } - - private static int rightRotate16(int v) - { - return v << 16 | (v >>> 16); - } - - private static int rightRotate12(int v) - { - return v << 20 | (v >>> 12); - } - - private static int rightRotate8(int v) - { - return v << 24 | (v >>> 8); - } - - private static int rightRotate7(int v) - { - return v << 25 | (v >>> 7); - } - - private void quarterRound(int a, int b, int c, int d, int i, int row) - { - v[a] += v[b] + m[sigma[row][2 * i]]; - v[d] = rightRotate16(v[d] ^ v[a]); - v[c] += v[d]; - v[b] = rightRotate12(v[b] ^ v[c]); - v[a] += v[b] + m[sigma[row][2 * i + 1]]; - v[d] = rightRotate8(v[d] ^ v[a]); - v[c] += v[d]; - v[b] = rightRotate7(v[b] ^ v[c]); - } - - @Override - public void destroy() { - Arrays.fill(h, (int)0); - Arrays.fill(block, (byte)0); - Arrays.fill(m, (int)0); - Arrays.fill(v, (int)0); - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/ChaChaCore.java b/src/main/java/com/southernstorm/noise/crypto/ChaChaCore.java deleted file mode 100644 index 4f38c4503..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/ChaChaCore.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.crypto; - -/** - * Implementation of the ChaCha20 core hash transformation. - */ -public final class ChaChaCore { - - private ChaChaCore() {} - - /** - * Hashes an input block with ChaCha20. - * - * @param output The output block, which must contain at least 16 - * elements and must not overlap with the input. - * @param input The input block, which must contain at least 16 - * elements. - */ - public static void hash(int[] output, int[] input) - { - int index; - - // Copy the input to the output to start with. - for (index = 0; index < 16; ++index) - output[index] = input[index]; - - // Perform the 20 ChaCha rounds in groups of two. - for (index = 0; index < 20; index += 2) { - // Column round. - quarterRound(output, 0, 4, 8, 12); - quarterRound(output, 1, 5, 9, 13); - quarterRound(output, 2, 6, 10, 14); - quarterRound(output, 3, 7, 11, 15); - - // Diagonal round. - quarterRound(output, 0, 5, 10, 15); - quarterRound(output, 1, 6, 11, 12); - quarterRound(output, 2, 7, 8, 13); - quarterRound(output, 3, 4, 9, 14); - } - - // Add the input block to the output. - for (index = 0; index < 16; ++index) - output[index] += input[index]; - } - - private static int char4(char c1, char c2, char c3, char c4) - { - return (((int)c1) & 0xFF) | ((((int)c2) & 0xFF) << 8) | ((((int)c3) & 0xFF) << 16) | ((((int)c4) & 0xFF) << 24); - } - - private static int fromLittleEndian(byte[] key, int offset) - { - return (key[offset] & 0xFF) | ((key[offset + 1] & 0xFF) << 8) | ((key[offset + 2] & 0xFF) << 16) | ((key[offset + 3] & 0xFF) << 24); - } - - /** - * Initializes a ChaCha20 block with a 128-bit key. - * - * @param output The output block, which must consist of at - * least 16 words. - * @param key The buffer containing the key. - * @param offset Offset of the key in the buffer. - */ - public static void initKey128(int[] output, byte[] key, int offset) - { - output[0] = char4('e', 'x', 'p', 'a'); - output[1] = char4('n', 'd', ' ', '1'); - output[2] = char4('6', '-', 'b', 'y'); - output[3] = char4('t', 'e', ' ', 'k'); - output[4] = fromLittleEndian(key, offset); - output[5] = fromLittleEndian(key, offset + 4); - output[6] = fromLittleEndian(key, offset + 8); - output[7] = fromLittleEndian(key, offset + 12); - output[8] = output[4]; - output[9] = output[5]; - output[10] = output[6]; - output[11] = output[7]; - output[12] = 0; - output[13] = 0; - output[14] = 0; - output[15] = 0; - } - - /** - * Initializes a ChaCha20 block with a 256-bit key. - * - * @param output The output block, which must consist of at - * least 16 words. - * @param key The buffer containing the key. - * @param offset Offset of the key in the buffer. - */ - public static void initKey256(int[] output, byte[] key, int offset) - { - output[0] = char4('e', 'x', 'p', 'a'); - output[1] = char4('n', 'd', ' ', '3'); - output[2] = char4('2', '-', 'b', 'y'); - output[3] = char4('t', 'e', ' ', 'k'); - output[4] = fromLittleEndian(key, offset); - output[5] = fromLittleEndian(key, offset + 4); - output[6] = fromLittleEndian(key, offset + 8); - output[7] = fromLittleEndian(key, offset + 12); - output[8] = fromLittleEndian(key, offset + 16); - output[9] = fromLittleEndian(key, offset + 20); - output[10] = fromLittleEndian(key, offset + 24); - output[11] = fromLittleEndian(key, offset + 28); - output[12] = 0; - output[13] = 0; - output[14] = 0; - output[15] = 0; - } - - /** - * Initializes the 64-bit initialization vector in a ChaCha20 block. - * - * @param output The output block, which must consist of at - * least 16 words and must have been initialized by initKey256() - * or initKey128(). - * @param iv The 64-bit initialization vector value. - * - * The counter portion of the output block is set to zero. - */ - public static void initIV(int[] output, long iv) - { - output[12] = 0; - output[13] = 0; - output[14] = (int)iv; - output[15] = (int)(iv >> 32); - } - - /** - * Initializes the 64-bit initialization vector and counter in a ChaCha20 block. - * - * @param output The output block, which must consist of at - * least 16 words and must have been initialized by initKey256() - * or initKey128(). - * @param iv The 64-bit initialization vector value. - * @param counter The 64-bit counter value. - */ - public static void initIV(int[] output, long iv, long counter) - { - output[12] = (int)counter; - output[13] = (int)(counter >> 32); - output[14] = (int)iv; - output[15] = (int)(iv >> 32); - } - - private static int leftRotate16(int v) - { - return v << 16 | (v >>> 16); - } - - private static int leftRotate12(int v) - { - return v << 12 | (v >>> 20); - } - - private static int leftRotate8(int v) - { - return v << 8 | (v >>> 24); - } - - private static int leftRotate7(int v) - { - return v << 7 | (v >>> 25); - } - - private static void quarterRound(int[] v, int a, int b, int c, int d) - { - v[a] += v[b]; - v[d] = leftRotate16(v[d] ^ v[a]); - v[c] += v[d]; - v[b] = leftRotate12(v[b] ^ v[c]); - v[a] += v[b]; - v[d] = leftRotate8(v[d] ^ v[a]); - v[c] += v[d]; - v[b] = leftRotate7(v[b] ^ v[c]); - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/Curve25519.java b/src/main/java/com/southernstorm/noise/crypto/Curve25519.java deleted file mode 100644 index 5183e2260..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/Curve25519.java +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.crypto; - -import java.util.Arrays; - -/** - * Implementation of the Curve25519 elliptic curve algorithm. - * - * This implementation is based on that from arduinolibs: - * https://github.com/rweather/arduinolibs - * - * Differences in this version are due to using 26-bit limbs for the - * representation instead of the 8/16/32-bit limbs in the original. - * - * References: http://cr.yp.to/ecdh.html, RFC 7748 - */ -public final class Curve25519 { - - // Numbers modulo 2^255 - 19 are broken up into ten 26-bit words. - private static final int NUM_LIMBS_255BIT = 10; - private static final int NUM_LIMBS_510BIT = 20; - private int[] x_1; - private int[] x_2; - private int[] x_3; - private int[] z_2; - private int[] z_3; - private int[] A; - private int[] B; - private int[] C; - private int[] D; - private int[] E; - private int[] AA; - private int[] BB; - private int[] DA; - private int[] CB; - private long[] t1; - private int[] t2; - - /** - * Constructs the temporary state holder for Curve25519 evaluation. - */ - private Curve25519() - { - // Allocate memory for all of the temporary variables we will need. - x_1 = new int [NUM_LIMBS_255BIT]; - x_2 = new int [NUM_LIMBS_255BIT]; - x_3 = new int [NUM_LIMBS_255BIT]; - z_2 = new int [NUM_LIMBS_255BIT]; - z_3 = new int [NUM_LIMBS_255BIT]; - A = new int [NUM_LIMBS_255BIT]; - B = new int [NUM_LIMBS_255BIT]; - C = new int [NUM_LIMBS_255BIT]; - D = new int [NUM_LIMBS_255BIT]; - E = new int [NUM_LIMBS_255BIT]; - AA = new int [NUM_LIMBS_255BIT]; - BB = new int [NUM_LIMBS_255BIT]; - DA = new int [NUM_LIMBS_255BIT]; - CB = new int [NUM_LIMBS_255BIT]; - t1 = new long [NUM_LIMBS_510BIT]; - t2 = new int [NUM_LIMBS_510BIT]; - } - - - /** - * Destroy all sensitive data in this object. - */ - private void destroy() { - // Destroy all temporary variables. - Arrays.fill(x_1, 0); - Arrays.fill(x_2, 0); - Arrays.fill(x_3, 0); - Arrays.fill(z_2, 0); - Arrays.fill(z_3, 0); - Arrays.fill(A, 0); - Arrays.fill(B, 0); - Arrays.fill(C, 0); - Arrays.fill(D, 0); - Arrays.fill(E, 0); - Arrays.fill(AA, 0); - Arrays.fill(BB, 0); - Arrays.fill(DA, 0); - Arrays.fill(CB, 0); - Arrays.fill(t1, 0L); - Arrays.fill(t2, 0); - } - - /** - * Reduces a number modulo 2^255 - 19 where it is known that the - * number can be reduced with only 1 trial subtraction. - * - * @param x The number to reduce, and the result. - */ - private void reduceQuick(int[] x) - { - int index, carry; - - // Perform a trial subtraction of (2^255 - 19) from "x" which is - // equivalent to adding 19 and subtracting 2^255. We add 19 here; - // the subtraction of 2^255 occurs in the next step. - carry = 19; - for (index = 0; index < NUM_LIMBS_255BIT; ++index) { - carry += x[index]; - t2[index] = carry & 0x03FFFFFF; - carry >>= 26; - } - - // If there was a borrow, then the original "x" is the correct answer. - // If there was no borrow, then "t2" is the correct answer. Select the - // correct answer but do it in a way that instruction timing will not - // reveal which value was selected. Borrow will occur if bit 21 of - // "t2" is zero. Turn the bit into a selection mask. - int mask = -((t2[NUM_LIMBS_255BIT - 1] >> 21) & 0x01); - int nmask = ~mask; - t2[NUM_LIMBS_255BIT - 1] &= 0x001FFFFF; - for (index = 0; index < NUM_LIMBS_255BIT; ++index) - x[index] = (x[index] & nmask) | (t2[index] & mask); - } - - /** - * Reduce a number modulo 2^255 - 19. - * - * @param result The result. - * @param x The value to be reduced. This array will be - * modified during the reduction. - * @param size The number of limbs in the high order half of x. - */ - private void reduce(int[] result, int[] x, int size) - { - int index, limb, carry; - - // Calculate (x mod 2^255) + ((x / 2^255) * 19) which will - // either produce the answer we want or it will produce a - // value of the form "answer + j * (2^255 - 19)". There are - // 5 left-over bits in the top-most limb of the bottom half. - carry = 0; - limb = x[NUM_LIMBS_255BIT - 1] >> 21; - x[NUM_LIMBS_255BIT - 1] &= 0x001FFFFF; - for (index = 0; index < size; ++index) { - limb += x[NUM_LIMBS_255BIT + index] << 5; - carry += (limb & 0x03FFFFFF) * 19 + x[index]; - x[index] = carry & 0x03FFFFFF; - limb >>= 26; - carry >>= 26; - } - if (size < NUM_LIMBS_255BIT) { - // The high order half of the number is short; e.g. for mulA24(). - // Propagate the carry through the rest of the low order part. - for (index = size; index < NUM_LIMBS_255BIT; ++index) { - carry += x[index]; - x[index] = carry & 0x03FFFFFF; - carry >>= 26; - } - } - - // The "j" value may still be too large due to the final carry-out. - // We must repeat the reduction. If we already have the answer, - // then this won't do any harm but we must still do the calculation - // to preserve the overall timing. The "j" value will be between - // 0 and 19, which means that the carry we care about is in the - // top 5 bits of the highest limb of the bottom half. - carry = (x[NUM_LIMBS_255BIT - 1] >> 21) * 19; - x[NUM_LIMBS_255BIT - 1] &= 0x001FFFFF; - for (index = 0; index < NUM_LIMBS_255BIT; ++index) { - carry += x[index]; - result[index] = carry & 0x03FFFFFF; - carry >>= 26; - } - - // At this point "x" will either be the answer or it will be the - // answer plus (2^255 - 19). Perform a trial subtraction to - // complete the reduction process. - reduceQuick(result); - } - - /** - * Multiplies two numbers modulo 2^255 - 19. - * - * @param result The result. - * @param x The first number to multiply. - * @param y The second number to multiply. - */ - private void mul(int[] result, int[] x, int[] y) - { - int i, j; - - // Multiply the two numbers to create the intermediate result. - long v = x[0]; - for (i = 0; i < NUM_LIMBS_255BIT; ++i) { - t1[i] = v * y[i]; - } - for (i = 1; i < NUM_LIMBS_255BIT; ++i) { - v = x[i]; - for (j = 0; j < (NUM_LIMBS_255BIT - 1); ++j) { - t1[i + j] += v * y[j]; - } - t1[i + NUM_LIMBS_255BIT - 1] = v * y[NUM_LIMBS_255BIT - 1]; - } - - // Propagate carries and convert back into 26-bit words. - v = t1[0]; - t2[0] = ((int)v) & 0x03FFFFFF; - for (i = 1; i < NUM_LIMBS_510BIT; ++i) { - v = (v >> 26) + t1[i]; - t2[i] = ((int)v) & 0x03FFFFFF; - } - - // Reduce the result modulo 2^255 - 19. - reduce(result, t2, NUM_LIMBS_255BIT); - } - - /** - * Squares a number modulo 2^255 - 19. - * - * @param result The result. - * @param x The number to square. - */ - private void square(int[] result, int[] x) - { - mul(result, x, x); - } - - /** - * Multiplies a number by the a24 constant, modulo 2^255 - 19. - * - * @param result The result. - * @param x The number to multiply by a24. - */ - private void mulA24(int[] result, int[] x) - { - long a24 = 121665; - long carry = 0; - int index; - for (index = 0; index < NUM_LIMBS_255BIT; ++index) { - carry += a24 * x[index]; - t2[index] = ((int)carry) & 0x03FFFFFF; - carry >>= 26; - } - t2[NUM_LIMBS_255BIT] = ((int)carry) & 0x03FFFFFF; - reduce(result, t2, 1); - } - - /** - * Adds two numbers modulo 2^255 - 19. - * - * @param result The result. - * @param x The first number to add. - * @param y The second number to add. - */ - private void add(int[] result, int[] x, int[] y) - { - int index, carry; - carry = x[0] + y[0]; - result[0] = carry & 0x03FFFFFF; - for (index = 1; index < NUM_LIMBS_255BIT; ++index) { - carry = (carry >> 26) + x[index] + y[index]; - result[index] = carry & 0x03FFFFFF; - } - reduceQuick(result); - } - - /** - * Subtracts two numbers modulo 2^255 - 19. - * - * @param result The result. - * @param x The first number to subtract. - * @param y The second number to subtract. - */ - private void sub(int[] result, int[] x, int[] y) - { - int index, borrow; - - // Subtract y from x to generate the intermediate result. - borrow = 0; - for (index = 0; index < NUM_LIMBS_255BIT; ++index) { - borrow = x[index] - y[index] - ((borrow >> 26) & 0x01); - result[index] = borrow & 0x03FFFFFF; - } - - // If we had a borrow, then the result has gone negative and we - // have to add 2^255 - 19 to the result to make it positive again. - // The top bits of "borrow" will be all 1's if there is a borrow - // or it will be all 0's if there was no borrow. Easiest is to - // conditionally subtract 19 and then mask off the high bits. - borrow = result[0] - ((-((borrow >> 26) & 0x01)) & 19); - result[0] = borrow & 0x03FFFFFF; - for (index = 1; index < NUM_LIMBS_255BIT; ++index) { - borrow = result[index] - ((borrow >> 26) & 0x01); - result[index] = borrow & 0x03FFFFFF; - } - result[NUM_LIMBS_255BIT - 1] &= 0x001FFFFF; - } - - /** - * Conditional swap of two values. - * - * @param select Set to 1 to swap, 0 to leave as-is. - * @param x The first value. - * @param y The second value. - */ - private static void cswap(int select, int[] x, int[] y) - { - int dummy; - select = -select; - for (int index = 0; index < NUM_LIMBS_255BIT; ++index) { - dummy = select & (x[index] ^ y[index]); - x[index] ^= dummy; - y[index] ^= dummy; - } - } - - /** - * Raise x to the power of (2^250 - 1). - * - * @param result The result. Must not overlap with x. - * @param x The argument. - */ - private void pow250(int[] result, int[] x) - { - int i, j; - - // The big-endian hexadecimal expansion of (2^250 - 1) is: - // 03FFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF - // - // The naive implementation needs to do 2 multiplications per 1 bit and - // 1 multiplication per 0 bit. We can improve upon this by creating a - // pattern 0000000001 ... 0000000001. If we square and multiply the - // pattern by itself we can turn the pattern into the partial results - // 0000000011 ... 0000000011, 0000000111 ... 0000000111, etc. - // This averages out to about 1.1 multiplications per 1 bit instead of 2. - - // Build a pattern of 250 bits in length of repeated copies of 0000000001. - square(A, x); - for (j = 0; j < 9; ++j) - square(A, A); - mul(result, A, x); - for (i = 0; i < 23; ++i) { - for (j = 0; j < 10; ++j) - square(A, A); - mul(result, result, A); - } - - // Multiply bit-shifted versions of the 0000000001 pattern into - // the result to "fill in" the gaps in the pattern. - square(A, result); - mul(result, result, A); - for (j = 0; j < 8; ++j) { - square(A, A); - mul(result, result, A); - } - } - - /** - * Computes the reciprocal of a number modulo 2^255 - 19. - * - * @param result The result. Must not overlap with x. - * @param x The argument. - */ - private void recip(int[] result, int[] x) - { - // The reciprocal is the same as x ^ (p - 2) where p = 2^255 - 19. - // The big-endian hexadecimal expansion of (p - 2) is: - // 7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFEB - // Start with the 250 upper bits of the expansion of (p - 2). - pow250(result, x); - - // Deal with the 5 lowest bits of (p - 2), 01011, from highest to lowest. - square(result, result); - square(result, result); - mul(result, result, x); - square(result, result); - square(result, result); - mul(result, result, x); - square(result, result); - mul(result, result, x); - } - - /** - * Evaluates the curve for every bit in a secret key. - * - * @param s The 32-byte secret key. - */ - private void evalCurve(byte[] s) - { - int sposn = 31; - int sbit = 6; - int svalue = s[sposn] | 0x40; - int swap = 0; - int select; - - // Iterate over all 255 bits of "s" from the highest to the lowest. - // We ignore the high bit of the 256-bit representation of "s". - for (;;) { - // Conditional swaps on entry to this bit but only if we - // didn't swap on the previous bit. - select = (svalue >> sbit) & 0x01; - swap ^= select; - cswap(swap, x_2, x_3); - cswap(swap, z_2, z_3); - swap = select; - - // Evaluate the curve. - add(A, x_2, z_2); // A = x_2 + z_2 - square(AA, A); // AA = A^2 - sub(B, x_2, z_2); // B = x_2 - z_2 - square(BB, B); // BB = B^2 - sub(E, AA, BB); // E = AA - BB - add(C, x_3, z_3); // C = x_3 + z_3 - sub(D, x_3, z_3); // D = x_3 - z_3 - mul(DA, D, A); // DA = D * A - mul(CB, C, B); // CB = C * B - add(x_3, DA, CB); // x_3 = (DA + CB)^2 - square(x_3, x_3); - sub(z_3, DA, CB); // z_3 = x_1 * (DA - CB)^2 - square(z_3, z_3); - mul(z_3, z_3, x_1); - mul(x_2, AA, BB); // x_2 = AA * BB - mulA24(z_2, E); // z_2 = E * (AA + a24 * E) - add(z_2, z_2, AA); - mul(z_2, z_2, E); - - // Move onto the next lower bit of "s". - if (sbit > 0) { - --sbit; - } else if (sposn == 0) { - break; - } else if (sposn == 1) { - --sposn; - svalue = s[sposn] & 0xF8; - sbit = 7; - } else { - --sposn; - svalue = s[sposn]; - sbit = 7; - } - } - - // Final conditional swaps. - cswap(swap, x_2, x_3); - cswap(swap, z_2, z_3); - } - - /** - * Evaluates the Curve25519 curve. - * - * @param result Buffer to place the result of the evaluation into. - * @param offset Offset into the result buffer. - * @param privateKey The private key to use in the evaluation. - * @param publicKey The public key to use in the evaluation, or null - * if the base point of the curve should be used. - */ - public static void eval(byte[] result, int offset, byte[] privateKey, byte[] publicKey) - { - Curve25519 state = new Curve25519(); - try { - // Unpack the public key value. If null, use 9 as the base point. - Arrays.fill(state.x_1, 0); - if (publicKey != null) { - // Convert the input value from little-endian into 26-bit limbs. - for (int index = 0; index < 32; ++index) { - int bit = (index * 8) % 26; - int word = (index * 8) / 26; - int value = publicKey[index] & 0xFF; - if (bit <= (26 - 8)) { - state.x_1[word] |= value << bit; - } else { - state.x_1[word] |= value << bit; - state.x_1[word] &= 0x03FFFFFF; - state.x_1[word + 1] |= value >> (26 - bit); - } - } - - // Just in case, we reduce the number modulo 2^255 - 19 to - // make sure that it is in range of the field before we start. - // This eliminates values between 2^255 - 19 and 2^256 - 1. - state.reduceQuick(state.x_1); - state.reduceQuick(state.x_1); - } else { - state.x_1[0] = 9; - } - - // Initialize the other temporary variables. - Arrays.fill(state.x_2, 0); // x_2 = 1 - state.x_2[0] = 1; - Arrays.fill(state.z_2, 0); // z_2 = 0 - System.arraycopy(state.x_1, 0, state.x_3, 0, state.x_1.length); // x_3 = x_1 - Arrays.fill(state.z_3, 0); // z_3 = 1 - state.z_3[0] = 1; - - // Evaluate the curve for every bit of the private key. - state.evalCurve(privateKey); - - // Compute x_2 * (z_2 ^ (p - 2)) where p = 2^255 - 19. - state.recip(state.z_3, state.z_2); - state.mul(state.x_2, state.x_2, state.z_3); - - // Convert x_2 into little-endian in the result buffer. - for (int index = 0; index < 32; ++index) { - int bit = (index * 8) % 26; - int word = (index * 8) / 26; - if (bit <= (26 - 8)) - result[offset + index] = (byte)(state.x_2[word] >> bit); - else - result[offset + index] = (byte)((state.x_2[word] >> bit) | (state.x_2[word + 1] << (26 - bit))); - } - } finally { - // Clean up all temporary state before we exit. - state.destroy(); - } - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/Curve448.java b/src/main/java/com/southernstorm/noise/crypto/Curve448.java deleted file mode 100644 index 13102bc85..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/Curve448.java +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -/* - -Portions of this code were extracted from the p448/arch_32 field -arithmetic implementation in Ed448-Goldilocks and converted from -C into Java. The LICENSE.txt file for the imported code follows: - ----- -The MIT License (MIT) - -Copyright (c) 2011 Stanford University. -Copyright (c) 2014 Cryptography Research, Inc. - -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: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -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. ----- - -*/ - -package com.southernstorm.noise.crypto; - -import java.util.Arrays; - -/** - * Implementation of the Curve448 elliptic curve algorithm. - * - * Reference: RFC 7748 - */ -public final class Curve448 { - - // Numbers modulo 2^448 - 2^224 - 1 are broken up into sixteen 28-bit words. - private int[] x_1; - private int[] x_2; - private int[] x_3; - private int[] z_2; - private int[] z_3; - private int[] A; - private int[] B; - private int[] C; - private int[] D; - private int[] E; - private int[] AA; - private int[] BB; - private int[] DA; - private int[] CB; - private int[] aa; - private int[] bb; - - /** - * Constructs the temporary state holder for Curve448 evaluation. - */ - private Curve448() - { - // Allocate memory for all of the temporary variables we will need. - x_1 = new int [16]; - x_2 = new int [16]; - x_3 = new int [16]; - z_2 = new int [16]; - z_3 = new int [16]; - A = new int [16]; - B = new int [16]; - C = new int [16]; - D = new int [16]; - E = new int [16]; - AA = new int [16]; - BB = new int [16]; - DA = new int [16]; - CB = new int [16]; - aa = new int [8]; - bb = new int [8]; - } - - /** - * Destroy all sensitive data in this object. - */ - private void destroy() { - // Destroy all temporary variables. - Arrays.fill(x_1, 0); - Arrays.fill(x_2, 0); - Arrays.fill(x_3, 0); - Arrays.fill(z_2, 0); - Arrays.fill(z_3, 0); - Arrays.fill(A, 0); - Arrays.fill(B, 0); - Arrays.fill(C, 0); - Arrays.fill(D, 0); - Arrays.fill(E, 0); - Arrays.fill(AA, 0); - Arrays.fill(BB, 0); - Arrays.fill(DA, 0); - Arrays.fill(CB, 0); - Arrays.fill(aa, 0); - Arrays.fill(bb, 0); - } - - /* Beginning of code imported from Ed448-Goldilocks */ - - private static long widemul_32(int a, int b) - { - return ((long)a) * b; - } - - // p448_mul() - private void mul(int[] c, int[] a, int[] b) - { - long accum0 = 0, accum1 = 0, accum2 = 0; - int mask = (1<<28) - 1; - - int i,j; - for (i=0; i<8; i++) { - aa[i] = a[i] + a[i+8]; - bb[i] = b[i] + b[i+8]; - } - - for (j=0; j<8; j++) { - accum2 = 0; - - for (i=0; i<=j; i++) { - accum2 += widemul_32(a[j-i],b[i]); - accum1 += widemul_32(aa[j-i],bb[i]); - accum0 += widemul_32(a[8+j-i], b[8+i]); - } - - accum1 -= accum2; - accum0 += accum2; - accum2 = 0; - - for (; i<8; i++) { - accum0 -= widemul_32(a[8+j-i], b[i]); - accum2 += widemul_32(aa[8+j-i], bb[i]); - accum1 += widemul_32(a[16+j-i], b[8+i]); - } - - accum1 += accum2; - accum0 += accum2; - - c[j] = ((int)(accum0)) & mask; - c[j+8] = ((int)(accum1)) & mask; - - accum0 >>>= 28; - accum1 >>>= 28; - } - - accum0 += accum1; - accum0 += c[8]; - accum1 += c[0]; - c[8] = ((int)(accum0)) & mask; - c[0] = ((int)(accum1)) & mask; - - accum0 >>>= 28; - accum1 >>>= 28; - c[9] += ((int)(accum0)); - c[1] += ((int)(accum1)); - } - - // p448_mulw() - private static void mulw(int[] c, int[] a, long b) - { - int bhi = (int)(b>>28), blo = ((int)b) & ((1<<28)-1); - - long accum0, accum8; - int mask = (1<<28) - 1; - - int i; - - accum0 = widemul_32(blo, a[0]); - accum8 = widemul_32(blo, a[8]); - accum0 += widemul_32(bhi, a[15]); - accum8 += widemul_32(bhi, a[15] + a[7]); - - c[0] = ((int)accum0) & mask; accum0 >>>= 28; - c[8] = ((int)accum8) & mask; accum8 >>>= 28; - - for (i=1; i<8; i++) { - accum0 += widemul_32(blo, a[i]); - accum8 += widemul_32(blo, a[i+8]); - - accum0 += widemul_32(bhi, a[i-1]); - accum8 += widemul_32(bhi, a[i+7]); - - c[i] = ((int)accum0) & mask; accum0 >>>= 28; - c[i+8] = ((int)accum8) & mask; accum8 >>>= 28; - } - - accum0 += accum8 + c[8]; - c[8] = ((int)accum0) & mask; - c[9] += accum0 >>> 28; - - accum8 += c[0]; - c[0] = ((int)accum8) & mask; - c[1] += accum8 >>> 28; - } - - // p448_weak_reduce - private static void weak_reduce(int[] a) - { - int mask = (1<<28) - 1; - int tmp = a[15] >>> 28; - int i; - a[8] += tmp; - for (i=15; i>0; i--) { - a[i] = (a[i] & mask) + (a[i-1]>>>28); - } - a[0] = (a[0] & mask) + tmp; - } - - // p448_strong_reduce - private static void strong_reduce(int[] a) - { - int mask = (1<<28) - 1; - - /* first, clear high */ - a[8] += a[15]>>>28; - a[0] += a[15]>>>28; - a[15] &= mask; - - /* now the total is less than 2^448 - 2^(448-56) + 2^(448-56+8) < 2p */ - - /* compute total_value - p. No need to reduce mod p. */ - - long scarry = 0; - int i; - for (i=0; i<16; i++) { - scarry = scarry + (a[i] & 0xFFFFFFFFL) - ((i==8)?mask-1:mask); - a[i] = (int)(scarry & mask); - scarry >>= 28; - } - - /* uncommon case: it was >= p, so now scarry = 0 and this = x - * common case: it was < p, so now scarry = -1 and this = x - p + 2^448 - * so let's add back in p. will carry back off the top for 2^448. - */ - - int scarry_mask = (int)(scarry & mask); - long carry = 0; - - /* add it back */ - for (i=0; i<16; i++) { - carry = carry + (a[i] & 0xFFFFFFFFL) + ((i==8)?(scarry_mask&~1):scarry_mask); - a[i] = (int)(carry & mask); - carry >>>= 28; - } - } - - // field_add() - private static void add(int[] out, int[] a, int[] b) - { - for (int i = 0; i < 16; ++i) - out[i] = a[i] + b[i]; - weak_reduce(out); - } - - // field_sub() - private static void sub(int[] out, int[] a, int[] b) - { - int i; - - // p448_sub_RAW(out, a, b) - for (i = 0; i < 16; ++i) - out[i] = a[i] - b[i]; - - // p448_bias(out, 2) - int co1 = ((1 << 28) - 1) * 2; - int co2 = co1 - 2; - for (i = 0; i < 16; ++i) { - if (i != 8) - out[i] += co1; - else - out[i] += co2; - } - - weak_reduce(out); - } - - // p448_serialize() - private static void serialize(byte[] serial, int offset, int[] x) - { - int i,j; - for (i=0; i<8; i++) { - long limb = x[2*i] + (((long)x[2*i+1])<<28); - for (j=0; j<7; j++) { - serial[offset+7*i+j] = (byte)limb; - limb >>= 8; - } - } - } - - private static int is_zero(int x) - { - long xx = x & 0xFFFFFFFFL; - xx--; - return (int)(xx >> 32); - } - - // p448_deserialize() - private static int deserialize(int[] x, byte[] serial, int offset) - { - int i,j; - for (i=0; i<8; i++) { - long out = 0; - for (j=0; j<7; j++) { - out |= (serial[offset+7*i+j] & 0xFFL)<<(8*j); - } - x[2*i] = ((int)out) & ((1<<28)-1); - x[2*i+1] = (int)(out >>> 28); - } - - /* Check for reduction. - * - * The idea is to create a variable ge which is all ones (rather, 56 ones) - * if and only if the low $i$ words of $x$ are >= those of p. - * - * Remember p = little_endian(1111,1111,1111,1111,1110,1111,1111,1111) - */ - int ge = -1, mask = (1<<28)-1; - for (i=0; i<8; i++) { - ge &= x[i]; - } - - /* At this point, ge = 1111 iff bottom are all 1111. Now propagate if 1110, or set if 1111 */ - ge = (ge & (x[8] + 1)) | is_zero(x[8] ^ mask); - - /* Propagate the rest */ - for (i=9; i<16; i++) { - ge &= x[i]; - } - - return ~is_zero(ge ^ mask); - } - - /* End of code imported from Ed448-Goldilocks */ - - /** - * Squares a number modulo 2^448 - 2^224 - 1. - * - * @param result The result. - * @param x The number to square. - */ - private void square(int[] result, int[] x) - { - mul(result, x, x); - } - - /** - * Conditional swap of two values. - * - * @param select Set to 1 to swap, 0 to leave as-is. - * @param x The first value. - * @param y The second value. - */ - private static void cswap(int select, int[] x, int[] y) - { - int dummy; - select = -select; - for (int index = 0; index < 16; ++index) { - dummy = select & (x[index] ^ y[index]); - x[index] ^= dummy; - y[index] ^= dummy; - } - } - - /** - * Computes the reciprocal of a number modulo 2^448 - 2^224 - 1. - * - * @param result The result. Must not overlap with z_2. - * @param z_2 The argument. - */ - private void recip(int[] result, int[] z_2) - { - int posn; - - /* Compute z_2 ^ (p - 2) - - The value p - 2 is: FF...FEFF...FD, which from highest to lowest is - 223 one bits, followed by a zero bit, followed by 222 one bits, - followed by another zero bit, and a final one bit. - - The naive implementation that squares for every bit and multiplies - for every 1 bit requires 893 multiplications. The following can - do the same operation in 483 multiplications. The basic idea is to - create bit patterns and then "shift" them into position. We start - with a 4 bit pattern 1111, which we can square 4 times to get - 11110000 and then multiply by the 1111 pattern to get 11111111. - We then repeat that to turn 11111111 into 1111111111111111, etc. - */ - square(B, z_2); /* Set A to a 4 bit pattern */ - mul(A, B, z_2); - square(B, A); - mul(A, B, z_2); - square(B, A); - mul(A, B, z_2); - square(B, A); /* Set C to a 6 bit pattern */ - mul(C, B, z_2); - square(B, C); - mul(C, B, z_2); - square(B, C); /* Set A to a 8 bit pattern */ - mul(A, B, z_2); - square(B, A); - mul(A, B, z_2); - square(E, A); /* Set E to a 16 bit pattern */ - square(B, E); - for (posn = 1; posn < 4; ++posn) { - square(E, B); - square(B, E); - } - mul(E, B, A); - square(AA, E); /* Set AA to a 32 bit pattern */ - square(B, AA); - for (posn = 1; posn < 8; ++posn) { - square(AA, B); - square(B, AA); - } - mul(AA, B, E); - square(BB, AA); /* Set BB to a 64 bit pattern */ - square(B, BB); - for (posn = 1; posn < 16; ++posn) { - square(BB, B); - square(B, BB); - } - mul(BB, B, AA); - square(DA, BB); /* Set DA to a 128 bit pattern */ - square(B, DA); - for (posn = 1; posn < 32; ++posn) { - square(DA, B); - square(B, DA); - } - mul(DA, B, BB); - square(CB, DA); /* Set CB to a 192 bit pattern */ - square(B, CB); /* 192 = 128 + 64 */ - for (posn = 1; posn < 32; ++posn) { - square(CB, B); - square(B, CB); - } - mul(CB, B, BB); - square(DA, CB); /* Set DA to a 208 bit pattern */ - square(B, DA); /* 208 = 128 + 64 + 16 */ - for (posn = 1; posn < 8; ++posn) { - square(DA, B); - square(B, DA); - } - mul(DA, B, E); - square(CB, DA); /* Set CB to a 216 bit pattern */ - square(B, CB); /* 216 = 128 + 64 + 16 + 8 */ - for (posn = 1; posn < 4; ++posn) { - square(CB, B); - square(B, CB); - } - mul(CB, B, A); - square(DA, CB); /* Set DA to a 222 bit pattern */ - square(B, DA); /* 222 = 128 + 64 + 16 + 8 + 6 */ - for (posn = 1; posn < 3; ++posn) { - square(DA, B); - square(B, DA); - } - mul(DA, B, C); - square(CB, DA); /* Set CB to a 224 bit pattern */ - mul(B, CB, z_2); /* CB = DA|1|0 */ - square(CB, B); - square(BB, CB); /* Set BB to a 446 bit pattern */ - square(B, BB); /* BB = DA|1|0|DA */ - for (posn = 1; posn < 111; ++posn) { - square(BB, B); - square(B, BB); - } - mul(BB, B, DA); - square(B, BB); /* Set result to a 448 bit pattern */ - square(BB, B); /* result = DA|1|0|DA|01 */ - mul(result, BB, z_2); - } - - /** - * Evaluates the curve for every bit in a secret key. - * - * @param s The 56-byte secret key. - */ - private void evalCurve(byte[] s) - { - int sposn = 55; - int sbit = 7; - int svalue = s[sposn] | 0x80; - int swap = 0; - int select; - - // Iterate over all 448 bits of "s" from the highest to the lowest. - for (;;) { - // Conditional swaps on entry to this bit but only if we - // didn't swap on the previous bit. - select = (svalue >> sbit) & 0x01; - swap ^= select; - cswap(swap, x_2, x_3); - cswap(swap, z_2, z_3); - swap = select; - - // Evaluate the curve. - add(A, x_2, z_2); // A = x_2 + z_2 - square(AA, A); // AA = A^2 - sub(B, x_2, z_2); // B = x_2 - z_2 - square(BB, B); // BB = B^2 - sub(E, AA, BB); // E = AA - BB - add(C, x_3, z_3); // C = x_3 + z_3 - sub(D, x_3, z_3); // D = x_3 - z_3 - mul(DA, D, A); // DA = D * A - mul(CB, C, B); // CB = C * B - add(z_2, DA, CB); // x_3 = (DA + CB)^2 - square(x_3, z_2); - sub(z_2, DA, CB); // z_3 = x_1 * (DA - CB)^2 - square(x_2, z_2); - mul(z_3, x_1, x_2); - mul(x_2, AA, BB); // x_2 = AA * BB - mulw(z_2, E, 39081); // z_2 = E * (AA + a24 * E) - add(A, AA, z_2); - mul(z_2, E, A); - - // Move onto the next lower bit of "s". - if (sbit > 0) { - --sbit; - } else if (sposn == 0) { - break; - } else if (sposn == 1) { - --sposn; - svalue = s[sposn] & 0xFC; - sbit = 7; - } else { - --sposn; - svalue = s[sposn]; - sbit = 7; - } - } - - // Final conditional swaps. - cswap(swap, x_2, x_3); - cswap(swap, z_2, z_3); - } - - /** - * Evaluates the Curve448 curve. - * - * @param result Buffer to place the result of the evaluation into. - * @param offset Offset into the result buffer. - * @param privateKey The private key to use in the evaluation. - * @param publicKey The public key to use in the evaluation, or null - * if the base point of the curve should be used. - * @return Returns true if the curve evaluation was successful, - * false if the publicKey value is out of range. - */ - public static boolean eval(byte[] result, int offset, byte[] privateKey, byte[] publicKey) - { - Curve448 state = new Curve448(); - int success = -1; - try { - // Unpack the public key value. If null, use 5 as the base point. - Arrays.fill(state.x_1, 0); - if (publicKey != null) { - // Convert the input value from little-endian into 28-bit limbs. - // It is possible that the public key is out of range. If so, - // delay reporting that state until the function completes. - success = deserialize(state.x_1, publicKey, 0); - } else { - state.x_1[0] = 5; - } - - // Initialize the other temporary variables. - Arrays.fill(state.x_2, 0); // x_2 = 1 - state.x_2[0] = 1; - Arrays.fill(state.z_2, 0); // z_2 = 0 - System.arraycopy(state.x_1, 0, state.x_3, 0, state.x_1.length); // x_3 = x_1 - Arrays.fill(state.z_3, 0); // z_3 = 1 - state.z_3[0] = 1; - - // Evaluate the curve for every bit of the private key. - state.evalCurve(privateKey); - - // Compute x_2 * (z_2 ^ (p - 2)) where p = 2^448 - 2^224 - 1. - state.recip(state.z_3, state.z_2); - state.mul(state.x_1, state.x_2, state.z_3); - - // Convert x_2 into little-endian in the result buffer. - strong_reduce(state.x_1); - serialize(result, offset, state.x_1); - } finally { - // Clean up all temporary state before we exit. - state.destroy(); - } - return (success & 0x01) != 0; - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/GHASH.java b/src/main/java/com/southernstorm/noise/crypto/GHASH.java deleted file mode 100644 index d7b82888c..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/GHASH.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.crypto; - -import com.southernstorm.noise.protocol.Destroyable; - -import java.util.Arrays; - -/** - * Implementation of the GHASH primitive for GCM. - */ -public final class GHASH implements Destroyable { - - private long[] H; - private byte[] Y; - int posn; - - /** - * Constructs a new GHASH object. - */ - public GHASH() - { - H = new long [2]; - Y = new byte [16]; - posn = 0; - } - - /** - * Resets this GHASH object with a new key. - * - * @param key The key, which must contain at least 16 bytes. - * @param offset The offset of the first key byte. - */ - public void reset(byte[] key, int offset) - { - H[0] = readBigEndian(key, offset); - H[1] = readBigEndian(key, offset + 8); - Arrays.fill(Y, (byte)0); - posn = 0; - } - - /** - * Resets the GHASH object but retains the previous key. - */ - public void reset() - { - Arrays.fill(Y, (byte)0); - posn = 0; - } - - /** - * Updates this GHASH object with more data. - * - * @param data Buffer containing the data. - * @param offset Offset of the first data byte in the buffer. - * @param length The number of bytes from the buffer to hash. - */ - public void update(byte[] data, int offset, int length) - { - while (length > 0) { - int size = 16 - posn; - if (size > length) - size = length; - for (int index = 0; index < size; ++index) - Y[posn + index] ^= data[offset + index]; - posn += size; - length -= size; - offset += size; - if (posn == 16) { - GF128_mul(Y, H); - posn = 0; - } - } - } - - /** - * Finishes the GHASH process and returns the tag. - * - * @param tag Buffer to receive the tag. - * @param offset Offset of the first byte of the tag. - * @param length The length of the tag, which must be less - * than or equal to 16. - */ - public void finish(byte[] tag, int offset, int length) - { - pad(); - System.arraycopy(Y, 0, tag, offset, length); - } - - /** - * Pads the input to a 16-byte boundary. - */ - public void pad() - { - if (posn != 0) { - // Padding involves XOR'ing the rest of state->Y with zeroes, - // which does nothing. Immediately process the next chunk. - GF128_mul(Y, H); - posn = 0; - } - } - - /** - * Pads the input to a 16-byte boundary and then adds a block - * containing the AD and data lengths. - * - * @param adLen Length of the associated data in bytes. - * @param dataLen Length of the data in bytes. - */ - public void pad(long adLen, long dataLen) - { - byte[] temp = new byte [16]; - try { - pad(); - writeBigEndian(temp, 0, adLen * 8); - writeBigEndian(temp, 8, dataLen * 8); - update(temp, 0, 16); - } finally { - Arrays.fill(temp, (byte)0); - } - } - - @Override - public void destroy() { - Arrays.fill(H, 0L); - Arrays.fill(Y, (byte)0); - } - - private static long readBigEndian(byte[] buf, int offset) - { - return ((buf[offset] & 0xFFL) << 56) | - ((buf[offset + 1] & 0xFFL) << 48) | - ((buf[offset + 2] & 0xFFL) << 40) | - ((buf[offset + 3] & 0xFFL) << 32) | - ((buf[offset + 4] & 0xFFL) << 24) | - ((buf[offset + 5] & 0xFFL) << 16) | - ((buf[offset + 6] & 0xFFL) << 8) | - (buf[offset + 7] & 0xFFL); - } - - private static void writeBigEndian(byte[] buf, int offset, long value) - { - buf[offset] = (byte)(value >> 56); - buf[offset + 1] = (byte)(value >> 48); - buf[offset + 2] = (byte)(value >> 40); - buf[offset + 3] = (byte)(value >> 32); - buf[offset + 4] = (byte)(value >> 24); - buf[offset + 5] = (byte)(value >> 16); - buf[offset + 6] = (byte)(value >> 8); - buf[offset + 7] = (byte)value; - } - - private static void GF128_mul(byte[] Y, long[] H) - { - long Z0 = 0; // Z = 0 - long Z1 = 0; - long V0 = H[0]; // V = H - long V1 = H[1]; - - // Multiply Z by V for the set bits in Y, starting at the top. - // This is a very simple bit by bit version that may not be very - // fast but it should be resistant to cache timing attacks. - for (int posn = 0; posn < 16; ++posn) { - int value = Y[posn] & 0xFF; - for (int bit = 7; bit >= 0; --bit) { - // Extract the high bit of "value" and turn it into a mask. - long mask = -((long)((value >> bit) & 0x01)); - - // XOR V with Z if the bit is 1. - Z0 ^= (V0 & mask); - Z1 ^= (V1 & mask); - - // Rotate V right by 1 bit. - mask = ((~(V1 & 0x01)) + 1) & 0xE100000000000000L; - V1 = (V1 >>> 1) | (V0 << 63); - V0 = (V0 >>> 1) ^ mask; - } - } - - // We have finished the block so copy Z into Y and byte-swap. - writeBigEndian(Y, 0, Z0); - writeBigEndian(Y, 8, Z1); - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/NewHope.java b/src/main/java/com/southernstorm/noise/crypto/NewHope.java deleted file mode 100644 index c583601d7..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/NewHope.java +++ /dev/null @@ -1,1602 +0,0 @@ -/* - * Based on the public domain C reference code for New Hope. - * This Java version is also placed into the public domain. - * - * Original authors: Erdem Alkim, Léo Ducas, Thomas Pöppelmann, Peter Schwabe - * Java port: Rhys Weatherley - */ - -package com.southernstorm.noise.crypto; - -import java.security.SecureRandom; -import java.util.Arrays; - -/** - * NewHope key exchange algorithm. - * - * This class implements the standard "ref" version of the New Hope - * algorithm. - * - * @see NewHopeTor - */ -public class NewHope { - - // -------------- params.h -------------- - - static final int PARAM_N = 1024; - static final int PARAM_Q = 12289; - static final int POLY_BYTES = 1792; - static final int SEEDBYTES = 32; - static final int RECBYTES = 256; - - /** - * Number of bytes in the public key value sent by Alice. - */ - public static final int SENDABYTES = POLY_BYTES + SEEDBYTES; - - /** - * Number of bytes in the public key value sent by Bob. - */ - public static final int SENDBBYTES = POLY_BYTES + RECBYTES; - - /** - * Number of bytes in shared secret values computed by shareda() and sharedb(). - */ - public static final int SHAREDBYTES = 32; - - // -------------- newhope.c -------------- - - private Poly sk; - - /** - * Constructs a NewHope object. - */ - public NewHope() - { - sk = null; - } - - @Override - protected void finalize() - { - destroy(); - } - - /** - * Destroys sensitive material in this object. - * - * This function should be called once the application has finished - * with the private key contained in this object. This function - * will also be called when the object is finalized, but the point - * of finalization is unpredictable. This function provides a more - * predictable place where the sensitive data is destroyed. - */ - public void destroy() - { - if (sk != null) { - sk.destroy(); - sk = null; - } - } - - /** - * Generates the keypair for Alice. - * - * @param send Buffer to place the public key for Alice in, to be sent to Bob. - * @param sendOffset Offset of the first byte in the send buffer to populate. - * - * The send buffer must have space for at least NewHope.SENDABYTES bytes - * starting at sendOffset. - * - * @see sharedb(), shareda() - */ - public void keygen(byte[] send, int sendOffset) - { - Poly a = new Poly(); - Poly e = new Poly(); - Poly r = new Poly(); - Poly pk = new Poly(); - byte[] seed = new byte [SEEDBYTES + 32]; - byte[] noiseseed = new byte [32]; - - try { - randombytes(seed); - sha3256(seed, 0, seed, 0, SEEDBYTES); /* Don't send output of system RNG */ - System.arraycopy(seed, SEEDBYTES, noiseseed, 0, 32); - - uniform(a.coeffs, seed); - - if (sk == null) - sk = new Poly(); - sk.getnoise(noiseseed,(byte)0); - sk.ntt(); - - e.getnoise(noiseseed,(byte)1); - e.ntt(); - - r.pointwise(sk,a); - pk.add(e,r); - - encode_a(send, sendOffset, pk, seed); - } finally { - a.destroy(); - e.destroy(); - r.destroy(); - pk.destroy(); - Arrays.fill(seed, (byte)0); - Arrays.fill(noiseseed, (byte)0); - } - } - - /** - * Generates the public key and shared secret for Bob. - * - * @param sharedkey Buffer to place the shared secret for Bob in. - * @param sharedkeyOffset Offset of the first byte in the sharedkey buffer to populate. - * @param send Buffer to place the public key for Bob in to be sent to Alice. - * @param sendOffset Offset of the first byte in the send buffer to populate. - * @param received Buffer containing the public key value received from Alice. - * @param receivedOffset Offset of the first byte of the value received from Alice. - * - * The sharedkey buffer must have space for at least NewHope.SHAREDBYTES - * bytes starting at sharedkeyOffset. - * - * The send buffer must have space for at least NewHope.SENDBBYTES bytes - * starting at sendOffset. - * - * The received buffer must have space for at least NewHope.SENDABYTES - * bytes starting at receivedOffset. - * - * @see shareda(), keygen() - */ - public void sharedb(byte[] sharedkey, int sharedkeyOffset, - byte[] send, int sendOffset, - byte[] received, int receivedOffset) - { - Poly sp = new Poly(); - Poly ep = new Poly(); - Poly v = new Poly(); - Poly a = new Poly(); - Poly pka = new Poly(); - Poly c = new Poly(); - Poly epp = new Poly(); - Poly bp = new Poly(); - byte[] seed = new byte [SEEDBYTES]; - byte[] noiseseed = new byte [32]; - byte[] skey = new byte [32]; - - try { - randombytes(noiseseed); - - decode_a(pka, seed, received, receivedOffset); - uniform(a.coeffs, seed); - - sp.getnoise(noiseseed,(byte)0); - sp.ntt(); - ep.getnoise(noiseseed,(byte)1); - ep.ntt(); - - bp.pointwise(a, sp); - bp.add(bp, ep); - - v.pointwise(pka, sp); - v.invntt(); - - epp.getnoise(noiseseed,(byte)2); - v.add(v, epp); - - helprec(c, v, noiseseed, (byte)3); - - encode_b(send, sendOffset, bp, c); - - rec(skey, v, c); - - sha3256(sharedkey, sharedkeyOffset, skey, 0, 32); - } finally { - sp.destroy(); - ep.destroy(); - v.destroy(); - a.destroy(); - pka.destroy(); - c.destroy(); - epp.destroy(); - bp.destroy(); - Arrays.fill(seed, (byte)0); - Arrays.fill(noiseseed, (byte)0); - Arrays.fill(skey, (byte)0); - } - } - - /** - * Generates the shared secret for Alice. - * - * @param sharedkey Buffer to place the shared secret for Alice in. - * @param sharedkeyOffset Offset of the first byte in the sharedkey buffer to populate. - * @param received Buffer containing the public key value received from Bob. - * @param receivedOffset Offset of the first byte of the value received from Bob. - * - * The sharedkey buffer must have space for at least NewHope.SHAREDBYTES - * bytes starting at sharedkeyOffset. - * - * The received buffer must have space for at least NewHope.SENDBBYTES bytes - * starting at receivedOffset. - * - * @see shareda(), keygen() - */ - public void shareda(byte[] sharedkey, int sharedkeyOffset, - byte[] received, int receivedOffset) - { - Poly v = new Poly(); - Poly bp = new Poly(); - Poly c = new Poly(); - byte[] skey = new byte [32]; - - try { - decode_b(bp, c, received, receivedOffset); - - v.pointwise(sk,bp); - v.invntt(); - - rec(skey, v, c); - - sha3256(sharedkey, sharedkeyOffset, skey, 0, 32); - } finally { - v.destroy(); - bp.destroy(); - c.destroy(); - Arrays.fill(skey, (byte)0); - } - } - - /** - * Generates random bytes for use in the NewHope implementation. - * - * @param buffer The buffer to fill with random bytes. - * - * This function may be overridden in subclasses to provide a better - * random number generator or to provide static data for test vectors. - */ - protected void randombytes(byte[] buffer) - { - SecureRandom random = new SecureRandom(); - random.nextBytes(buffer); - } - - private static void encode_a(byte[] r, int roffset, Poly pk, byte[] seed) - { - int i; - pk.tobytes(r, roffset); - for(i=0;i> 2) & 0x03); - c.coeffs[4*i+2] = (char)((r[POLY_BYTES+roffset+i] >> 4) & 0x03); - c.coeffs[4*i+3] = (char)(((r[POLY_BYTES+roffset+i] & 0xff) >> 6)); - } - } - - // -------------- poly.c -------------- - - private class Poly - { - public char[] coeffs; - - public Poly() - { - coeffs = new char [PARAM_N]; - } - - protected void finalize() - { - destroy(); - } - - public void destroy() - { - Arrays.fill(coeffs, (char)0); - } - - public void frombytes(byte[] a, int offset) - { - int i; - for (i = 0; i < PARAM_N/4; i++) - { - coeffs[4*i+0] = (char)( (a[offset+7*i+0] & 0xff) | ((a[offset+7*i+1] & 0x3f) << 8)); - coeffs[4*i+1] = (char)(((a[offset+7*i+1] & 0xc0) >> 6) | ((a[offset+7*i+2] & 0xff) << 2) | ((a[offset+7*i+3] & 0x0f) << 10)); - coeffs[4*i+2] = (char)(((a[offset+7*i+3] & 0xf0) >> 4) | ((a[offset+7*i+4] & 0xff) << 4) | ((a[offset+7*i+5] & 0x03) << 12)); - coeffs[4*i+3] = (char)(((a[offset+7*i+5] & 0xfc) >> 2) | ((a[offset+7*i+6] & 0xff) << 6)); - } - } - - public void tobytes(byte[] r, int offset) - { - int i; - int t0,t1,t2,t3,m; - int c; - for (i = 0; i < PARAM_N/4; i++) - { - t0 = barrett_reduce(coeffs[4*i+0]); //Make sure that coefficients have only 14 bits - t1 = barrett_reduce(coeffs[4*i+1]); - t2 = barrett_reduce(coeffs[4*i+2]); - t3 = barrett_reduce(coeffs[4*i+3]); - - m = t0 - PARAM_Q; - c = m; - c >>= 15; - t0 = m ^ ((t0^m)&c); // >= 15; - t1 = m ^ ((t1^m)&c); // >= 15; - t2 = m ^ ((t2^m)&c); // >= 15; - t3 = m ^ ((t3^m)&c); // > 8) | (t1 << 6)); - r[offset+7*i+2] = (byte)(t1 >> 2); - r[offset+7*i+3] = (byte)((t1 >> 10) | (t2 << 4)); - r[offset+7*i+4] = (byte)(t2 >> 4); - r[offset+7*i+5] = (byte)((t2 >> 12) | (t3 << 2)); - r[offset+7*i+6] = (byte)(t3 >> 6); - } - } - - public void getnoise(byte[] seed, byte nonce) - { - byte[] buf = new byte [4*PARAM_N]; - int /*t, d,*/ a, b; - int i/*,j*/; - - try { - crypto_stream_chacha20(buf,0,4*PARAM_N,nonce,seed); - - for(i=0;i>> j) & 0x01010101; - a = ((d >>> 8) & 0xff) + (d & 0xff); - b = (d >>> 24) + ((d >>> 16) & 0xff); - - What the above is doing is reading 32-bit words from buf and then - setting a and b to the number of 1 bits in the low and high 16 bits. - We instead use the following technique from "Bit Twiddling Hacks", - modified for 16-bit quantities: - - https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel - */ - a = (buf[4*i] & 0xff) | (((buf[4*i+1]) & 0xff) << 8); - a = a - ((a >> 1) & 0x5555); - a = (a & 0x3333) + ((a >> 2) & 0x3333); - a = ((a >> 4) + a) & 0x0F0F; - a = ((a >> 8) + a) & 0x00FF; - - b = (buf[4*i+2] & 0xff) | (((buf[4*i+3]) & 0xff) << 8); - b = b - ((b >> 1) & 0x5555); - b = (b & 0x3333) + ((b >> 2) & 0x3333); - b = ((b >> 4) + b) & 0x0F0F; - b = ((b >> 8) + b) & 0x00FF; - - coeffs[i] = (char)(a + PARAM_Q - b); - } - } finally { - Arrays.fill(buf, (byte)0); - } - } - - public void pointwise(Poly a, Poly b) - { - int i; - int t; - for(i=0;i SHAKE128_RATE*nblocks-2) - { - nblocks=1; - shake128_squeezeblocks(buf,0,nblocks,state); - pos = 0; - } - } - } finally { - Arrays.fill(state, 0); - Arrays.fill(buf, (byte)0); - } - } - - // -------------- reduce.c -------------- - - private static final int qinv = 12287; // -inverse_mod(p,2^18) - private static final int rlog = 18; - - private static int montgomery_reduce(int a) - { - int u; - - u = (a * qinv); - u &= ((1<>> 18; - } - - private static int barrett_reduce(int a) - { - int u; - a &= 0xffff; - u = (a * 5) >> 16; - u *= PARAM_Q; - a -= u; - return a & 0xffff; - } - - // -------------- error_correction.c -------------- - - private static int abs(int v) - { - int mask = v >> 31; - return (v ^ mask) - mask; - } - - private static int f(int[] v0, int v0offset, int[] v1, int v1offset, int x) - { - int xit, t, r, b; - - // Next 6 lines compute t = x/PARAM_Q; - b = x*2730; - t = b >> 25; - b = x - t*12289; - b = 12288 - b; - b >>= 31; - t -= b; - - r = t & 1; - xit = (t>>1); - v0[v0offset] = xit+r; // v0 = round(x/(2*PARAM_Q)) - - t -= 1; - r = t & 1; - v1[v1offset] = (t>>1)+r; - - return abs(x-((v0[v0offset])*2*PARAM_Q)); - } - - private static int g(int x) - { - int t,c,b; - - // Next 6 lines compute t = x/(4*PARAM_Q); - b = x*2730; - t = b >> 27; - b = x - t*49156; - b = 49155 - b; - b >>= 31; - t -= b; - - c = t & 1; - t = (t >> 1) + c; // t = round(x/(8*PARAM_Q)) - - t *= 8*PARAM_Q; - - return abs(t - x); - } - - private static int LDDecode(int xi0, int xi1, int xi2, int xi3) - { - int t; - - t = g(xi0); - t += g(xi1); - t += g(xi2); - t += g(xi3); - - t -= 8*PARAM_Q; - t >>= 31; - return t&1; - } - - private static void helprec(Poly c, Poly v, byte[] seed, byte nonce) - { - int[] v0 = new int [8]; - int v_tmp0,v_tmp1,v_tmp2,v_tmp3; - int k; - int rbit; - byte[] rand = new byte [32]; - int i; - - try { - crypto_stream_chacha20(rand,0,32,((long)nonce) << 56,seed); - - for(i=0; i<256; i++) - { - rbit = (rand[i>>3] >> (i&7)) & 1; - - k = f(v0,0, v0,4, 8*v.coeffs[ 0+i] + 4*rbit); - k += f(v0,1, v0,5, 8*v.coeffs[256+i] + 4*rbit); - k += f(v0,2, v0,6, 8*v.coeffs[512+i] + 4*rbit); - k += f(v0,3, v0,7, 8*v.coeffs[768+i] + 4*rbit); - - k = (2*PARAM_Q-1-k) >> 31; - - v_tmp0 = ((~k) & v0[0]) ^ (k & v0[4]); - v_tmp1 = ((~k) & v0[1]) ^ (k & v0[5]); - v_tmp2 = ((~k) & v0[2]) ^ (k & v0[6]); - v_tmp3 = ((~k) & v0[3]) ^ (k & v0[7]); - - c.coeffs[ 0+i] = (char)((v_tmp0 - v_tmp3) & 3); - c.coeffs[256+i] = (char)((v_tmp1 - v_tmp3) & 3); - c.coeffs[512+i] = (char)((v_tmp2 - v_tmp3) & 3); - c.coeffs[768+i] = (char)(( -k + 2*v_tmp3) & 3); - } - } finally { - Arrays.fill(v0, 0); - Arrays.fill(rand, (byte)0); - } - } - - private static void rec(byte[] key, Poly v, Poly c) - { - int i; - int tmp0,tmp1,tmp2,tmp3; - - for(i=0;i<32;i++) - key[i] = 0; - - for(i=0; i<256; i++) - { - char c768 = c.coeffs[768+i]; - tmp0 = 16*PARAM_Q + 8*(int)v.coeffs[ 0+i] - PARAM_Q * (2*c.coeffs[ 0+i]+c768); - tmp1 = 16*PARAM_Q + 8*(int)v.coeffs[256+i] - PARAM_Q * (2*c.coeffs[256+i]+c768); - tmp2 = 16*PARAM_Q + 8*(int)v.coeffs[512+i] - PARAM_Q * (2*c.coeffs[512+i]+c768); - tmp3 = 16*PARAM_Q + 8*(int)v.coeffs[768+i] - PARAM_Q * ( c768); - - key[i>>3] |= LDDecode(tmp0, tmp1, tmp2, tmp3) << (i & 7); - } - } - - // -------------- ntt.c -------------- - - private static final int bitrev_table_combined[/*496*/] = { - 524289,262146,786435,131076,655365,393222,917511,65544, - 589833,327690,851979,196620,720909,458766,983055,32784, - 557073,294930,819219,163860,688149,426006,950295,98328, - 622617,360474,884763,229404,753693,491550,1015839,540705, - 278562,802851,147492,671781,409638,933927,81960,606249, - 344106,868395,213036,737325,475182,999471,573489,311346, - 835635,180276,704565,442422,966711,114744,639033,376890, - 901179,245820,770109,507966,1032255,532545,270402,794691, - 139332,663621,401478,925767,598089,335946,860235,204876, - 729165,467022,991311,565329,303186,827475,172116,696405, - 434262,958551,106584,630873,368730,893019,237660,761949, - 499806,1024095,548961,286818,811107,155748,680037,417894, - 942183,614505,352362,876651,221292,745581,483438,1007727, - 581745,319602,843891,188532,712821,450678,974967,647289, - 385146,909435,254076,778365,516222,1040511,528513,266370, - 790659,659589,397446,921735,594057,331914,856203,200844, - 725133,462990,987279,561297,299154,823443,168084,692373, - 430230,954519,626841,364698,888987,233628,757917,495774, - 1020063,544929,282786,807075,676005,413862,938151,610473, - 348330,872619,217260,741549,479406,1003695,577713,315570, - 839859,708789,446646,970935,643257,381114,905403,250044, - 774333,512190,1036479,536769,274626,798915,667845,405702, - 929991,602313,340170,864459,733389,471246,995535,569553, - 307410,831699,700629,438486,962775,635097,372954,897243, - 241884,766173,504030,1028319,553185,291042,815331,684261, - 422118,946407,618729,356586,880875,749805,487662,1011951, - 585969,323826,848115,717045,454902,979191,651513,389370, - 913659,782589,520446,1044735,526593,788739,657669,395526, - 919815,592137,329994,854283,723213,461070,985359,559377, - 297234,821523,690453,428310,952599,624921,362778,887067, - 755997,493854,1018143,543009,805155,674085,411942,936231, - 608553,346410,870699,739629,477486,1001775,575793,837939, - 706869,444726,969015,641337,379194,903483,772413,510270, - 1034559,534849,796995,665925,403782,928071,600393,862539, - 731469,469326,993615,567633,829779,698709,436566,960855, - 633177,371034,895323,764253,502110,1026399,551265,813411, - 682341,420198,944487,616809,878955,747885,485742,1010031, - 584049,846195,715125,452982,977271,649593,911739,780669, - 518526,1042815,530817,792963,661893,924039,596361,858507, - 727437,465294,989583,563601,825747,694677,432534,956823, - 629145,891291,760221,498078,1022367,547233,809379,678309, - 940455,612777,874923,743853,481710,1005999,580017,842163, - 711093,973239,645561,907707,776637,514494,1038783,539073, - 801219,670149,932295,604617,866763,735693,997839,571857, - 834003,702933,965079,637401,899547,768477,506334,1030623, - 555489,817635,686565,948711,621033,883179,752109,1014255, - 588273,850419,719349,981495,653817,915963,784893,1047039, - 787971,656901,919047,591369,853515,722445,984591,558609, - 820755,689685,951831,624153,886299,755229,1017375,804387, - 673317,935463,607785,869931,738861,1001007,837171,706101, - 968247,640569,902715,771645,1033791,796227,665157,927303, - 861771,730701,992847,829011,697941,960087,632409,894555, - 763485,1025631,812643,681573,943719,878187,747117,1009263, - 845427,714357,976503,910971,779901,1042047,792195,923271, - 857739,726669,988815,824979,693909,956055,890523,759453, - 1021599,808611,939687,874155,743085,1005231,841395,972471, - 906939,775869,1038015,800451,931527,865995,997071,833235, - 964311,898779,767709,1029855,816867,947943,882411,1013487, - 849651,980727,915195,1046271,921351,855819,986895,823059, - 954135,888603,1019679,937767,872235,1003311,970551,905019, - 1036095,929607,995151,962391,896859,1027935,946023,1011567, - 978807,1044351,991119,958359,1023903,1007535,1040319,1032159 - }; - - // Modified version of bitrev_vector() from the C reference code - // that reduces the number of array bounds checks on the bitrev_table - // from 1024 to 496. The values in the combined table are encoded - // as (i + (r * PARAM_N)) where i and r are the indices to swap. - // The pseudo-code to generate this combined table is: - // p = 0; - // for (i = 0; i < PARAM_N; i++) { - // r = bitrev_table[i]; - // if (i < r) - // bitrev_table_combined[p++] = i + (r * PARAM_N); - // } - private static void bitrev_vector(char[] poly) - { - int i,r,p; - char tmp; - - for(p = 0; p < 496; ++p) - { - int indices = bitrev_table_combined[p]; - i = indices & 0x03FF; - r = indices >> 10; - tmp = poly[i]; - poly[i] = poly[r]; - poly[r] = tmp; - } - } - - private static void mul_coefficients(char[] poly, char[] factors) - { - int i; - - for(i = 0; i < PARAM_N; i++) - poly[i] = (char)montgomery_reduce((poly[i] * factors[i])); - } - - /* GS_bo_to_no; omegas need to be in Montgomery domain */ - private static void ntt_global(char[] a, char[] omega) - { - int i, start, j, jTwiddle, distance; - char temp, W; - - - for(i=0;i<10;i+=2) - { - // Even level - distance = (1<>> (64 - offset)); - } - - private static long load64(byte[] x, int offset) - { - long r = 0; - - for (int i = 0; i < 8; ++i) { - r |= ((long)(x[offset+i] & 0xff)) << (8 * i); - } - return r; - } - - private static void store64(byte[] x, int offset, long u) - { - int i; - - for(i=0; i<8; ++i) { - x[offset+i] = (byte)u; - u >>= 8; - } - } - - private static final long[] KeccakF_RoundConstants = - { - 0x0000000000000001L, - 0x0000000000008082L, - 0x800000000000808aL, - 0x8000000080008000L, - 0x000000000000808bL, - 0x0000000080000001L, - 0x8000000080008081L, - 0x8000000000008009L, - 0x000000000000008aL, - 0x0000000000000088L, - 0x0000000080008009L, - 0x000000008000000aL, - 0x000000008000808bL, - 0x800000000000008bL, - 0x8000000000008089L, - 0x8000000000008003L, - 0x8000000000008002L, - 0x8000000000000080L, - 0x000000000000800aL, - 0x800000008000000aL, - 0x8000000080008081L, - 0x8000000000008080L, - 0x0000000080000001L, - 0x8000000080008008L - }; - - - private static void KeccakF1600_StatePermute(long[] state) - { - int round; - - long Aba, Abe, Abi, Abo, Abu; - long Aga, Age, Agi, Ago, Agu; - long Aka, Ake, Aki, Ako, Aku; - long Ama, Ame, Ami, Amo, Amu; - long Asa, Ase, Asi, Aso, Asu; - long BCa, BCe, BCi, BCo, BCu; - long Da, De, Di, Do, Du; - long Eba, Ebe, Ebi, Ebo, Ebu; - long Ega, Ege, Egi, Ego, Egu; - long Eka, Eke, Eki, Eko, Eku; - long Ema, Eme, Emi, Emo, Emu; - long Esa, Ese, Esi, Eso, Esu; - - //copyFromState(A, state) - Aba = state[ 0]; - Abe = state[ 1]; - Abi = state[ 2]; - Abo = state[ 3]; - Abu = state[ 4]; - Aga = state[ 5]; - Age = state[ 6]; - Agi = state[ 7]; - Ago = state[ 8]; - Agu = state[ 9]; - Aka = state[10]; - Ake = state[11]; - Aki = state[12]; - Ako = state[13]; - Aku = state[14]; - Ama = state[15]; - Ame = state[16]; - Ami = state[17]; - Amo = state[18]; - Amu = state[19]; - Asa = state[20]; - Ase = state[21]; - Asi = state[22]; - Aso = state[23]; - Asu = state[24]; - - for( round = 0; round < 24; round += 2 ) - { - // prepareTheta - BCa = Aba^Aga^Aka^Ama^Asa; - BCe = Abe^Age^Ake^Ame^Ase; - BCi = Abi^Agi^Aki^Ami^Asi; - BCo = Abo^Ago^Ako^Amo^Aso; - BCu = Abu^Agu^Aku^Amu^Asu; - - //thetaRhoPiChiIotaPrepareTheta(round , A, E) - Da = BCu^ROL(BCe, 1); - De = BCa^ROL(BCi, 1); - Di = BCe^ROL(BCo, 1); - Do = BCi^ROL(BCu, 1); - Du = BCo^ROL(BCa, 1); - - Aba ^= Da; - BCa = Aba; - Age ^= De; - BCe = ROL(Age, 44); - Aki ^= Di; - BCi = ROL(Aki, 43); - Amo ^= Do; - BCo = ROL(Amo, 21); - Asu ^= Du; - BCu = ROL(Asu, 14); - Eba = BCa ^((~BCe)& BCi ); - Eba ^= KeccakF_RoundConstants[round]; - Ebe = BCe ^((~BCi)& BCo ); - Ebi = BCi ^((~BCo)& BCu ); - Ebo = BCo ^((~BCu)& BCa ); - Ebu = BCu ^((~BCa)& BCe ); - - Abo ^= Do; - BCa = ROL(Abo, 28); - Agu ^= Du; - BCe = ROL(Agu, 20); - Aka ^= Da; - BCi = ROL(Aka, 3); - Ame ^= De; - BCo = ROL(Ame, 45); - Asi ^= Di; - BCu = ROL(Asi, 61); - Ega = BCa ^((~BCe)& BCi ); - Ege = BCe ^((~BCi)& BCo ); - Egi = BCi ^((~BCo)& BCu ); - Ego = BCo ^((~BCu)& BCa ); - Egu = BCu ^((~BCa)& BCe ); - - Abe ^= De; - BCa = ROL(Abe, 1); - Agi ^= Di; - BCe = ROL(Agi, 6); - Ako ^= Do; - BCi = ROL(Ako, 25); - Amu ^= Du; - BCo = ROL(Amu, 8); - Asa ^= Da; - BCu = ROL(Asa, 18); - Eka = BCa ^((~BCe)& BCi ); - Eke = BCe ^((~BCi)& BCo ); - Eki = BCi ^((~BCo)& BCu ); - Eko = BCo ^((~BCu)& BCa ); - Eku = BCu ^((~BCa)& BCe ); - - Abu ^= Du; - BCa = ROL(Abu, 27); - Aga ^= Da; - BCe = ROL(Aga, 36); - Ake ^= De; - BCi = ROL(Ake, 10); - Ami ^= Di; - BCo = ROL(Ami, 15); - Aso ^= Do; - BCu = ROL(Aso, 56); - Ema = BCa ^((~BCe)& BCi ); - Eme = BCe ^((~BCi)& BCo ); - Emi = BCi ^((~BCo)& BCu ); - Emo = BCo ^((~BCu)& BCa ); - Emu = BCu ^((~BCa)& BCe ); - - Abi ^= Di; - BCa = ROL(Abi, 62); - Ago ^= Do; - BCe = ROL(Ago, 55); - Aku ^= Du; - BCi = ROL(Aku, 39); - Ama ^= Da; - BCo = ROL(Ama, 41); - Ase ^= De; - BCu = ROL(Ase, 2); - Esa = BCa ^((~BCe)& BCi ); - Ese = BCe ^((~BCi)& BCo ); - Esi = BCi ^((~BCo)& BCu ); - Eso = BCo ^((~BCu)& BCa ); - Esu = BCu ^((~BCa)& BCe ); - - // prepareTheta - BCa = Eba^Ega^Eka^Ema^Esa; - BCe = Ebe^Ege^Eke^Eme^Ese; - BCi = Ebi^Egi^Eki^Emi^Esi; - BCo = Ebo^Ego^Eko^Emo^Eso; - BCu = Ebu^Egu^Eku^Emu^Esu; - - //thetaRhoPiChiIotaPrepareTheta(round+1, E, A) - Da = BCu^ROL(BCe, 1); - De = BCa^ROL(BCi, 1); - Di = BCe^ROL(BCo, 1); - Do = BCi^ROL(BCu, 1); - Du = BCo^ROL(BCa, 1); - - Eba ^= Da; - BCa = Eba; - Ege ^= De; - BCe = ROL(Ege, 44); - Eki ^= Di; - BCi = ROL(Eki, 43); - Emo ^= Do; - BCo = ROL(Emo, 21); - Esu ^= Du; - BCu = ROL(Esu, 14); - Aba = BCa ^((~BCe)& BCi ); - Aba ^= KeccakF_RoundConstants[round+1]; - Abe = BCe ^((~BCi)& BCo ); - Abi = BCi ^((~BCo)& BCu ); - Abo = BCo ^((~BCu)& BCa ); - Abu = BCu ^((~BCa)& BCe ); - - Ebo ^= Do; - BCa = ROL(Ebo, 28); - Egu ^= Du; - BCe = ROL(Egu, 20); - Eka ^= Da; - BCi = ROL(Eka, 3); - Eme ^= De; - BCo = ROL(Eme, 45); - Esi ^= Di; - BCu = ROL(Esi, 61); - Aga = BCa ^((~BCe)& BCi ); - Age = BCe ^((~BCi)& BCo ); - Agi = BCi ^((~BCo)& BCu ); - Ago = BCo ^((~BCu)& BCa ); - Agu = BCu ^((~BCa)& BCe ); - - Ebe ^= De; - BCa = ROL(Ebe, 1); - Egi ^= Di; - BCe = ROL(Egi, 6); - Eko ^= Do; - BCi = ROL(Eko, 25); - Emu ^= Du; - BCo = ROL(Emu, 8); - Esa ^= Da; - BCu = ROL(Esa, 18); - Aka = BCa ^((~BCe)& BCi ); - Ake = BCe ^((~BCi)& BCo ); - Aki = BCi ^((~BCo)& BCu ); - Ako = BCo ^((~BCu)& BCa ); - Aku = BCu ^((~BCa)& BCe ); - - Ebu ^= Du; - BCa = ROL(Ebu, 27); - Ega ^= Da; - BCe = ROL(Ega, 36); - Eke ^= De; - BCi = ROL(Eke, 10); - Emi ^= Di; - BCo = ROL(Emi, 15); - Eso ^= Do; - BCu = ROL(Eso, 56); - Ama = BCa ^((~BCe)& BCi ); - Ame = BCe ^((~BCi)& BCo ); - Ami = BCi ^((~BCo)& BCu ); - Amo = BCo ^((~BCu)& BCa ); - Amu = BCu ^((~BCa)& BCe ); - - Ebi ^= Di; - BCa = ROL(Ebi, 62); - Ego ^= Do; - BCe = ROL(Ego, 55); - Eku ^= Du; - BCi = ROL(Eku, 39); - Ema ^= Da; - BCo = ROL(Ema, 41); - Ese ^= De; - BCu = ROL(Ese, 2); - Asa = BCa ^((~BCe)& BCi ); - Ase = BCe ^((~BCi)& BCo ); - Asi = BCi ^((~BCo)& BCu ); - Aso = BCo ^((~BCu)& BCa ); - Asu = BCu ^((~BCa)& BCe ); - } - - //copyToState(state, A) - state[ 0] = Aba; - state[ 1] = Abe; - state[ 2] = Abi; - state[ 3] = Abo; - state[ 4] = Abu; - state[ 5] = Aga; - state[ 6] = Age; - state[ 7] = Agi; - state[ 8] = Ago; - state[ 9] = Agu; - state[10] = Aka; - state[11] = Ake; - state[12] = Aki; - state[13] = Ako; - state[14] = Aku; - state[15] = Ama; - state[16] = Ame; - state[17] = Ami; - state[18] = Amo; - state[19] = Amu; - state[20] = Asa; - state[21] = Ase; - state[22] = Asi; - state[23] = Aso; - state[24] = Asu; - } - - private static void keccak_absorb(long[] s, int r, byte[] m, int offset, int mlen, byte p) - { - int i; - byte[] t = new byte [200]; - - try { - for (i = 0; i < 25; ++i) - s[i] = 0; - - while (mlen >= r) - { - for (i = 0; i < r / 8; ++i) - s[i] ^= load64(m, offset + 8 * i); - - KeccakF1600_StatePermute(s); - mlen -= r; - offset += r; - } - - for (i = 0; i < r; ++i) - t[i] = 0; - for (i = 0; i < mlen; ++i) - t[i] = m[offset + i]; - t[i] = p; - t[r - 1] |= 128; - for (i = 0; i < r / 8; ++i) - s[i] ^= load64(t, 8 * i); - } finally { - Arrays.fill(t, (byte)0); - } - } - - private static void keccak_squeezeblocks(byte[] h, int offset, int nblocks, long [] s, int r) - { - int i; - while(nblocks > 0) - { - KeccakF1600_StatePermute(s); - for(i=0;i<(r>>3);i++) - { - store64(h, offset+8*i, s[i]); - } - offset += r; - nblocks--; - } - } - - static final int SHAKE128_RATE = 168; - - static void shake128_absorb(long[] s, byte[] input, int inputOffset, int inputByteLen) - { - keccak_absorb(s, SHAKE128_RATE, input, inputOffset, inputByteLen, (byte)0x1F); - } - - static void shake128_squeezeblocks(byte[] output, int outputOffset, int nblocks, long[] s) - { - keccak_squeezeblocks(output, outputOffset, nblocks, s, SHAKE128_RATE); - } - - private static final int SHA3_256_RATE = 136; - - private static void sha3256(byte[] output, int outputOffset, byte[] input, int inputOffset, int inputByteLen) - { - long[] s = new long [25]; - byte[] t = new byte [SHA3_256_RATE]; - int i; - - try { - keccak_absorb(s, SHA3_256_RATE, input, inputOffset, inputByteLen, (byte)0x06); - keccak_squeezeblocks(t, 0, 1, s, SHA3_256_RATE); - for(i=0;i<32;i++) - output[i] = t[i]; - } finally { - Arrays.fill(s, 0); - Arrays.fill(t, (byte)0); - } - } - - // -------------- crypto_stream_chacha20.c -------------- - - /* Based on the public domain implemntation in - * crypto_stream/chacha20/e/ref from http://bench.cr.yp.to/supercop.html - * by Daniel J. Bernstein */ - - private static int load_littleendian(byte[] x, int offset) - { - return - (int) (x[offset + 0] & 0xff) - | (((int) (x[offset + 1] & 0xff)) << 8) - | (((int) (x[offset + 2] & 0xff)) << 16) - | (((int) (x[offset + 3] & 0xff)) << 24); - } - - private static void store_littleendian(byte[] x, int offset, int u) - { - x[offset + 0] = (byte)u; u >>= 8; - x[offset + 1] = (byte)u; u >>= 8; - x[offset + 2] = (byte)u; u >>= 8; - x[offset + 3] = (byte)u; - } - - // Note: This version is limited to a maximum of 2^32 blocks or 2^38 bytes - // because the block number counter is 32-bit instead of 64-bit. This isn't - // a problem for New Hope because the maximum required output is 4096 bytes. - private static void crypto_core_chacha20(byte[] out, int outOffset, long nonce, int blknum, byte[] k) - { - int x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; - int j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; - int i; - - j0 = x0 = 0x61707865; // "expa" - j1 = x1 = 0x3320646e; // "nd 3" - j2 = x2 = 0x79622d32; // "2-by" - j3 = x3 = 0x6b206574; // "te k" - j4 = x4 = load_littleendian(k, 0); - j5 = x5 = load_littleendian(k, 4); - j6 = x6 = load_littleendian(k, 8); - j7 = x7 = load_littleendian(k, 12); - j8 = x8 = load_littleendian(k, 16); - j9 = x9 = load_littleendian(k, 20); - j10 = x10 = load_littleendian(k, 24); - j11 = x11 = load_littleendian(k, 28); - j12 = x12 = blknum; - j13 = x13 = 0; - j14 = x14 = (int)nonce; - j15 = x15 = (int)(nonce >>> 32); - - for (i = 20;i > 0;i -= 2) { - x0 += x4 ; x12 ^= x0 ; x12 = (x12 << 16) | (x12 >>> 16); - x8 += x12; x4 ^= x8 ; x4 = (x4 << 12) | (x4 >>> 20); - x0 += x4 ; x12 ^= x0 ; x12 = (x12 << 8) | (x12 >>> 24); - x8 += x12; x4 ^= x8 ; x4 = (x4 << 7) | (x4 >>> 25); - x1 += x5 ; x13 ^= x1 ; x13 = (x13 << 16) | (x13 >>> 16); - x9 += x13; x5 ^= x9 ; x5 = (x5 << 12) | (x5 >>> 20); - x1 += x5 ; x13 ^= x1 ; x13 = (x13 << 8) | (x13 >>> 24); - x9 += x13; x5 ^= x9 ; x5 = (x5 << 7) | (x5 >>> 25); - x2 += x6 ; x14 ^= x2 ; x14 = (x14 << 16) | (x14 >>> 16); - x10 += x14; x6 ^= x10; x6 = (x6 << 12) | (x6 >>> 20); - x2 += x6 ; x14 ^= x2 ; x14 = (x14 << 8) | (x14 >>> 24); - x10 += x14; x6 ^= x10; x6 = (x6 << 7) | (x6 >>> 25); - x3 += x7 ; x15 ^= x3 ; x15 = (x15 << 16) | (x15 >>> 16); - x11 += x15; x7 ^= x11; x7 = (x7 << 12) | (x7 >>> 20); - x3 += x7 ; x15 ^= x3 ; x15 = (x15 << 8) | (x15 >>> 24); - x11 += x15; x7 ^= x11; x7 = (x7 << 7) | (x7 >>> 25); - x0 += x5 ; x15 ^= x0 ; x15 = (x15 << 16) | (x15 >>> 16); - x10 += x15; x5 ^= x10; x5 = (x5 << 12) | (x5 >>> 20); - x0 += x5 ; x15 ^= x0 ; x15 = (x15 << 8) | (x15 >>> 24); - x10 += x15; x5 ^= x10; x5 = (x5 << 7) | (x5 >>> 25); - x1 += x6 ; x12 ^= x1 ; x12 = (x12 << 16) | (x12 >>> 16); - x11 += x12; x6 ^= x11; x6 = (x6 << 12) | (x6 >>> 20); - x1 += x6 ; x12 ^= x1 ; x12 = (x12 << 8) | (x12 >>> 24); - x11 += x12; x6 ^= x11; x6 = (x6 << 7) | (x6 >>> 25); - x2 += x7 ; x13 ^= x2 ; x13 = (x13 << 16) | (x13 >>> 16); - x8 += x13; x7 ^= x8 ; x7 = (x7 << 12) | (x7 >>> 20); - x2 += x7 ; x13 ^= x2 ; x13 = (x13 << 8) | (x13 >>> 24); - x8 += x13; x7 ^= x8 ; x7 = (x7 << 7) | (x7 >>> 25); - x3 += x4 ; x14 ^= x3 ; x14 = (x14 << 16) | (x14 >>> 16); - x9 += x14; x4 ^= x9 ; x4 = (x4 << 12) | (x4 >>> 20); - x3 += x4 ; x14 ^= x3 ; x14 = (x14 << 8) | (x14 >>> 24); - x9 += x14; x4 ^= x9 ; x4 = (x4 << 7) | (x4 >>> 25); - } - - x0 += j0; - x1 += j1; - x2 += j2; - x3 += j3; - x4 += j4; - x5 += j5; - x6 += j6; - x7 += j7; - x8 += j8; - x9 += j9; - x10 += j10; - x11 += j11; - x12 += j12; - x13 += j13; - x14 += j14; - x15 += j15; - - store_littleendian(out, outOffset + 0,x0); - store_littleendian(out, outOffset + 4,x1); - store_littleendian(out, outOffset + 8,x2); - store_littleendian(out, outOffset + 12,x3); - store_littleendian(out, outOffset + 16,x4); - store_littleendian(out, outOffset + 20,x5); - store_littleendian(out, outOffset + 24,x6); - store_littleendian(out, outOffset + 28,x7); - store_littleendian(out, outOffset + 32,x8); - store_littleendian(out, outOffset + 36,x9); - store_littleendian(out, outOffset + 40,x10); - store_littleendian(out, outOffset + 44,x11); - store_littleendian(out, outOffset + 48,x12); - store_littleendian(out, outOffset + 52,x13); - store_littleendian(out, outOffset + 56,x14); - store_littleendian(out, outOffset + 60,x15); - } - - private static void crypto_stream_chacha20(byte[] c, int coffset, int clen, long n, byte[] k) - { - int blknum = 0; - - if (clen <= 0) return; - - while (clen >= 64) { - crypto_core_chacha20(c,coffset,n,blknum,k); - ++blknum; - clen -= 64; - coffset += 64; - } - - if (clen != 0) { - byte[] block = new byte [64]; - try { - crypto_core_chacha20(block,0,n,blknum,k); - for (int i = 0;i < clen;++i) c[coffset+i] = block[i]; - } finally { - Arrays.fill(block, (byte)0); - } - } - } - - // -------------- precomp.c -------------- - - private static final char[/*PARAM_N/2*/] omegas_montgomery = { - 4075,6974,7373,7965,3262,5079,522,2169,6364,1018,1041,8775,2344, - 11011,5574,1973,4536,1050,6844,3860,3818,6118,2683,1190,4789,7822, - 7540,6752,5456,4449,3789,12142,11973,382,3988,468,6843,5339,6196, - 3710,11316,1254,5435,10930,3998,10256,10367,3879,11889,1728,6137, - 4948,5862,6136,3643,6874,8724,654,10302,1702,7083,6760,56,3199,9987, - 605,11785,8076,5594,9260,6403,4782,6212,4624,9026,8689,4080,11868, - 6221,3602,975,8077,8851,9445,5681,3477,1105,142,241,12231,1003, - 3532,5009,1956,6008,11404,7377,2049,10968,12097,7591,5057,3445, - 4780,2920,7048,3127,8120,11279,6821,11502,8807,12138,2127,2839, - 3957,431,1579,6383,9784,5874,677,3336,6234,2766,1323,9115,12237, - 2031,6956,6413,2281,3969,3991,12133,9522,4737,10996,4774,5429,11871, - 3772,453,5908,2882,1805,2051,1954,11713,3963,2447,6142,8174,3030, - 1843,2361,12071,2908,3529,3434,3202,7796,2057,5369,11939,1512,6906, - 10474,11026,49,10806,5915,1489,9789,5942,10706,10431,7535,426,8974, - 3757,10314,9364,347,5868,9551,9634,6554,10596,9280,11566,174,2948, - 2503,6507,10723,11606,2459,64,3656,8455,5257,5919,7856,1747,9166, - 5486,9235,6065,835,3570,4240,11580,4046,10970,9139,1058,8210,11848, - 922,7967,1958,10211,1112,3728,4049,11130,5990,1404,325,948,11143, - 6190,295,11637,5766,8212,8273,2919,8527,6119,6992,8333,1360,2555, - 6167,1200,7105,7991,3329,9597,12121,5106,5961,10695,10327,3051,9923, - 4896,9326,81,3091,1000,7969,4611,726,1853,12149,4255,11112,2768, - 10654,1062,2294,3553,4805,2747,4846,8577,9154,1170,2319,790,11334, - 9275,9088,1326,5086,9094,6429,11077,10643,3504,3542,8668,9744,1479, - 1,8246,7143,11567,10984,4134,5736,4978,10938,5777,8961,4591,5728, - 6461,5023,9650,7468,949,9664,2975,11726,2744,9283,10092,5067,12171, - 2476,3748,11336,6522,827,9452,5374,12159,7935,3296,3949,9893,4452, - 10908,2525,3584,8112,8011,10616,4989,6958,11809,9447,12280,1022, - 11950,9821,11745,5791,5092,2089,9005,2881,3289,2013,9048,729,7901, - 1260,5755,4632,11955,2426,10593,1428,4890,5911,3932,9558,8830,3637, - 5542,145,5179,8595,3707,10530,355,3382,4231,9741,1207,9041,7012,1168, - 10146,11224,4645,11885,10911,10377,435,7952,4096,493,9908,6845,6039, - 2422,2187,9723,8643,9852,9302,6022,7278,1002,4284,5088,1607,7313, - 875,8509,9430,1045,2481,5012,7428,354,6591,9377,11847,2401,1067, - 7188,11516,390,8511,8456,7270,545,8585,9611,12047,1537,4143,4714, - 4885,1017,5084,1632,3066,27,1440,8526,9273,12046,11618,9289,3400, - 9890,3136,7098,8758,11813,7384,3985,11869,6730,10745,10111,2249, - 4048,2884,11136,2126,1630,9103,5407,2686,9042,2969,8311,9424, - 9919,8779,5332,10626,1777,4654,10863,7351,3636,9585,5291,8374, - 2166,4919,12176,9140,12129,7852,12286,4895,10805,2780,5195,2305, - 7247,9644,4053,10600,3364,3271,4057,4414,9442,7917,2174 - }; - - private static final char[/*PARAM_N/2*/] omegas_inv_montgomery = { - 4075,5315,4324,4916,10120,11767,7210,9027,10316,6715,1278,9945, - 3514,11248,11271,5925,147,8500,7840,6833,5537,4749,4467,7500,11099, - 9606,6171,8471,8429,5445,11239,7753,9090,12233,5529,5206,10587, - 1987,11635,3565,5415,8646,6153,6427,7341,6152,10561,400,8410,1922, - 2033,8291,1359,6854,11035,973,8579,6093,6950,5446,11821,8301,11907, - 316,52,3174,10966,9523,6055,8953,11612,6415,2505,5906,10710,11858, - 8332,9450,10162,151,3482,787,5468,1010,4169,9162,5241,9369,7509, - 8844,7232,4698,192,1321,10240,4912,885,6281,10333,7280,8757,11286, - 58,12048,12147,11184,8812,6608,2844,3438,4212,11314,8687,6068,421, - 8209,3600,3263,7665,6077,7507,5886,3029,6695,4213,504,11684,2302, - 1962,1594,6328,7183,168,2692,8960,4298,5184,11089,6122,9734,10929, - 3956,5297,6170,3762,9370,4016,4077,6523,652,11994,6099,1146,11341, - 11964,10885,6299,1159,8240,8561,11177,2078,10331,4322,11367,441, - 4079,11231,3150,1319,8243,709,8049,8719,11454,6224,3054,6803,3123, - 10542,4433,6370,7032,3834,8633,12225,9830,683,1566,5782,9786,9341, - 12115,723,3009,1693,5735,2655,2738,6421,11942,2925,1975,8532,3315, - 11863,4754,1858,1583,6347,2500,10800,6374,1483,12240,1263,1815, - 5383,10777,350,6920,10232,4493,9087,8855,8760,9381,218,9928,10446, - 9259,4115,6147,9842,8326,576,10335,10238,10484,9407,6381,11836,8517, - 418,6860,7515,1293,7552,2767,156,8298,8320,10008,5876,5333,10258, - 10115,4372,2847,7875,8232,9018,8925,1689,8236,2645,5042,9984,7094, - 9509,1484,7394,3,4437,160,3149,113,7370,10123,3915,6998,2704,8653, - 4938,1426,7635,10512,1663,6957,3510,2370,2865,3978,9320,3247,9603, - 6882,3186,10659,10163,1153,9405,8241,10040,2178,1544,5559,420,8304, - 4905,476,3531,5191,9153,2399,8889,3000,671,243,3016,3763,10849,12262, - 9223,10657,7205,11272,7404,7575,8146,10752,242,2678,3704,11744, - 5019,3833,3778,11899,773,5101,11222,9888,442,2912,5698,11935,4861, - 7277,9808,11244,2859,3780,11414,4976,10682,7201,8005,11287,5011, - 6267,2987,2437,3646,2566,10102,9867,6250,5444,2381,11796,8193,4337, - 11854,1912,1378,404,7644,1065,2143,11121,5277,3248,11082,2548,8058, - 8907,11934,1759,8582,3694,7110,12144,6747,8652,3459,2731,8357,6378, - 7399,10861,1696,9863,334,7657,6534,11029,4388,11560,3241,10276,9000, - 9408,3284,10200,7197,6498,544,2468,339,11267,9,2842,480,5331,7300, - 1673,4278,4177,8705,9764,1381,7837,2396,8340,8993,4354,130,6915, - 2837,11462,5767,953,8541,9813,118,7222,2197,3006,9545,563,9314, - 2625,11340,4821,2639,7266,5828,6561,7698,3328,6512,1351,7311,6553, - 8155,1305,722,5146,4043,12288,10810,2545,3621,8747,8785,1646,1212, - 5860,3195,7203,10963,3201,3014,955,11499,9970,11119,3135,3712,7443, - 9542,7484,8736,9995,11227,1635,9521,1177,8034,140,10436,11563,7678, - 4320,11289,9198,12208,2963,7393,2366,9238 - }; - - private static final char[/*PARAM_N*/] psis_bitrev_montgomery = { - 4075,6974,7373,7965,3262,5079,522,2169,6364,1018,1041,8775,2344, - 11011,5574,1973,4536,1050,6844,3860,3818,6118,2683,1190,4789,7822, - 7540,6752,5456,4449,3789,12142,11973,382,3988,468,6843,5339,6196,3710, - 11316,1254,5435,10930,3998,10256,10367,3879,11889,1728,6137,4948, - 5862,6136,3643,6874,8724,654,10302,1702,7083,6760,56,3199,9987,605, - 11785,8076,5594,9260,6403,4782,6212,4624,9026,8689,4080,11868,6221, - 3602,975,8077,8851,9445,5681,3477,1105,142,241,12231,1003,3532,5009, - 1956,6008,11404,7377,2049,10968,12097,7591,5057,3445,4780,2920, - 7048,3127,8120,11279,6821,11502,8807,12138,2127,2839,3957,431,1579, - 6383,9784,5874,677,3336,6234,2766,1323,9115,12237,2031,6956,6413, - 2281,3969,3991,12133,9522,4737,10996,4774,5429,11871,3772,453, - 5908,2882,1805,2051,1954,11713,3963,2447,6142,8174,3030,1843,2361, - 12071,2908,3529,3434,3202,7796,2057,5369,11939,1512,6906,10474, - 11026,49,10806,5915,1489,9789,5942,10706,10431,7535,426,8974,3757, - 10314,9364,347,5868,9551,9634,6554,10596,9280,11566,174,2948,2503, - 6507,10723,11606,2459,64,3656,8455,5257,5919,7856,1747,9166,5486, - 9235,6065,835,3570,4240,11580,4046,10970,9139,1058,8210,11848,922, - 7967,1958,10211,1112,3728,4049,11130,5990,1404,325,948,11143,6190, - 295,11637,5766,8212,8273,2919,8527,6119,6992,8333,1360,2555,6167, - 1200,7105,7991,3329,9597,12121,5106,5961,10695,10327,3051,9923, - 4896,9326,81,3091,1000,7969,4611,726,1853,12149,4255,11112,2768, - 10654,1062,2294,3553,4805,2747,4846,8577,9154,1170,2319,790,11334, - 9275,9088,1326,5086,9094,6429,11077,10643,3504,3542,8668,9744,1479, - 1,8246,7143,11567,10984,4134,5736,4978,10938,5777,8961,4591,5728, - 6461,5023,9650,7468,949,9664,2975,11726,2744,9283,10092,5067,12171, - 2476,3748,11336,6522,827,9452,5374,12159,7935,3296,3949,9893,4452, - 10908,2525,3584,8112,8011,10616,4989,6958,11809,9447,12280,1022, - 11950,9821,11745,5791,5092,2089,9005,2881,3289,2013,9048,729,7901, - 1260,5755,4632,11955,2426,10593,1428,4890,5911,3932,9558,8830,3637, - 5542,145,5179,8595,3707,10530,355,3382,4231,9741,1207,9041,7012, - 1168,10146,11224,4645,11885,10911,10377,435,7952,4096,493,9908,6845, - 6039,2422,2187,9723,8643,9852,9302,6022,7278,1002,4284,5088,1607, - 7313,875,8509,9430,1045,2481,5012,7428,354,6591,9377,11847,2401, - 1067,7188,11516,390,8511,8456,7270,545,8585,9611,12047,1537,4143, - 4714,4885,1017,5084,1632,3066,27,1440,8526,9273,12046,11618,9289, - 3400,9890,3136,7098,8758,11813,7384,3985,11869,6730,10745,10111, - 2249,4048,2884,11136,2126,1630,9103,5407,2686,9042,2969,8311,9424, - 9919,8779,5332,10626,1777,4654,10863,7351,3636,9585,5291,8374, - 2166,4919,12176,9140,12129,7852,12286,4895,10805,2780,5195,2305, - 7247,9644,4053,10600,3364,3271,4057,4414,9442,7917,2174,3947, - 11951,2455,6599,10545,10975,3654,2894,7681,7126,7287,12269,4119, - 3343,2151,1522,7174,7350,11041,2442,2148,5959,6492,8330,8945,5598, - 3624,10397,1325,6565,1945,11260,10077,2674,3338,3276,11034,506, - 6505,1392,5478,8778,1178,2776,3408,10347,11124,2575,9489,12096, - 6092,10058,4167,6085,923,11251,11912,4578,10669,11914,425,10453, - 392,10104,8464,4235,8761,7376,2291,3375,7954,8896,6617,7790,1737, - 11667,3982,9342,6680,636,6825,7383,512,4670,2900,12050,7735,994, - 1687,11883,7021,146,10485,1403,5189,6094,2483,2054,3042,10945, - 3981,10821,11826,8882,8151,180,9600,7684,5219,10880,6780,204, - 11232,2600,7584,3121,3017,11053,7814,7043,4251,4739,11063,6771, - 7073,9261,2360,11925,1928,11825,8024,3678,3205,3359,11197,5209, - 8581,3238,8840,1136,9363,1826,3171,4489,7885,346,2068,1389,8257, - 3163,4840,6127,8062,8921,612,4238,10763,8067,125,11749,10125,5416, - 2110,716,9839,10584,11475,11873,3448,343,1908,4538,10423,7078, - 4727,1208,11572,3589,2982,1373,1721,10753,4103,2429,4209,5412, - 5993,9011,438,3515,7228,1218,8347,5232,8682,1327,7508,4924,448, - 1014,10029,12221,4566,5836,12229,2717,1535,3200,5588,5845,412, - 5102,7326,3744,3056,2528,7406,8314,9202,6454,6613,1417,10032,7784, - 1518,3765,4176,5063,9828,2275,6636,4267,6463,2065,7725,3495,8328, - 8755,8144,10533,5966,12077,9175,9520,5596,6302,8400,579,6781,11014, - 5734,11113,11164,4860,1131,10844,9068,8016,9694,3837,567,9348,7000, - 6627,7699,5082,682,11309,5207,4050,7087,844,7434,3769,293,9057, - 6940,9344,10883,2633,8190,3944,5530,5604,3480,2171,9282,11024,2213, - 8136,3805,767,12239,216,11520,6763,10353,7,8566,845,7235,3154,4360, - 3285,10268,2832,3572,1282,7559,3229,8360,10583,6105,3120,6643,6203, - 8536,8348,6919,3536,9199,10891,11463,5043,1658,5618,8787,5789,4719, - 751,11379,6389,10783,3065,7806,6586,2622,5386,510,7628,6921,578, - 10345,11839,8929,4684,12226,7154,9916,7302,8481,3670,11066,2334, - 1590,7878,10734,1802,1891,5103,6151,8820,3418,7846,9951,4693,417, - 9996,9652,4510,2946,5461,365,881,1927,1015,11675,11009,1371,12265, - 2485,11385,5039,6742,8449,1842,12217,8176,9577,4834,7937,9461,2643, - 11194,3045,6508,4094,3451,7911,11048,5406,4665,3020,6616,11345, - 7519,3669,5287,1790,7014,5410,11038,11249,2035,6125,10407,4565, - 7315,5078,10506,2840,2478,9270,4194,9195,4518,7469,1160,6878,2730, - 10421,10036,1734,3815,10939,5832,10595,10759,4423,8420,9617,7119, - 11010,11424,9173,189,10080,10526,3466,10588,7592,3578,11511,7785, - 9663,530,12150,8957,2532,3317,9349,10243,1481,9332,3454,3758,7899, - 4218,2593,11410,2276,982,6513,1849,8494,9021,4523,7988,8,457,648, - 150,8000,2307,2301,874,5650,170,9462,2873,9855,11498,2535,11169, - 5808,12268,9687,1901,7171,11787,3846,1573,6063,3793,466,11259, - 10608,3821,6320,4649,6263,2929 - }; - - private static final char[/*PARAM_N*/] psis_inv_montgomery = { - 256,10570,1510,7238,1034,7170,6291,7921,11665,3422,4000,2327, - 2088,5565,795,10647,1521,5484,2539,7385,1055,7173,8047,11683, - 1669,1994,3796,5809,4341,9398,11876,12230,10525,12037,12253, - 3506,4012,9351,4847,2448,7372,9831,3160,2207,5582,2553,7387,6322, - 9681,1383,10731,1533,219,5298,4268,7632,6357,9686,8406,4712,9451, - 10128,4958,5975,11387,8649,11769,6948,11526,12180,1740,10782, - 6807,2728,7412,4570,4164,4106,11120,12122,8754,11784,3439,5758, - 11356,6889,9762,11928,1704,1999,10819,12079,12259,7018,11536, - 1648,1991,2040,2047,2048,10826,12080,8748,8272,8204,1172,1923, - 7297,2798,7422,6327,4415,7653,6360,11442,12168,7005,8023,9924, - 8440,8228,2931,7441,1063,3663,5790,9605,10150,1450,8985,11817, - 10466,10273,12001,3470,7518,1074,1909,7295,9820,4914,702,5367, - 7789,8135,9940,1420,3714,11064,12114,12264,1752,5517,9566,11900, - 1700,3754,5803,829,1874,7290,2797,10933,5073,7747,8129,6428, - 6185,11417,1631,233,5300,9535,10140,11982,8734,8270,2937,10953, - 8587,8249,2934,9197,4825,5956,4362,9401,1343,3703,529,10609, - 12049,6988,6265,895,3639,4031,4087,4095,585,10617,8539,4731, - 4187,9376,3095,9220,10095,10220,1460,10742,12068,1724,5513, - 11321,6884,2739,5658,6075,4379,11159,10372,8504,4726,9453,3106, - 7466,11600,10435,8513,9994,8450,9985,3182,10988,8592,2983,9204, - 4826,2445,5616,6069,867,3635,5786,11360,5134,2489,10889,12089, - 1727,7269,2794,9177,1311,5454,9557,6632,2703,9164,10087,1441, - 3717,531,3587,2268,324,5313,759,1864,5533,2546,7386,9833,8427, - 4715,11207,1601,7251,4547,11183,12131,1733,10781,10318,1474, - 10744,5046,4232,11138,10369,6748,964,7160,4534,7670,8118,8182, - 4680,11202,6867,981,8918,1274,182,26,7026,8026,11680,12202, - 10521,1503,7237,4545,5916,9623,8397,11733,10454,3249,9242,6587, - 941,1890,270,10572,6777,9746,6659,6218,6155,6146,878,1881,7291, - 11575,12187,1741,7271,8061,11685,6936,4502,9421,4857,4205,7623, - 1089,10689,1527,8996,10063,11971,10488,6765,2722,3900,9335,11867, - 6962,11528,5158,4248,4118,5855,2592,5637,6072,2623,7397,8079, - 9932,4930,5971,853,3633,519,8852,11798,3441,11025,1575,225,8810, - 11792,12218,3501,9278,3081,9218,4828,7712,8124,11694,12204,3499, - 4011,573,3593,5780,7848,9899,10192,1456,208,7052,2763,7417,11593, - 10434,12024,8740,11782,10461,3250,5731,7841,9898,1414,202,3540, - 7528,2831,2160,10842,5060,4234,4116,588,84,12,7024,2759,9172,6577, - 11473,1639,9012,3043,7457,6332,11438,1634,1989,9062,11828,8712, - 11778,12216,10523,6770,9745,10170,4964,9487,6622,946,8913,6540, - 6201,4397,9406,8366,9973,8447,8229,11709,8695,10020,3187,5722, - 2573,10901,6824,4486,4152,9371,8361,2950,2177,311,1800,9035, - 8313,11721,3430,490,70,10,1757,251,3547,7529,11609,3414,7510, - 4584,4166,9373,1339,5458,7802,11648,1664,7260,9815,10180,6721, - 9738,10169,8475,8233,9954,1422,8981,1283,5450,11312,1616,3742, - 11068,10359,4991,713,3613,9294,8350,4704,672,96,7036,9783,11931, - 3460,5761,823,10651,12055,10500,1500,5481,783,3623,11051,8601, - 8251,8201,11705,10450,5004,4226,7626,2845,2162,3820,7568,9859, - 3164,452,10598,1514,5483,6050,6131,4387,7649,8115,6426,918,8909, - 8295,1185,5436,11310,8638,1234,5443,11311,5127,2488,2111,10835, - 5059,7745,2862,3920,560,80,1767,2008,3798,11076,6849,2734,10924, - 12094,8750,1250,10712,6797,971,7161,1023,8924,4786,7706,4612,4170, - 7618,6355,4419,5898,11376,10403,10264,6733,4473,639,5358,2521, - 9138,3061,5704,4326,618,5355,765,5376,768,7132,4530,9425,3102, - 9221,6584,11474,10417,10266,12000,6981,6264,4406,2385,7363,4563, - 4163,7617,9866,3165,9230,11852,10471,5007,5982,11388,5138,734, - 3616,11050,12112,6997,11533,12181,10518,12036,3475,2252,7344, - 9827,4915,9480,6621,4457,7659,9872,6677,4465,4149,7615,4599,657, - 3605,515,10607,6782,4480,640,1847,3775,5806,2585,5636,9583,1369, - 10729,8555,10000,11962,5220,7768,8132,8184,9947,1421,203,29,8782, - 11788,1684,10774,10317,4985,9490,8378,4708,11206,5112,5997,7879, - 11659,12199,8765,10030,4944,5973,6120,6141,6144,7900,11662,1666, - 238,34,3516,5769,9602,8394,9977,6692,956,10670,6791,9748,11926, - 8726,11780,5194,742,106,8793,10034,3189,10989,5081,4237,5872,4350, - 2377,10873,6820,6241,11425,10410,10265,3222,5727,9596,4882,2453, - 2106,3812,11078,12116,5242,4260,11142,8614,11764,12214,5256,4262, - 4120,11122,5100,11262,5120,2487,5622,9581,8391,8221,2930,10952, - 12098,6995,6266,9673,4893,699,3611,4027,5842,11368,1624,232,8811, - 8281,1183,169,8802,3013,2186,5579,797,3625,4029,11109,1587,7249, - 11569,8675,6506,2685,10917,12093,12261,12285,1755,7273,1039,1904, - 272,3550,9285,3082,5707,6082,4380,7648,11626,5172,4250,9385,8363, - 8217,4685,5936,848,8899,6538,934,1889,3781,9318,10109,10222,6727, - 961,5404,772,5377,9546,8386,1198,8949,3034,2189,7335,4559,5918,2601, - 10905,5069,9502,3113,7467,8089,11689,5181,9518,8382,2953,3933,4073, - 4093,7607,8109,2914,5683,4323,11151,1593,10761,6804,972,3650,2277, - 5592,4310,7638,9869,4921,703,1856,9043,4803,9464,1352,8971,11815, - 5199,7765,6376,4422,7654,2849,407,8836,6529,7955,2892,9191,1313, - 10721,12065,12257,1751,9028,8312,2943,2176,3822,546,78,8789,11789, - 10462,12028,6985,4509,9422,1346,5459,4291,613,10621,6784,9747,3148, - 7472,2823,5670,810,7138,8042,4660,7688,6365,6176,6149,2634,5643, - 9584,10147,11983,5223,9524,11894,10477,8519,1217,3685,2282,326, - 10580,3267,7489,4581,2410,5611,11335,6886,8006,8166,11700,3427, - 11023,8597,10006,3185,455,65,5276,7776,4622,5927,7869,9902,11948, - 5218,2501,5624,2559,10899,1557,1978,10816,10323,8497,4725,675,1852, - 10798,12076,10503,3256,9243,3076,2195,10847,12083,10504,12034,10497 - }; -} diff --git a/src/main/java/com/southernstorm/noise/crypto/NewHopeTor.java b/src/main/java/com/southernstorm/noise/crypto/NewHopeTor.java deleted file mode 100644 index 55855a9e8..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/NewHopeTor.java +++ /dev/null @@ -1,982 +0,0 @@ -/* - * Based on the public domain C reference code for New Hope. - * This Java version is also placed into the public domain. - * - * Original authors: Erdem Alkim, Léo Ducas, Thomas Pöppelmann, Peter Schwabe - * Java port: Rhys Weatherley - */ - -package com.southernstorm.noise.crypto; - -import java.util.Arrays; - -/** - * New Hope key exchange algorithm, "torref" variant. - * - * This version of New Hope implements the alternative constant-time - * method for generating the public "a" value for anonymity networks - * like Tor. It is not binary-compatible with the standard New Hope - * implementation in the NewHope class. - * - * Reference: https://cryptojedi.org/papers/newhope-20160803.pdf - * - * @see NewHope - */ -public class NewHopeTor extends NewHope { - - public NewHopeTor() {} - - @Override - protected void uniform(char[] coeffs, byte[] seed) - { - long[] state = new long [25]; - int nblocks=16; - byte[] buf = new byte [SHAKE128_RATE*nblocks]; - char[] x = new char [buf.length / 2]; - - try { - shake128_absorb(state, seed, 0, SEEDBYTES); - do - { - shake128_squeezeblocks(buf, 0, nblocks, state); - for (int i = buf.length - 2; i >= 0; i -= 2) - { - x[i / 2] = (char)((buf[i] & 0xff) | ((buf[i+1] & 0xff) << 8)); - } - } - while (discardtopoly(coeffs, x)); - } finally { - Arrays.fill(state, 0); - Arrays.fill(buf, (byte)0); - Arrays.fill(x, (char)0); - } - } - - private static boolean discardtopoly(char[] coeffs, char[] x) - { - int i, r=0; - - for(i=0;i<16;i++) - batcher84(x, i); - - // Check whether we're safe: - for(i=1008;i<1024;i++) - r |= 61444 - x[i]; - if((r >>= 31) != 0) return true; - - // If we are, copy coefficients to polynomial: - for(i=0;i> 31); x[offset + 0] ^= t; x[offset + 16] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 48]) & (c >> 31); x[offset + 32] ^= t; x[offset + 48] ^= t; - c = 61444 - x[offset + 0]; t = (x[offset + 0] ^ x[offset + 32]) & (c >> 31); x[offset + 0] ^= t; x[offset + 32] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 48]) & (c >> 31); x[offset + 16] ^= t; x[offset + 48] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 32]) & (c >> 31); x[offset + 16] ^= t; x[offset + 32] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 80]) & (c >> 31); x[offset + 64] ^= t; x[offset + 80] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 112]) & (c >> 31); x[offset + 96] ^= t; x[offset + 112] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 96]) & (c >> 31); x[offset + 64] ^= t; x[offset + 96] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 112]) & (c >> 31); x[offset + 80] ^= t; x[offset + 112] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 96]) & (c >> 31); x[offset + 80] ^= t; x[offset + 96] ^= t; - c = 61444 - x[offset + 0]; t = (x[offset + 0] ^ x[offset + 64]) & (c >> 31); x[offset + 0] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 96]) & (c >> 31); x[offset + 32] ^= t; x[offset + 96] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 64]) & (c >> 31); x[offset + 32] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 80]) & (c >> 31); x[offset + 16] ^= t; x[offset + 80] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 112]) & (c >> 31); x[offset + 48] ^= t; x[offset + 112] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 80]) & (c >> 31); x[offset + 48] ^= t; x[offset + 80] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 32]) & (c >> 31); x[offset + 16] ^= t; x[offset + 32] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 64]) & (c >> 31); x[offset + 48] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 96]) & (c >> 31); x[offset + 80] ^= t; x[offset + 96] ^= t; - c = 61444 - x[offset + 128]; t = (x[offset + 128] ^ x[offset + 144]) & (c >> 31); x[offset + 128] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 176]) & (c >> 31); x[offset + 160] ^= t; x[offset + 176] ^= t; - c = 61444 - x[offset + 128]; t = (x[offset + 128] ^ x[offset + 160]) & (c >> 31); x[offset + 128] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 176]) & (c >> 31); x[offset + 144] ^= t; x[offset + 176] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 160]) & (c >> 31); x[offset + 144] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 208]) & (c >> 31); x[offset + 192] ^= t; x[offset + 208] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 240]) & (c >> 31); x[offset + 224] ^= t; x[offset + 240] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 224]) & (c >> 31); x[offset + 192] ^= t; x[offset + 224] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 240]) & (c >> 31); x[offset + 208] ^= t; x[offset + 240] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 224]) & (c >> 31); x[offset + 208] ^= t; x[offset + 224] ^= t; - c = 61444 - x[offset + 128]; t = (x[offset + 128] ^ x[offset + 192]) & (c >> 31); x[offset + 128] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 224]) & (c >> 31); x[offset + 160] ^= t; x[offset + 224] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 192]) & (c >> 31); x[offset + 160] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 208]) & (c >> 31); x[offset + 144] ^= t; x[offset + 208] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 240]) & (c >> 31); x[offset + 176] ^= t; x[offset + 240] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 208]) & (c >> 31); x[offset + 176] ^= t; x[offset + 208] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 160]) & (c >> 31); x[offset + 144] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 192]) & (c >> 31); x[offset + 176] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 224]) & (c >> 31); x[offset + 208] ^= t; x[offset + 224] ^= t; - c = 61444 - x[offset + 0]; t = (x[offset + 0] ^ x[offset + 128]) & (c >> 31); x[offset + 0] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 192]) & (c >> 31); x[offset + 64] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 128]) & (c >> 31); x[offset + 64] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 160]) & (c >> 31); x[offset + 32] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 224]) & (c >> 31); x[offset + 96] ^= t; x[offset + 224] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 160]) & (c >> 31); x[offset + 96] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 64]) & (c >> 31); x[offset + 32] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 128]) & (c >> 31); x[offset + 96] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 192]) & (c >> 31); x[offset + 160] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 144]) & (c >> 31); x[offset + 16] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 208]) & (c >> 31); x[offset + 80] ^= t; x[offset + 208] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 144]) & (c >> 31); x[offset + 80] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 176]) & (c >> 31); x[offset + 48] ^= t; x[offset + 176] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 240]) & (c >> 31); x[offset + 112] ^= t; x[offset + 240] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 176]) & (c >> 31); x[offset + 112] ^= t; x[offset + 176] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 80]) & (c >> 31); x[offset + 48] ^= t; x[offset + 80] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 144]) & (c >> 31); x[offset + 112] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 208]) & (c >> 31); x[offset + 176] ^= t; x[offset + 208] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 32]) & (c >> 31); x[offset + 16] ^= t; x[offset + 32] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 64]) & (c >> 31); x[offset + 48] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 96]) & (c >> 31); x[offset + 80] ^= t; x[offset + 96] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 128]) & (c >> 31); x[offset + 112] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 160]) & (c >> 31); x[offset + 144] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 192]) & (c >> 31); x[offset + 176] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 224]) & (c >> 31); x[offset + 208] ^= t; x[offset + 224] ^= t; - c = 61444 - x[offset + 256]; t = (x[offset + 256] ^ x[offset + 272]) & (c >> 31); x[offset + 256] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 304]) & (c >> 31); x[offset + 288] ^= t; x[offset + 304] ^= t; - c = 61444 - x[offset + 256]; t = (x[offset + 256] ^ x[offset + 288]) & (c >> 31); x[offset + 256] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 304]) & (c >> 31); x[offset + 272] ^= t; x[offset + 304] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 288]) & (c >> 31); x[offset + 272] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 336]) & (c >> 31); x[offset + 320] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 368]) & (c >> 31); x[offset + 352] ^= t; x[offset + 368] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 352]) & (c >> 31); x[offset + 320] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 368]) & (c >> 31); x[offset + 336] ^= t; x[offset + 368] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 352]) & (c >> 31); x[offset + 336] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 256]; t = (x[offset + 256] ^ x[offset + 320]) & (c >> 31); x[offset + 256] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 352]) & (c >> 31); x[offset + 288] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 320]) & (c >> 31); x[offset + 288] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 336]) & (c >> 31); x[offset + 272] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 368]) & (c >> 31); x[offset + 304] ^= t; x[offset + 368] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 336]) & (c >> 31); x[offset + 304] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 288]) & (c >> 31); x[offset + 272] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 320]) & (c >> 31); x[offset + 304] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 352]) & (c >> 31); x[offset + 336] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 384]; t = (x[offset + 384] ^ x[offset + 400]) & (c >> 31); x[offset + 384] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 432]) & (c >> 31); x[offset + 416] ^= t; x[offset + 432] ^= t; - c = 61444 - x[offset + 384]; t = (x[offset + 384] ^ x[offset + 416]) & (c >> 31); x[offset + 384] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 432]) & (c >> 31); x[offset + 400] ^= t; x[offset + 432] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 416]) & (c >> 31); x[offset + 400] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 448]; t = (x[offset + 448] ^ x[offset + 464]) & (c >> 31); x[offset + 448] ^= t; x[offset + 464] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 496]) & (c >> 31); x[offset + 480] ^= t; x[offset + 496] ^= t; - c = 61444 - x[offset + 448]; t = (x[offset + 448] ^ x[offset + 480]) & (c >> 31); x[offset + 448] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 496]) & (c >> 31); x[offset + 464] ^= t; x[offset + 496] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 480]) & (c >> 31); x[offset + 464] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 384]; t = (x[offset + 384] ^ x[offset + 448]) & (c >> 31); x[offset + 384] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 480]) & (c >> 31); x[offset + 416] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 448]) & (c >> 31); x[offset + 416] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 464]) & (c >> 31); x[offset + 400] ^= t; x[offset + 464] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 496]) & (c >> 31); x[offset + 432] ^= t; x[offset + 496] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 464]) & (c >> 31); x[offset + 432] ^= t; x[offset + 464] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 416]) & (c >> 31); x[offset + 400] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 448]) & (c >> 31); x[offset + 432] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 480]) & (c >> 31); x[offset + 464] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 256]; t = (x[offset + 256] ^ x[offset + 384]) & (c >> 31); x[offset + 256] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 448]) & (c >> 31); x[offset + 320] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 384]) & (c >> 31); x[offset + 320] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 416]) & (c >> 31); x[offset + 288] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 480]) & (c >> 31); x[offset + 352] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 416]) & (c >> 31); x[offset + 352] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 320]) & (c >> 31); x[offset + 288] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 384]) & (c >> 31); x[offset + 352] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 448]) & (c >> 31); x[offset + 416] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 400]) & (c >> 31); x[offset + 272] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 464]) & (c >> 31); x[offset + 336] ^= t; x[offset + 464] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 400]) & (c >> 31); x[offset + 336] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 432]) & (c >> 31); x[offset + 304] ^= t; x[offset + 432] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 496]) & (c >> 31); x[offset + 368] ^= t; x[offset + 496] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 432]) & (c >> 31); x[offset + 368] ^= t; x[offset + 432] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 336]) & (c >> 31); x[offset + 304] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 400]) & (c >> 31); x[offset + 368] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 464]) & (c >> 31); x[offset + 432] ^= t; x[offset + 464] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 288]) & (c >> 31); x[offset + 272] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 320]) & (c >> 31); x[offset + 304] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 352]) & (c >> 31); x[offset + 336] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 384]) & (c >> 31); x[offset + 368] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 416]) & (c >> 31); x[offset + 400] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 448]) & (c >> 31); x[offset + 432] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 480]) & (c >> 31); x[offset + 464] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 0]; t = (x[offset + 0] ^ x[offset + 256]) & (c >> 31); x[offset + 0] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 128]; t = (x[offset + 128] ^ x[offset + 384]) & (c >> 31); x[offset + 128] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 128]; t = (x[offset + 128] ^ x[offset + 256]) & (c >> 31); x[offset + 128] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 320]) & (c >> 31); x[offset + 64] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 448]) & (c >> 31); x[offset + 192] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 320]) & (c >> 31); x[offset + 192] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 128]) & (c >> 31); x[offset + 64] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 256]) & (c >> 31); x[offset + 192] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 384]) & (c >> 31); x[offset + 320] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 288]) & (c >> 31); x[offset + 32] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 416]) & (c >> 31); x[offset + 160] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 288]) & (c >> 31); x[offset + 160] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 352]) & (c >> 31); x[offset + 96] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 480]) & (c >> 31); x[offset + 224] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 352]) & (c >> 31); x[offset + 224] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 160]) & (c >> 31); x[offset + 96] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 288]) & (c >> 31); x[offset + 224] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 416]) & (c >> 31); x[offset + 352] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 64]) & (c >> 31); x[offset + 32] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 128]) & (c >> 31); x[offset + 96] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 192]) & (c >> 31); x[offset + 160] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 256]) & (c >> 31); x[offset + 224] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 320]) & (c >> 31); x[offset + 288] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 384]) & (c >> 31); x[offset + 352] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 448]) & (c >> 31); x[offset + 416] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 272]) & (c >> 31); x[offset + 16] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 400]) & (c >> 31); x[offset + 144] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 272]) & (c >> 31); x[offset + 144] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 336]) & (c >> 31); x[offset + 80] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 464]) & (c >> 31); x[offset + 208] ^= t; x[offset + 464] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 336]) & (c >> 31); x[offset + 208] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 144]) & (c >> 31); x[offset + 80] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 272]) & (c >> 31); x[offset + 208] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 400]) & (c >> 31); x[offset + 336] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 304]) & (c >> 31); x[offset + 48] ^= t; x[offset + 304] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 432]) & (c >> 31); x[offset + 176] ^= t; x[offset + 432] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 304]) & (c >> 31); x[offset + 176] ^= t; x[offset + 304] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 368]) & (c >> 31); x[offset + 112] ^= t; x[offset + 368] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 496]) & (c >> 31); x[offset + 240] ^= t; x[offset + 496] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 368]) & (c >> 31); x[offset + 240] ^= t; x[offset + 368] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 176]) & (c >> 31); x[offset + 112] ^= t; x[offset + 176] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 304]) & (c >> 31); x[offset + 240] ^= t; x[offset + 304] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 432]) & (c >> 31); x[offset + 368] ^= t; x[offset + 432] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 80]) & (c >> 31); x[offset + 48] ^= t; x[offset + 80] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 144]) & (c >> 31); x[offset + 112] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 208]) & (c >> 31); x[offset + 176] ^= t; x[offset + 208] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 272]) & (c >> 31); x[offset + 240] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 336]) & (c >> 31); x[offset + 304] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 400]) & (c >> 31); x[offset + 368] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 464]) & (c >> 31); x[offset + 432] ^= t; x[offset + 464] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 32]) & (c >> 31); x[offset + 16] ^= t; x[offset + 32] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 64]) & (c >> 31); x[offset + 48] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 96]) & (c >> 31); x[offset + 80] ^= t; x[offset + 96] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 128]) & (c >> 31); x[offset + 112] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 160]) & (c >> 31); x[offset + 144] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 192]) & (c >> 31); x[offset + 176] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 224]) & (c >> 31); x[offset + 208] ^= t; x[offset + 224] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 256]) & (c >> 31); x[offset + 240] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 288]) & (c >> 31); x[offset + 272] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 320]) & (c >> 31); x[offset + 304] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 352]) & (c >> 31); x[offset + 336] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 384]) & (c >> 31); x[offset + 368] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 416]) & (c >> 31); x[offset + 400] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 448]) & (c >> 31); x[offset + 432] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 480]) & (c >> 31); x[offset + 464] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 512]; t = (x[offset + 512] ^ x[offset + 528]) & (c >> 31); x[offset + 512] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 560]) & (c >> 31); x[offset + 544] ^= t; x[offset + 560] ^= t; - c = 61444 - x[offset + 512]; t = (x[offset + 512] ^ x[offset + 544]) & (c >> 31); x[offset + 512] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 560]) & (c >> 31); x[offset + 528] ^= t; x[offset + 560] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 544]) & (c >> 31); x[offset + 528] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 576]; t = (x[offset + 576] ^ x[offset + 592]) & (c >> 31); x[offset + 576] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 624]) & (c >> 31); x[offset + 608] ^= t; x[offset + 624] ^= t; - c = 61444 - x[offset + 576]; t = (x[offset + 576] ^ x[offset + 608]) & (c >> 31); x[offset + 576] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 624]) & (c >> 31); x[offset + 592] ^= t; x[offset + 624] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 608]) & (c >> 31); x[offset + 592] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 512]; t = (x[offset + 512] ^ x[offset + 576]) & (c >> 31); x[offset + 512] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 608]) & (c >> 31); x[offset + 544] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 576]) & (c >> 31); x[offset + 544] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 592]) & (c >> 31); x[offset + 528] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 624]) & (c >> 31); x[offset + 560] ^= t; x[offset + 624] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 592]) & (c >> 31); x[offset + 560] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 544]) & (c >> 31); x[offset + 528] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 576]) & (c >> 31); x[offset + 560] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 608]) & (c >> 31); x[offset + 592] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 640]; t = (x[offset + 640] ^ x[offset + 656]) & (c >> 31); x[offset + 640] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 688]) & (c >> 31); x[offset + 672] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 640]; t = (x[offset + 640] ^ x[offset + 672]) & (c >> 31); x[offset + 640] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 688]) & (c >> 31); x[offset + 656] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 672]) & (c >> 31); x[offset + 656] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 720]) & (c >> 31); x[offset + 704] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 752]) & (c >> 31); x[offset + 736] ^= t; x[offset + 752] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 736]) & (c >> 31); x[offset + 704] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 752]) & (c >> 31); x[offset + 720] ^= t; x[offset + 752] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 736]) & (c >> 31); x[offset + 720] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 640]; t = (x[offset + 640] ^ x[offset + 704]) & (c >> 31); x[offset + 640] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 736]) & (c >> 31); x[offset + 672] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 704]) & (c >> 31); x[offset + 672] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 720]) & (c >> 31); x[offset + 656] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 752]) & (c >> 31); x[offset + 688] ^= t; x[offset + 752] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 720]) & (c >> 31); x[offset + 688] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 672]) & (c >> 31); x[offset + 656] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 704]) & (c >> 31); x[offset + 688] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 736]) & (c >> 31); x[offset + 720] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 512]; t = (x[offset + 512] ^ x[offset + 640]) & (c >> 31); x[offset + 512] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 576]; t = (x[offset + 576] ^ x[offset + 704]) & (c >> 31); x[offset + 576] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 576]; t = (x[offset + 576] ^ x[offset + 640]) & (c >> 31); x[offset + 576] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 672]) & (c >> 31); x[offset + 544] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 736]) & (c >> 31); x[offset + 608] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 672]) & (c >> 31); x[offset + 608] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 576]) & (c >> 31); x[offset + 544] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 640]) & (c >> 31); x[offset + 608] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 704]) & (c >> 31); x[offset + 672] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 656]) & (c >> 31); x[offset + 528] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 720]) & (c >> 31); x[offset + 592] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 656]) & (c >> 31); x[offset + 592] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 688]) & (c >> 31); x[offset + 560] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 752]) & (c >> 31); x[offset + 624] ^= t; x[offset + 752] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 688]) & (c >> 31); x[offset + 624] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 592]) & (c >> 31); x[offset + 560] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 656]) & (c >> 31); x[offset + 624] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 720]) & (c >> 31); x[offset + 688] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 544]) & (c >> 31); x[offset + 528] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 576]) & (c >> 31); x[offset + 560] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 608]) & (c >> 31); x[offset + 592] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 640]) & (c >> 31); x[offset + 624] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 672]) & (c >> 31); x[offset + 656] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 704]) & (c >> 31); x[offset + 688] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 736]) & (c >> 31); x[offset + 720] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 768]; t = (x[offset + 768] ^ x[offset + 784]) & (c >> 31); x[offset + 768] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 816]) & (c >> 31); x[offset + 800] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 768]; t = (x[offset + 768] ^ x[offset + 800]) & (c >> 31); x[offset + 768] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 816]) & (c >> 31); x[offset + 784] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 800]) & (c >> 31); x[offset + 784] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 832]; t = (x[offset + 832] ^ x[offset + 848]) & (c >> 31); x[offset + 832] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 880]) & (c >> 31); x[offset + 864] ^= t; x[offset + 880] ^= t; - c = 61444 - x[offset + 832]; t = (x[offset + 832] ^ x[offset + 864]) & (c >> 31); x[offset + 832] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 880]) & (c >> 31); x[offset + 848] ^= t; x[offset + 880] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 864]) & (c >> 31); x[offset + 848] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 768]; t = (x[offset + 768] ^ x[offset + 832]) & (c >> 31); x[offset + 768] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 864]) & (c >> 31); x[offset + 800] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 832]) & (c >> 31); x[offset + 800] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 848]) & (c >> 31); x[offset + 784] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 880]) & (c >> 31); x[offset + 816] ^= t; x[offset + 880] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 848]) & (c >> 31); x[offset + 816] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 800]) & (c >> 31); x[offset + 784] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 832]) & (c >> 31); x[offset + 816] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 864]) & (c >> 31); x[offset + 848] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 896]; t = (x[offset + 896] ^ x[offset + 912]) & (c >> 31); x[offset + 896] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 928]; t = (x[offset + 928] ^ x[offset + 944]) & (c >> 31); x[offset + 928] ^= t; x[offset + 944] ^= t; - c = 61444 - x[offset + 896]; t = (x[offset + 896] ^ x[offset + 928]) & (c >> 31); x[offset + 896] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 944]) & (c >> 31); x[offset + 912] ^= t; x[offset + 944] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 928]) & (c >> 31); x[offset + 912] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 960]; t = (x[offset + 960] ^ x[offset + 976]) & (c >> 31); x[offset + 960] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 992]; t = (x[offset + 992] ^ x[offset + 1008]) & (c >> 31); x[offset + 992] ^= t; x[offset + 1008] ^= t; - c = 61444 - x[offset + 960]; t = (x[offset + 960] ^ x[offset + 992]) & (c >> 31); x[offset + 960] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 1008]) & (c >> 31); x[offset + 976] ^= t; x[offset + 1008] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 992]) & (c >> 31); x[offset + 976] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 896]; t = (x[offset + 896] ^ x[offset + 960]) & (c >> 31); x[offset + 896] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 928]; t = (x[offset + 928] ^ x[offset + 992]) & (c >> 31); x[offset + 928] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 928]; t = (x[offset + 928] ^ x[offset + 960]) & (c >> 31); x[offset + 928] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 976]) & (c >> 31); x[offset + 912] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 1008]) & (c >> 31); x[offset + 944] ^= t; x[offset + 1008] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 976]) & (c >> 31); x[offset + 944] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 928]) & (c >> 31); x[offset + 912] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 960]) & (c >> 31); x[offset + 944] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 992]) & (c >> 31); x[offset + 976] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 768]; t = (x[offset + 768] ^ x[offset + 896]) & (c >> 31); x[offset + 768] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 832]; t = (x[offset + 832] ^ x[offset + 960]) & (c >> 31); x[offset + 832] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 832]; t = (x[offset + 832] ^ x[offset + 896]) & (c >> 31); x[offset + 832] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 928]) & (c >> 31); x[offset + 800] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 992]) & (c >> 31); x[offset + 864] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 928]) & (c >> 31); x[offset + 864] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 832]) & (c >> 31); x[offset + 800] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 896]) & (c >> 31); x[offset + 864] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 928]; t = (x[offset + 928] ^ x[offset + 960]) & (c >> 31); x[offset + 928] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 912]) & (c >> 31); x[offset + 784] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 976]) & (c >> 31); x[offset + 848] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 912]) & (c >> 31); x[offset + 848] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 944]) & (c >> 31); x[offset + 816] ^= t; x[offset + 944] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 1008]) & (c >> 31); x[offset + 880] ^= t; x[offset + 1008] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 944]) & (c >> 31); x[offset + 880] ^= t; x[offset + 944] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 848]) & (c >> 31); x[offset + 816] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 912]) & (c >> 31); x[offset + 880] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 976]) & (c >> 31); x[offset + 944] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 800]) & (c >> 31); x[offset + 784] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 832]) & (c >> 31); x[offset + 816] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 864]) & (c >> 31); x[offset + 848] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 896]) & (c >> 31); x[offset + 880] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 928]) & (c >> 31); x[offset + 912] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 960]) & (c >> 31); x[offset + 944] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 992]) & (c >> 31); x[offset + 976] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 512]; t = (x[offset + 512] ^ x[offset + 768]) & (c >> 31); x[offset + 512] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 640]; t = (x[offset + 640] ^ x[offset + 896]) & (c >> 31); x[offset + 640] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 640]; t = (x[offset + 640] ^ x[offset + 768]) & (c >> 31); x[offset + 640] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 576]; t = (x[offset + 576] ^ x[offset + 832]) & (c >> 31); x[offset + 576] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 960]) & (c >> 31); x[offset + 704] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 832]) & (c >> 31); x[offset + 704] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 576]; t = (x[offset + 576] ^ x[offset + 640]) & (c >> 31); x[offset + 576] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 768]) & (c >> 31); x[offset + 704] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 832]; t = (x[offset + 832] ^ x[offset + 896]) & (c >> 31); x[offset + 832] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 800]) & (c >> 31); x[offset + 544] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 928]) & (c >> 31); x[offset + 672] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 800]) & (c >> 31); x[offset + 672] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 864]) & (c >> 31); x[offset + 608] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 992]) & (c >> 31); x[offset + 736] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 864]) & (c >> 31); x[offset + 736] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 672]) & (c >> 31); x[offset + 608] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 800]) & (c >> 31); x[offset + 736] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 928]) & (c >> 31); x[offset + 864] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 576]) & (c >> 31); x[offset + 544] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 640]) & (c >> 31); x[offset + 608] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 704]) & (c >> 31); x[offset + 672] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 768]) & (c >> 31); x[offset + 736] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 832]) & (c >> 31); x[offset + 800] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 896]) & (c >> 31); x[offset + 864] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 928]; t = (x[offset + 928] ^ x[offset + 960]) & (c >> 31); x[offset + 928] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 784]) & (c >> 31); x[offset + 528] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 912]) & (c >> 31); x[offset + 656] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 784]) & (c >> 31); x[offset + 656] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 848]) & (c >> 31); x[offset + 592] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 976]) & (c >> 31); x[offset + 720] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 848]) & (c >> 31); x[offset + 720] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 656]) & (c >> 31); x[offset + 592] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 784]) & (c >> 31); x[offset + 720] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 912]) & (c >> 31); x[offset + 848] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 816]) & (c >> 31); x[offset + 560] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 944]) & (c >> 31); x[offset + 688] ^= t; x[offset + 944] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 816]) & (c >> 31); x[offset + 688] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 880]) & (c >> 31); x[offset + 624] ^= t; x[offset + 880] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 1008]) & (c >> 31); x[offset + 752] ^= t; x[offset + 1008] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 880]) & (c >> 31); x[offset + 752] ^= t; x[offset + 880] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 688]) & (c >> 31); x[offset + 624] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 816]) & (c >> 31); x[offset + 752] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 944]) & (c >> 31); x[offset + 880] ^= t; x[offset + 944] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 592]) & (c >> 31); x[offset + 560] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 656]) & (c >> 31); x[offset + 624] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 720]) & (c >> 31); x[offset + 688] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 784]) & (c >> 31); x[offset + 752] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 848]) & (c >> 31); x[offset + 816] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 912]) & (c >> 31); x[offset + 880] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 976]) & (c >> 31); x[offset + 944] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 544]) & (c >> 31); x[offset + 528] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 576]) & (c >> 31); x[offset + 560] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 608]) & (c >> 31); x[offset + 592] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 640]) & (c >> 31); x[offset + 624] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 672]) & (c >> 31); x[offset + 656] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 704]) & (c >> 31); x[offset + 688] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 736]) & (c >> 31); x[offset + 720] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 768]) & (c >> 31); x[offset + 752] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 800]) & (c >> 31); x[offset + 784] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 832]) & (c >> 31); x[offset + 816] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 864]) & (c >> 31); x[offset + 848] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 896]) & (c >> 31); x[offset + 880] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 928]) & (c >> 31); x[offset + 912] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 960]) & (c >> 31); x[offset + 944] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 992]) & (c >> 31); x[offset + 976] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 0]; t = (x[offset + 0] ^ x[offset + 512]) & (c >> 31); x[offset + 0] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 256]; t = (x[offset + 256] ^ x[offset + 768]) & (c >> 31); x[offset + 256] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 256]; t = (x[offset + 256] ^ x[offset + 512]) & (c >> 31); x[offset + 256] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 128]; t = (x[offset + 128] ^ x[offset + 640]) & (c >> 31); x[offset + 128] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 384]; t = (x[offset + 384] ^ x[offset + 896]) & (c >> 31); x[offset + 384] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 384]; t = (x[offset + 384] ^ x[offset + 640]) & (c >> 31); x[offset + 384] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 128]; t = (x[offset + 128] ^ x[offset + 256]) & (c >> 31); x[offset + 128] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 384]; t = (x[offset + 384] ^ x[offset + 512]) & (c >> 31); x[offset + 384] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 640]; t = (x[offset + 640] ^ x[offset + 768]) & (c >> 31); x[offset + 640] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 576]) & (c >> 31); x[offset + 64] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 832]) & (c >> 31); x[offset + 320] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 576]) & (c >> 31); x[offset + 320] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 704]) & (c >> 31); x[offset + 192] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 448]; t = (x[offset + 448] ^ x[offset + 960]) & (c >> 31); x[offset + 448] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 448]; t = (x[offset + 448] ^ x[offset + 704]) & (c >> 31); x[offset + 448] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 320]) & (c >> 31); x[offset + 192] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 448]; t = (x[offset + 448] ^ x[offset + 576]) & (c >> 31); x[offset + 448] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 832]) & (c >> 31); x[offset + 704] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 128]) & (c >> 31); x[offset + 64] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 256]) & (c >> 31); x[offset + 192] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 384]) & (c >> 31); x[offset + 320] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 448]; t = (x[offset + 448] ^ x[offset + 512]) & (c >> 31); x[offset + 448] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 576]; t = (x[offset + 576] ^ x[offset + 640]) & (c >> 31); x[offset + 576] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 768]) & (c >> 31); x[offset + 704] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 832]; t = (x[offset + 832] ^ x[offset + 896]) & (c >> 31); x[offset + 832] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 544]) & (c >> 31); x[offset + 32] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 800]) & (c >> 31); x[offset + 288] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 544]) & (c >> 31); x[offset + 288] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 672]) & (c >> 31); x[offset + 160] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 928]) & (c >> 31); x[offset + 416] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 672]) & (c >> 31); x[offset + 416] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 288]) & (c >> 31); x[offset + 160] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 544]) & (c >> 31); x[offset + 416] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 800]) & (c >> 31); x[offset + 672] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 608]) & (c >> 31); x[offset + 96] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 864]) & (c >> 31); x[offset + 352] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 608]) & (c >> 31); x[offset + 352] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 736]) & (c >> 31); x[offset + 224] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 992]) & (c >> 31); x[offset + 480] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 736]) & (c >> 31); x[offset + 480] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 352]) & (c >> 31); x[offset + 224] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 608]) & (c >> 31); x[offset + 480] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 864]) & (c >> 31); x[offset + 736] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 160]) & (c >> 31); x[offset + 96] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 288]) & (c >> 31); x[offset + 224] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 416]) & (c >> 31); x[offset + 352] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 544]) & (c >> 31); x[offset + 480] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 672]) & (c >> 31); x[offset + 608] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 800]) & (c >> 31); x[offset + 736] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 928]) & (c >> 31); x[offset + 864] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 64]) & (c >> 31); x[offset + 32] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 128]) & (c >> 31); x[offset + 96] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 192]) & (c >> 31); x[offset + 160] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 256]) & (c >> 31); x[offset + 224] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 320]) & (c >> 31); x[offset + 288] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 384]) & (c >> 31); x[offset + 352] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 448]) & (c >> 31); x[offset + 416] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 512]) & (c >> 31); x[offset + 480] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 576]) & (c >> 31); x[offset + 544] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 640]) & (c >> 31); x[offset + 608] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 704]) & (c >> 31); x[offset + 672] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 768]) & (c >> 31); x[offset + 736] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 832]) & (c >> 31); x[offset + 800] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 896]) & (c >> 31); x[offset + 864] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 928]; t = (x[offset + 928] ^ x[offset + 960]) & (c >> 31); x[offset + 928] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 528]) & (c >> 31); x[offset + 16] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 784]) & (c >> 31); x[offset + 272] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 528]) & (c >> 31); x[offset + 272] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 656]) & (c >> 31); x[offset + 144] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 912]) & (c >> 31); x[offset + 400] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 656]) & (c >> 31); x[offset + 400] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 272]) & (c >> 31); x[offset + 144] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 528]) & (c >> 31); x[offset + 400] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 784]) & (c >> 31); x[offset + 656] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 592]) & (c >> 31); x[offset + 80] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 848]) & (c >> 31); x[offset + 336] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 592]) & (c >> 31); x[offset + 336] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 720]) & (c >> 31); x[offset + 208] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 976]) & (c >> 31); x[offset + 464] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 720]) & (c >> 31); x[offset + 464] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 336]) & (c >> 31); x[offset + 208] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 592]) & (c >> 31); x[offset + 464] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 848]) & (c >> 31); x[offset + 720] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 144]) & (c >> 31); x[offset + 80] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 272]) & (c >> 31); x[offset + 208] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 400]) & (c >> 31); x[offset + 336] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 528]) & (c >> 31); x[offset + 464] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 656]) & (c >> 31); x[offset + 592] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 784]) & (c >> 31); x[offset + 720] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 912]) & (c >> 31); x[offset + 848] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 560]) & (c >> 31); x[offset + 48] ^= t; x[offset + 560] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 816]) & (c >> 31); x[offset + 304] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 560]) & (c >> 31); x[offset + 304] ^= t; x[offset + 560] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 688]) & (c >> 31); x[offset + 176] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 944]) & (c >> 31); x[offset + 432] ^= t; x[offset + 944] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 688]) & (c >> 31); x[offset + 432] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 304]) & (c >> 31); x[offset + 176] ^= t; x[offset + 304] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 560]) & (c >> 31); x[offset + 432] ^= t; x[offset + 560] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 816]) & (c >> 31); x[offset + 688] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 624]) & (c >> 31); x[offset + 112] ^= t; x[offset + 624] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 880]) & (c >> 31); x[offset + 368] ^= t; x[offset + 880] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 624]) & (c >> 31); x[offset + 368] ^= t; x[offset + 624] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 752]) & (c >> 31); x[offset + 240] ^= t; x[offset + 752] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 1008]) & (c >> 31); x[offset + 496] ^= t; x[offset + 1008] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 752]) & (c >> 31); x[offset + 496] ^= t; x[offset + 752] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 368]) & (c >> 31); x[offset + 240] ^= t; x[offset + 368] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 624]) & (c >> 31); x[offset + 496] ^= t; x[offset + 624] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 880]) & (c >> 31); x[offset + 752] ^= t; x[offset + 880] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 176]) & (c >> 31); x[offset + 112] ^= t; x[offset + 176] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 304]) & (c >> 31); x[offset + 240] ^= t; x[offset + 304] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 432]) & (c >> 31); x[offset + 368] ^= t; x[offset + 432] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 560]) & (c >> 31); x[offset + 496] ^= t; x[offset + 560] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 688]) & (c >> 31); x[offset + 624] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 816]) & (c >> 31); x[offset + 752] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 944]) & (c >> 31); x[offset + 880] ^= t; x[offset + 944] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 80]) & (c >> 31); x[offset + 48] ^= t; x[offset + 80] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 144]) & (c >> 31); x[offset + 112] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 208]) & (c >> 31); x[offset + 176] ^= t; x[offset + 208] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 272]) & (c >> 31); x[offset + 240] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 336]) & (c >> 31); x[offset + 304] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 400]) & (c >> 31); x[offset + 368] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 464]) & (c >> 31); x[offset + 432] ^= t; x[offset + 464] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 528]) & (c >> 31); x[offset + 496] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 592]) & (c >> 31); x[offset + 560] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 656]) & (c >> 31); x[offset + 624] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 720]) & (c >> 31); x[offset + 688] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 784]) & (c >> 31); x[offset + 752] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 848]) & (c >> 31); x[offset + 816] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 912]) & (c >> 31); x[offset + 880] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 976]) & (c >> 31); x[offset + 944] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 32]) & (c >> 31); x[offset + 16] ^= t; x[offset + 32] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 64]) & (c >> 31); x[offset + 48] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 96]) & (c >> 31); x[offset + 80] ^= t; x[offset + 96] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 128]) & (c >> 31); x[offset + 112] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 160]) & (c >> 31); x[offset + 144] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 192]) & (c >> 31); x[offset + 176] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 224]) & (c >> 31); x[offset + 208] ^= t; x[offset + 224] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 256]) & (c >> 31); x[offset + 240] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 288]) & (c >> 31); x[offset + 272] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 320]) & (c >> 31); x[offset + 304] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 352]) & (c >> 31); x[offset + 336] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 384]) & (c >> 31); x[offset + 368] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 416]) & (c >> 31); x[offset + 400] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 448]) & (c >> 31); x[offset + 432] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 480]) & (c >> 31); x[offset + 464] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 512]) & (c >> 31); x[offset + 496] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 544]) & (c >> 31); x[offset + 528] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 576]) & (c >> 31); x[offset + 560] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 608]) & (c >> 31); x[offset + 592] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 640]) & (c >> 31); x[offset + 624] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 672]) & (c >> 31); x[offset + 656] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 704]) & (c >> 31); x[offset + 688] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 736]) & (c >> 31); x[offset + 720] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 768]) & (c >> 31); x[offset + 752] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 800]) & (c >> 31); x[offset + 784] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 832]) & (c >> 31); x[offset + 816] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 864]) & (c >> 31); x[offset + 848] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 896]) & (c >> 31); x[offset + 880] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 928]) & (c >> 31); x[offset + 912] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 960]) & (c >> 31); x[offset + 944] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 992]) & (c >> 31); x[offset + 976] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 1024]; t = (x[offset + 1024] ^ x[offset + 1040]) & (c >> 31); x[offset + 1024] ^= t; x[offset + 1040] ^= t; - c = 61444 - x[offset + 1056]; t = (x[offset + 1056] ^ x[offset + 1072]) & (c >> 31); x[offset + 1056] ^= t; x[offset + 1072] ^= t; - c = 61444 - x[offset + 1024]; t = (x[offset + 1024] ^ x[offset + 1056]) & (c >> 31); x[offset + 1024] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1072]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1072] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1056]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 1088]; t = (x[offset + 1088] ^ x[offset + 1104]) & (c >> 31); x[offset + 1088] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1136]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1136] ^= t; - c = 61444 - x[offset + 1088]; t = (x[offset + 1088] ^ x[offset + 1120]) & (c >> 31); x[offset + 1088] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1136]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1136] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1120]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 1024]; t = (x[offset + 1024] ^ x[offset + 1088]) & (c >> 31); x[offset + 1024] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1056]; t = (x[offset + 1056] ^ x[offset + 1120]) & (c >> 31); x[offset + 1056] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 1056]; t = (x[offset + 1056] ^ x[offset + 1088]) & (c >> 31); x[offset + 1056] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1104]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1136]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1136] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1104]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1056]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1088]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1120]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 1152]; t = (x[offset + 1152] ^ x[offset + 1168]) & (c >> 31); x[offset + 1152] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1200]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 1152]; t = (x[offset + 1152] ^ x[offset + 1184]) & (c >> 31); x[offset + 1152] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1200]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1184]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1216]; t = (x[offset + 1216] ^ x[offset + 1232]) & (c >> 31); x[offset + 1216] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 1248]; t = (x[offset + 1248] ^ x[offset + 1264]) & (c >> 31); x[offset + 1248] ^= t; x[offset + 1264] ^= t; - c = 61444 - x[offset + 1216]; t = (x[offset + 1216] ^ x[offset + 1248]) & (c >> 31); x[offset + 1216] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1264]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1264] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1248]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 1152]; t = (x[offset + 1152] ^ x[offset + 1216]) & (c >> 31); x[offset + 1152] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1248]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1216]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1232]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1264]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1264] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1232]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1184]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1216]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1248]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 1024]; t = (x[offset + 1024] ^ x[offset + 1152]) & (c >> 31); x[offset + 1024] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1088]; t = (x[offset + 1088] ^ x[offset + 1216]) & (c >> 31); x[offset + 1088] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1088]; t = (x[offset + 1088] ^ x[offset + 1152]) & (c >> 31); x[offset + 1088] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1056]; t = (x[offset + 1056] ^ x[offset + 1184]) & (c >> 31); x[offset + 1056] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1248]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1184]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1056]; t = (x[offset + 1056] ^ x[offset + 1088]) & (c >> 31); x[offset + 1056] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1152]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1216]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1168]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1232]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1168]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1200]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1264]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1264] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1200]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1104]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1168]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1232]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1056]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1088]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1120]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1152]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1184]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1216]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1248]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 1280]; t = (x[offset + 1280] ^ x[offset + 1296]) & (c >> 31); x[offset + 1280] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 1312]; t = (x[offset + 1312] ^ x[offset + 1328]) & (c >> 31); x[offset + 1312] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 1280]; t = (x[offset + 1280] ^ x[offset + 1312]) & (c >> 31); x[offset + 1280] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1296]; t = (x[offset + 1296] ^ x[offset + 1328]) & (c >> 31); x[offset + 1296] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 1296]; t = (x[offset + 1296] ^ x[offset + 1312]) & (c >> 31); x[offset + 1296] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1296]; t = (x[offset + 1296] ^ x[offset + 1312]) & (c >> 31); x[offset + 1296] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1296]; t = (x[offset + 1296] ^ x[offset + 1312]) & (c >> 31); x[offset + 1296] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1024]; t = (x[offset + 1024] ^ x[offset + 1280]) & (c >> 31); x[offset + 1024] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1152]; t = (x[offset + 1152] ^ x[offset + 1280]) & (c >> 31); x[offset + 1152] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1088]; t = (x[offset + 1088] ^ x[offset + 1152]) & (c >> 31); x[offset + 1088] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1216]; t = (x[offset + 1216] ^ x[offset + 1280]) & (c >> 31); x[offset + 1216] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1056]; t = (x[offset + 1056] ^ x[offset + 1312]) & (c >> 31); x[offset + 1056] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1312]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1184]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1248]; t = (x[offset + 1248] ^ x[offset + 1312]) & (c >> 31); x[offset + 1248] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1056]; t = (x[offset + 1056] ^ x[offset + 1088]) & (c >> 31); x[offset + 1056] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1152]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1216]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1248]; t = (x[offset + 1248] ^ x[offset + 1280]) & (c >> 31); x[offset + 1248] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1296]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1296]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1168]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1296]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1328]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1328]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1200]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 1264]; t = (x[offset + 1264] ^ x[offset + 1328]) & (c >> 31); x[offset + 1264] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1104]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1168]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1232]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 1264]; t = (x[offset + 1264] ^ x[offset + 1296]) & (c >> 31); x[offset + 1264] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1056]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1088]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1120]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1152]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1184]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1216]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1248]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 1264]; t = (x[offset + 1264] ^ x[offset + 1280]) & (c >> 31); x[offset + 1264] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1296]; t = (x[offset + 1296] ^ x[offset + 1312]) & (c >> 31); x[offset + 1296] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1152]; t = (x[offset + 1152] ^ x[offset + 1280]) & (c >> 31); x[offset + 1152] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1088]; t = (x[offset + 1088] ^ x[offset + 1152]) & (c >> 31); x[offset + 1088] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1216]; t = (x[offset + 1216] ^ x[offset + 1280]) & (c >> 31); x[offset + 1216] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1312]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1184]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1248]; t = (x[offset + 1248] ^ x[offset + 1312]) & (c >> 31); x[offset + 1248] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 1056]; t = (x[offset + 1056] ^ x[offset + 1088]) & (c >> 31); x[offset + 1056] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1152]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1216]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1248]; t = (x[offset + 1248] ^ x[offset + 1280]) & (c >> 31); x[offset + 1248] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1296]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1168]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1296]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1328]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1200]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 1264]; t = (x[offset + 1264] ^ x[offset + 1328]) & (c >> 31); x[offset + 1264] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1104]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1168]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1232]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 1264]; t = (x[offset + 1264] ^ x[offset + 1296]) & (c >> 31); x[offset + 1264] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1056]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1088]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1120]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1152]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1184]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1216]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1248]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 1264]; t = (x[offset + 1264] ^ x[offset + 1280]) & (c >> 31); x[offset + 1264] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1296]; t = (x[offset + 1296] ^ x[offset + 1312]) & (c >> 31); x[offset + 1296] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 0]; t = (x[offset + 0] ^ x[offset + 1024]) & (c >> 31); x[offset + 0] ^= t; x[offset + 1024] ^= t; - c = 61444 - x[offset + 512]; t = (x[offset + 512] ^ x[offset + 1024]) & (c >> 31); x[offset + 512] ^= t; x[offset + 1024] ^= t; - c = 61444 - x[offset + 256]; t = (x[offset + 256] ^ x[offset + 1280]) & (c >> 31); x[offset + 256] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 768]; t = (x[offset + 768] ^ x[offset + 1280]) & (c >> 31); x[offset + 768] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 256]; t = (x[offset + 256] ^ x[offset + 512]) & (c >> 31); x[offset + 256] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 768]; t = (x[offset + 768] ^ x[offset + 1024]) & (c >> 31); x[offset + 768] ^= t; x[offset + 1024] ^= t; - c = 61444 - x[offset + 128]; t = (x[offset + 128] ^ x[offset + 1152]) & (c >> 31); x[offset + 128] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 640]; t = (x[offset + 640] ^ x[offset + 1152]) & (c >> 31); x[offset + 640] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 384]; t = (x[offset + 384] ^ x[offset + 640]) & (c >> 31); x[offset + 384] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 896]; t = (x[offset + 896] ^ x[offset + 1152]) & (c >> 31); x[offset + 896] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 128]; t = (x[offset + 128] ^ x[offset + 256]) & (c >> 31); x[offset + 128] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 384]; t = (x[offset + 384] ^ x[offset + 512]) & (c >> 31); x[offset + 384] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 640]; t = (x[offset + 640] ^ x[offset + 768]) & (c >> 31); x[offset + 640] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 896]; t = (x[offset + 896] ^ x[offset + 1024]) & (c >> 31); x[offset + 896] ^= t; x[offset + 1024] ^= t; - c = 61444 - x[offset + 1152]; t = (x[offset + 1152] ^ x[offset + 1280]) & (c >> 31); x[offset + 1152] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 1088]) & (c >> 31); x[offset + 64] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 576]; t = (x[offset + 576] ^ x[offset + 1088]) & (c >> 31); x[offset + 576] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 576]) & (c >> 31); x[offset + 320] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 832]; t = (x[offset + 832] ^ x[offset + 1088]) & (c >> 31); x[offset + 832] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 1216]) & (c >> 31); x[offset + 192] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 1216]) & (c >> 31); x[offset + 704] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 448]; t = (x[offset + 448] ^ x[offset + 704]) & (c >> 31); x[offset + 448] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 960]; t = (x[offset + 960] ^ x[offset + 1216]) & (c >> 31); x[offset + 960] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 320]) & (c >> 31); x[offset + 192] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 448]; t = (x[offset + 448] ^ x[offset + 576]) & (c >> 31); x[offset + 448] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 832]) & (c >> 31); x[offset + 704] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 960]; t = (x[offset + 960] ^ x[offset + 1088]) & (c >> 31); x[offset + 960] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 64]; t = (x[offset + 64] ^ x[offset + 128]) & (c >> 31); x[offset + 64] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 192]; t = (x[offset + 192] ^ x[offset + 256]) & (c >> 31); x[offset + 192] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 320]; t = (x[offset + 320] ^ x[offset + 384]) & (c >> 31); x[offset + 320] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 448]; t = (x[offset + 448] ^ x[offset + 512]) & (c >> 31); x[offset + 448] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 576]; t = (x[offset + 576] ^ x[offset + 640]) & (c >> 31); x[offset + 576] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 704]; t = (x[offset + 704] ^ x[offset + 768]) & (c >> 31); x[offset + 704] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 832]; t = (x[offset + 832] ^ x[offset + 896]) & (c >> 31); x[offset + 832] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 960]; t = (x[offset + 960] ^ x[offset + 1024]) & (c >> 31); x[offset + 960] ^= t; x[offset + 1024] ^= t; - c = 61444 - x[offset + 1088]; t = (x[offset + 1088] ^ x[offset + 1152]) & (c >> 31); x[offset + 1088] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1216]; t = (x[offset + 1216] ^ x[offset + 1280]) & (c >> 31); x[offset + 1216] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 1056]) & (c >> 31); x[offset + 32] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 1056]) & (c >> 31); x[offset + 544] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 1312]) & (c >> 31); x[offset + 288] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 1312]) & (c >> 31); x[offset + 800] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 544]) & (c >> 31); x[offset + 288] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 1056]) & (c >> 31); x[offset + 800] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 1184]) & (c >> 31); x[offset + 160] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 1184]) & (c >> 31); x[offset + 672] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 672]) & (c >> 31); x[offset + 416] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 928]; t = (x[offset + 928] ^ x[offset + 1184]) & (c >> 31); x[offset + 928] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 288]) & (c >> 31); x[offset + 160] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 544]) & (c >> 31); x[offset + 416] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 800]) & (c >> 31); x[offset + 672] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 928]; t = (x[offset + 928] ^ x[offset + 1056]) & (c >> 31); x[offset + 928] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1312]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 1120]) & (c >> 31); x[offset + 96] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 1120]) & (c >> 31); x[offset + 608] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 608]) & (c >> 31); x[offset + 352] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 1120]) & (c >> 31); x[offset + 864] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 1248]) & (c >> 31); x[offset + 224] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 1248]) & (c >> 31); x[offset + 736] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 736]) & (c >> 31); x[offset + 480] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 992]; t = (x[offset + 992] ^ x[offset + 1248]) & (c >> 31); x[offset + 992] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 352]) & (c >> 31); x[offset + 224] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 608]) & (c >> 31); x[offset + 480] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 864]) & (c >> 31); x[offset + 736] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 992]; t = (x[offset + 992] ^ x[offset + 1120]) & (c >> 31); x[offset + 992] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 160]) & (c >> 31); x[offset + 96] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 288]) & (c >> 31); x[offset + 224] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 416]) & (c >> 31); x[offset + 352] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 544]) & (c >> 31); x[offset + 480] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 672]) & (c >> 31); x[offset + 608] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 800]) & (c >> 31); x[offset + 736] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 928]) & (c >> 31); x[offset + 864] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 992]; t = (x[offset + 992] ^ x[offset + 1056]) & (c >> 31); x[offset + 992] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1184]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1248]; t = (x[offset + 1248] ^ x[offset + 1312]) & (c >> 31); x[offset + 1248] ^= t; x[offset + 1312] ^= t; - c = 61444 - x[offset + 32]; t = (x[offset + 32] ^ x[offset + 64]) & (c >> 31); x[offset + 32] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 96]; t = (x[offset + 96] ^ x[offset + 128]) & (c >> 31); x[offset + 96] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 160]; t = (x[offset + 160] ^ x[offset + 192]) & (c >> 31); x[offset + 160] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 224]; t = (x[offset + 224] ^ x[offset + 256]) & (c >> 31); x[offset + 224] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 288]; t = (x[offset + 288] ^ x[offset + 320]) & (c >> 31); x[offset + 288] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 352]; t = (x[offset + 352] ^ x[offset + 384]) & (c >> 31); x[offset + 352] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 416]; t = (x[offset + 416] ^ x[offset + 448]) & (c >> 31); x[offset + 416] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 480]; t = (x[offset + 480] ^ x[offset + 512]) & (c >> 31); x[offset + 480] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 544]; t = (x[offset + 544] ^ x[offset + 576]) & (c >> 31); x[offset + 544] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 608]; t = (x[offset + 608] ^ x[offset + 640]) & (c >> 31); x[offset + 608] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 672]; t = (x[offset + 672] ^ x[offset + 704]) & (c >> 31); x[offset + 672] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 736]; t = (x[offset + 736] ^ x[offset + 768]) & (c >> 31); x[offset + 736] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 800]; t = (x[offset + 800] ^ x[offset + 832]) & (c >> 31); x[offset + 800] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 864]; t = (x[offset + 864] ^ x[offset + 896]) & (c >> 31); x[offset + 864] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 928]; t = (x[offset + 928] ^ x[offset + 960]) & (c >> 31); x[offset + 928] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 992]; t = (x[offset + 992] ^ x[offset + 1024]) & (c >> 31); x[offset + 992] ^= t; x[offset + 1024] ^= t; - c = 61444 - x[offset + 1056]; t = (x[offset + 1056] ^ x[offset + 1088]) & (c >> 31); x[offset + 1056] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1120]; t = (x[offset + 1120] ^ x[offset + 1152]) & (c >> 31); x[offset + 1120] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1184]; t = (x[offset + 1184] ^ x[offset + 1216]) & (c >> 31); x[offset + 1184] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1248]; t = (x[offset + 1248] ^ x[offset + 1280]) & (c >> 31); x[offset + 1248] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 1040]) & (c >> 31); x[offset + 16] ^= t; x[offset + 1040] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 1040]) & (c >> 31); x[offset + 528] ^= t; x[offset + 1040] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 1296]) & (c >> 31); x[offset + 272] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 1296]) & (c >> 31); x[offset + 784] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 528]) & (c >> 31); x[offset + 272] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 1040]) & (c >> 31); x[offset + 784] ^= t; x[offset + 1040] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 1168]) & (c >> 31); x[offset + 144] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 1168]) & (c >> 31); x[offset + 656] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 656]) & (c >> 31); x[offset + 400] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 1168]) & (c >> 31); x[offset + 912] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 272]) & (c >> 31); x[offset + 144] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 528]) & (c >> 31); x[offset + 400] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 784]) & (c >> 31); x[offset + 656] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 1040]) & (c >> 31); x[offset + 912] ^= t; x[offset + 1040] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1296]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 1104]) & (c >> 31); x[offset + 80] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 1104]) & (c >> 31); x[offset + 592] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 592]) & (c >> 31); x[offset + 336] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 1104]) & (c >> 31); x[offset + 848] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 1232]) & (c >> 31); x[offset + 208] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 1232]) & (c >> 31); x[offset + 720] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 720]) & (c >> 31); x[offset + 464] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 1232]) & (c >> 31); x[offset + 976] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 336]) & (c >> 31); x[offset + 208] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 592]) & (c >> 31); x[offset + 464] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 848]) & (c >> 31); x[offset + 720] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 1104]) & (c >> 31); x[offset + 976] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 144]) & (c >> 31); x[offset + 80] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 272]) & (c >> 31); x[offset + 208] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 400]) & (c >> 31); x[offset + 336] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 528]) & (c >> 31); x[offset + 464] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 656]) & (c >> 31); x[offset + 592] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 784]) & (c >> 31); x[offset + 720] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 912]) & (c >> 31); x[offset + 848] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 1040]) & (c >> 31); x[offset + 976] ^= t; x[offset + 1040] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1168]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1296]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 1072]) & (c >> 31); x[offset + 48] ^= t; x[offset + 1072] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 1072]) & (c >> 31); x[offset + 560] ^= t; x[offset + 1072] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 1328]) & (c >> 31); x[offset + 304] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 1328]) & (c >> 31); x[offset + 816] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 560]) & (c >> 31); x[offset + 304] ^= t; x[offset + 560] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 1072]) & (c >> 31); x[offset + 816] ^= t; x[offset + 1072] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 1200]) & (c >> 31); x[offset + 176] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 1200]) & (c >> 31); x[offset + 688] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 688]) & (c >> 31); x[offset + 432] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 1200]) & (c >> 31); x[offset + 944] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 304]) & (c >> 31); x[offset + 176] ^= t; x[offset + 304] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 560]) & (c >> 31); x[offset + 432] ^= t; x[offset + 560] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 816]) & (c >> 31); x[offset + 688] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 1072]) & (c >> 31); x[offset + 944] ^= t; x[offset + 1072] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1328]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 1136]) & (c >> 31); x[offset + 112] ^= t; x[offset + 1136] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 1136]) & (c >> 31); x[offset + 624] ^= t; x[offset + 1136] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 624]) & (c >> 31); x[offset + 368] ^= t; x[offset + 624] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 1136]) & (c >> 31); x[offset + 880] ^= t; x[offset + 1136] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 1264]) & (c >> 31); x[offset + 240] ^= t; x[offset + 1264] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 1264]) & (c >> 31); x[offset + 752] ^= t; x[offset + 1264] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 752]) & (c >> 31); x[offset + 496] ^= t; x[offset + 752] ^= t; - c = 61444 - x[offset + 1008]; t = (x[offset + 1008] ^ x[offset + 1264]) & (c >> 31); x[offset + 1008] ^= t; x[offset + 1264] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 368]) & (c >> 31); x[offset + 240] ^= t; x[offset + 368] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 624]) & (c >> 31); x[offset + 496] ^= t; x[offset + 624] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 880]) & (c >> 31); x[offset + 752] ^= t; x[offset + 880] ^= t; - c = 61444 - x[offset + 1008]; t = (x[offset + 1008] ^ x[offset + 1136]) & (c >> 31); x[offset + 1008] ^= t; x[offset + 1136] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 176]) & (c >> 31); x[offset + 112] ^= t; x[offset + 176] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 304]) & (c >> 31); x[offset + 240] ^= t; x[offset + 304] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 432]) & (c >> 31); x[offset + 368] ^= t; x[offset + 432] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 560]) & (c >> 31); x[offset + 496] ^= t; x[offset + 560] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 688]) & (c >> 31); x[offset + 624] ^= t; x[offset + 688] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 816]) & (c >> 31); x[offset + 752] ^= t; x[offset + 816] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 944]) & (c >> 31); x[offset + 880] ^= t; x[offset + 944] ^= t; - c = 61444 - x[offset + 1008]; t = (x[offset + 1008] ^ x[offset + 1072]) & (c >> 31); x[offset + 1008] ^= t; x[offset + 1072] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1200]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1200] ^= t; - c = 61444 - x[offset + 1264]; t = (x[offset + 1264] ^ x[offset + 1328]) & (c >> 31); x[offset + 1264] ^= t; x[offset + 1328] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 80]) & (c >> 31); x[offset + 48] ^= t; x[offset + 80] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 144]) & (c >> 31); x[offset + 112] ^= t; x[offset + 144] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 208]) & (c >> 31); x[offset + 176] ^= t; x[offset + 208] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 272]) & (c >> 31); x[offset + 240] ^= t; x[offset + 272] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 336]) & (c >> 31); x[offset + 304] ^= t; x[offset + 336] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 400]) & (c >> 31); x[offset + 368] ^= t; x[offset + 400] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 464]) & (c >> 31); x[offset + 432] ^= t; x[offset + 464] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 528]) & (c >> 31); x[offset + 496] ^= t; x[offset + 528] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 592]) & (c >> 31); x[offset + 560] ^= t; x[offset + 592] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 656]) & (c >> 31); x[offset + 624] ^= t; x[offset + 656] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 720]) & (c >> 31); x[offset + 688] ^= t; x[offset + 720] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 784]) & (c >> 31); x[offset + 752] ^= t; x[offset + 784] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 848]) & (c >> 31); x[offset + 816] ^= t; x[offset + 848] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 912]) & (c >> 31); x[offset + 880] ^= t; x[offset + 912] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 976]) & (c >> 31); x[offset + 944] ^= t; x[offset + 976] ^= t; - c = 61444 - x[offset + 1008]; t = (x[offset + 1008] ^ x[offset + 1040]) & (c >> 31); x[offset + 1008] ^= t; x[offset + 1040] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1104]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1104] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1168]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1168] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1232]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1232] ^= t; - c = 61444 - x[offset + 1264]; t = (x[offset + 1264] ^ x[offset + 1296]) & (c >> 31); x[offset + 1264] ^= t; x[offset + 1296] ^= t; - c = 61444 - x[offset + 16]; t = (x[offset + 16] ^ x[offset + 32]) & (c >> 31); x[offset + 16] ^= t; x[offset + 32] ^= t; - c = 61444 - x[offset + 48]; t = (x[offset + 48] ^ x[offset + 64]) & (c >> 31); x[offset + 48] ^= t; x[offset + 64] ^= t; - c = 61444 - x[offset + 80]; t = (x[offset + 80] ^ x[offset + 96]) & (c >> 31); x[offset + 80] ^= t; x[offset + 96] ^= t; - c = 61444 - x[offset + 112]; t = (x[offset + 112] ^ x[offset + 128]) & (c >> 31); x[offset + 112] ^= t; x[offset + 128] ^= t; - c = 61444 - x[offset + 144]; t = (x[offset + 144] ^ x[offset + 160]) & (c >> 31); x[offset + 144] ^= t; x[offset + 160] ^= t; - c = 61444 - x[offset + 176]; t = (x[offset + 176] ^ x[offset + 192]) & (c >> 31); x[offset + 176] ^= t; x[offset + 192] ^= t; - c = 61444 - x[offset + 208]; t = (x[offset + 208] ^ x[offset + 224]) & (c >> 31); x[offset + 208] ^= t; x[offset + 224] ^= t; - c = 61444 - x[offset + 240]; t = (x[offset + 240] ^ x[offset + 256]) & (c >> 31); x[offset + 240] ^= t; x[offset + 256] ^= t; - c = 61444 - x[offset + 272]; t = (x[offset + 272] ^ x[offset + 288]) & (c >> 31); x[offset + 272] ^= t; x[offset + 288] ^= t; - c = 61444 - x[offset + 304]; t = (x[offset + 304] ^ x[offset + 320]) & (c >> 31); x[offset + 304] ^= t; x[offset + 320] ^= t; - c = 61444 - x[offset + 336]; t = (x[offset + 336] ^ x[offset + 352]) & (c >> 31); x[offset + 336] ^= t; x[offset + 352] ^= t; - c = 61444 - x[offset + 368]; t = (x[offset + 368] ^ x[offset + 384]) & (c >> 31); x[offset + 368] ^= t; x[offset + 384] ^= t; - c = 61444 - x[offset + 400]; t = (x[offset + 400] ^ x[offset + 416]) & (c >> 31); x[offset + 400] ^= t; x[offset + 416] ^= t; - c = 61444 - x[offset + 432]; t = (x[offset + 432] ^ x[offset + 448]) & (c >> 31); x[offset + 432] ^= t; x[offset + 448] ^= t; - c = 61444 - x[offset + 464]; t = (x[offset + 464] ^ x[offset + 480]) & (c >> 31); x[offset + 464] ^= t; x[offset + 480] ^= t; - c = 61444 - x[offset + 496]; t = (x[offset + 496] ^ x[offset + 512]) & (c >> 31); x[offset + 496] ^= t; x[offset + 512] ^= t; - c = 61444 - x[offset + 528]; t = (x[offset + 528] ^ x[offset + 544]) & (c >> 31); x[offset + 528] ^= t; x[offset + 544] ^= t; - c = 61444 - x[offset + 560]; t = (x[offset + 560] ^ x[offset + 576]) & (c >> 31); x[offset + 560] ^= t; x[offset + 576] ^= t; - c = 61444 - x[offset + 592]; t = (x[offset + 592] ^ x[offset + 608]) & (c >> 31); x[offset + 592] ^= t; x[offset + 608] ^= t; - c = 61444 - x[offset + 624]; t = (x[offset + 624] ^ x[offset + 640]) & (c >> 31); x[offset + 624] ^= t; x[offset + 640] ^= t; - c = 61444 - x[offset + 656]; t = (x[offset + 656] ^ x[offset + 672]) & (c >> 31); x[offset + 656] ^= t; x[offset + 672] ^= t; - c = 61444 - x[offset + 688]; t = (x[offset + 688] ^ x[offset + 704]) & (c >> 31); x[offset + 688] ^= t; x[offset + 704] ^= t; - c = 61444 - x[offset + 720]; t = (x[offset + 720] ^ x[offset + 736]) & (c >> 31); x[offset + 720] ^= t; x[offset + 736] ^= t; - c = 61444 - x[offset + 752]; t = (x[offset + 752] ^ x[offset + 768]) & (c >> 31); x[offset + 752] ^= t; x[offset + 768] ^= t; - c = 61444 - x[offset + 784]; t = (x[offset + 784] ^ x[offset + 800]) & (c >> 31); x[offset + 784] ^= t; x[offset + 800] ^= t; - c = 61444 - x[offset + 816]; t = (x[offset + 816] ^ x[offset + 832]) & (c >> 31); x[offset + 816] ^= t; x[offset + 832] ^= t; - c = 61444 - x[offset + 848]; t = (x[offset + 848] ^ x[offset + 864]) & (c >> 31); x[offset + 848] ^= t; x[offset + 864] ^= t; - c = 61444 - x[offset + 880]; t = (x[offset + 880] ^ x[offset + 896]) & (c >> 31); x[offset + 880] ^= t; x[offset + 896] ^= t; - c = 61444 - x[offset + 912]; t = (x[offset + 912] ^ x[offset + 928]) & (c >> 31); x[offset + 912] ^= t; x[offset + 928] ^= t; - c = 61444 - x[offset + 944]; t = (x[offset + 944] ^ x[offset + 960]) & (c >> 31); x[offset + 944] ^= t; x[offset + 960] ^= t; - c = 61444 - x[offset + 976]; t = (x[offset + 976] ^ x[offset + 992]) & (c >> 31); x[offset + 976] ^= t; x[offset + 992] ^= t; - c = 61444 - x[offset + 1008]; t = (x[offset + 1008] ^ x[offset + 1024]) & (c >> 31); x[offset + 1008] ^= t; x[offset + 1024] ^= t; - c = 61444 - x[offset + 1040]; t = (x[offset + 1040] ^ x[offset + 1056]) & (c >> 31); x[offset + 1040] ^= t; x[offset + 1056] ^= t; - c = 61444 - x[offset + 1072]; t = (x[offset + 1072] ^ x[offset + 1088]) & (c >> 31); x[offset + 1072] ^= t; x[offset + 1088] ^= t; - c = 61444 - x[offset + 1104]; t = (x[offset + 1104] ^ x[offset + 1120]) & (c >> 31); x[offset + 1104] ^= t; x[offset + 1120] ^= t; - c = 61444 - x[offset + 1136]; t = (x[offset + 1136] ^ x[offset + 1152]) & (c >> 31); x[offset + 1136] ^= t; x[offset + 1152] ^= t; - c = 61444 - x[offset + 1168]; t = (x[offset + 1168] ^ x[offset + 1184]) & (c >> 31); x[offset + 1168] ^= t; x[offset + 1184] ^= t; - c = 61444 - x[offset + 1200]; t = (x[offset + 1200] ^ x[offset + 1216]) & (c >> 31); x[offset + 1200] ^= t; x[offset + 1216] ^= t; - c = 61444 - x[offset + 1232]; t = (x[offset + 1232] ^ x[offset + 1248]) & (c >> 31); x[offset + 1232] ^= t; x[offset + 1248] ^= t; - c = 61444 - x[offset + 1264]; t = (x[offset + 1264] ^ x[offset + 1280]) & (c >> 31); x[offset + 1264] ^= t; x[offset + 1280] ^= t; - c = 61444 - x[offset + 1296]; t = (x[offset + 1296] ^ x[offset + 1312]) & (c >> 31); x[offset + 1296] ^= t; x[offset + 1312] ^= t; - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/Poly1305.java b/src/main/java/com/southernstorm/noise/crypto/Poly1305.java deleted file mode 100644 index c3cc0a1ce..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/Poly1305.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.crypto; - -import com.southernstorm.noise.protocol.Destroyable; - -import java.util.Arrays; - -/** - * Simple implementation of the Poly1305 message authenticator. - */ -public final class Poly1305 implements Destroyable { - - // The 130-bit intermediate values are broken up into five 26-bit words. - private byte[] nonce; - private byte[] block; - private int[] h; - private int[] r; - private int[] c; - private long[] t; - private int posn; - - /** - * Constructs a new Poly1305 message authenticator. - */ - public Poly1305() - { - nonce = new byte [16]; - block = new byte [16]; - h = new int [5]; - r = new int [5]; - c = new int [5]; - t = new long [10]; - posn = 0; - } - - /** - * Resets the message authenticator with a new key. - * - * @param key The buffer containing the 32 byte key. - * @param offset The offset into the buffer of the first key byte. - */ - public void reset(byte[] key, int offset) - { - System.arraycopy(key, offset + 16, nonce, 0, 16); - Arrays.fill(h, 0); - posn = 0; - - // Convert the first 16 bytes of the key into a 130-bit - // "r" value while masking off the bits that we don't need. - r[0] = ((key[offset] & 0xFF)) | - ((key[offset + 1] & 0xFF) << 8) | - ((key[offset + 2] & 0xFF) << 16) | - ((key[offset + 3] & 0x03) << 24); - r[1] = ((key[offset + 3] & 0x0C) >> 2) | - ((key[offset + 4] & 0xFC) << 6) | - ((key[offset + 5] & 0xFF) << 14) | - ((key[offset + 6] & 0x0F) << 22); - r[2] = ((key[offset + 6] & 0xF0) >> 4) | - ((key[offset + 7] & 0x0F) << 4) | - ((key[offset + 8] & 0xFC) << 12) | - ((key[offset + 9] & 0x3F) << 20); - r[3] = ((key[offset + 9] & 0xC0) >> 6) | - ((key[offset + 10] & 0xFF) << 2) | - ((key[offset + 11] & 0x0F) << 10) | - ((key[offset + 12] & 0xFC) << 18); - r[4] = ((key[offset + 13] & 0xFF)) | - ((key[offset + 14] & 0xFF) << 8) | - ((key[offset + 15] & 0x0F) << 16); - } - - /** - * Updates the message authenticator with more input data. - * - * @param data The buffer containing the input data. - * @param offset The offset of the first byte of input. - * @param length The number of bytes of input. - */ - public void update(byte[] data, int offset, int length) - { - while (length > 0) { - if (posn == 0 && length >= 16) { - // We can process the chunk directly out of the input buffer. - processChunk(data, offset, false); - offset += 16; - length -= 16; - } else { - // Collect up partial bytes in the block buffer. - int temp = 16 - posn; - if (temp > length) - temp = length; - System.arraycopy(data, offset, block, posn, temp); - offset += temp; - length -= temp; - posn += temp; - if (posn >= 16) { - processChunk(block, 0, false); - posn = 0; - } - } - } - } - - /** - * Pads the input with zeroes to a multiple of 16 bytes. - */ - public void pad() - { - if (posn != 0) { - Arrays.fill(block, posn, 16, (byte)0); - processChunk(block, 0, false); - posn = 0; - } - } - - /** - * Finishes the message authenticator and returns the 16-byte token. - * - * @param token The buffer to receive the token. - * @param offset The offset of the token in the buffer. - */ - public void finish(byte[] token, int offset) - { - // Pad and flush the final chunk. - if (posn != 0) { - block[posn] = (byte)1; - Arrays.fill(block, posn + 1, 16, (byte)0); - processChunk(block, 0, true); - } - - // At this point, processChunk() has left h as a partially reduced - // result that is less than (2^130 - 5) * 6. Perform one more - // reduction and a trial subtraction to produce the final result. - - // Multiply the high bits of h by 5 and add them to the 130 low bits. - int carry = (h[4] >> 26) * 5 + h[0]; - h[0] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[1]; - h[1] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[2]; - h[2] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[3]; - h[3] = carry & 0x03FFFFFF; - h[4] = (carry >> 26) + (h[4] & 0x03FFFFFF); - - // Subtract (2^130 - 5) from h by computing c = h + 5 - 2^130. - // The "minus 2^130" step is implicit. - carry = 5 + h[0]; - c[0] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[1]; - c[1] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[2]; - c[2] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[3]; - c[3] = carry & 0x03FFFFFF; - c[4] = (carry >> 26) + h[4]; - - // Borrow occurs if bit 2^130 of the previous c result is zero. - // Carefully turn this into a selection mask so we can select either - // h or c as the final result. - int mask = -((c[4] >> 26) & 0x01); - int nmask = ~mask; - h[0] = (h[0] & nmask) | (c[0] & mask); - h[1] = (h[1] & nmask) | (c[1] & mask); - h[2] = (h[2] & nmask) | (c[2] & mask); - h[3] = (h[3] & nmask) | (c[3] & mask); - h[4] = (h[4] & nmask) | (c[4] & mask); - - // Convert h into little-endian in the block buffer. - block[0] = (byte)(h[0]); - block[1] = (byte)(h[0] >> 8); - block[2] = (byte)(h[0] >> 16); - block[3] = (byte)((h[0] >> 24) | (h[1] << 2)); - block[4] = (byte)(h[1] >> 6); - block[5] = (byte)(h[1] >> 14); - block[6] = (byte)((h[1] >> 22) | (h[2] << 4)); - block[7] = (byte)(h[2] >> 4); - block[8] = (byte)(h[2] >> 12); - block[9] = (byte)((h[2] >> 20) | (h[3] << 6)); - block[10] = (byte)(h[3] >> 2); - block[11] = (byte)(h[3] >> 10); - block[12] = (byte)(h[3] >> 18); - block[13] = (byte)(h[4]); - block[14] = (byte)(h[4] >> 8); - block[15] = (byte)(h[4] >> 16); - - // Add the nonce and write the final result to the token. - carry = (nonce[0] & 0xFF) + (block[0] & 0xFF); - token[offset] = (byte)carry; - for (int x = 1; x < 16; ++x) { - carry = (carry >> 8) + (nonce[x] & 0xFF) + (block[x] & 0xFF); - token[offset + x] = (byte)carry; - } - } - - /** - * Processes the next chunk of input data. - * - * @param chunk Buffer containing the input data chunk. - * @param offset Offset of the first byte of the 16-byte chunk. - * @param finalChunk Set to true if this is the final chunk. - */ - private void processChunk(byte[] chunk, int offset, boolean finalChunk) - { - int x; - - // Unpack the 128-bit chunk into a 130-bit value in "c". - c[0] = ((chunk[offset] & 0xFF)) | - ((chunk[offset + 1] & 0xFF) << 8) | - ((chunk[offset + 2] & 0xFF) << 16) | - ((chunk[offset + 3] & 0x03) << 24); - c[1] = ((chunk[offset + 3] & 0xFC) >> 2) | - ((chunk[offset + 4] & 0xFF) << 6) | - ((chunk[offset + 5] & 0xFF) << 14) | - ((chunk[offset + 6] & 0x0F) << 22); - c[2] = ((chunk[offset + 6] & 0xF0) >> 4) | - ((chunk[offset + 7] & 0xFF) << 4) | - ((chunk[offset + 8] & 0xFF) << 12) | - ((chunk[offset + 9] & 0x3F) << 20); - c[3] = ((chunk[offset + 9] & 0xC0) >> 6) | - ((chunk[offset + 10] & 0xFF) << 2) | - ((chunk[offset + 11] & 0xFF) << 10) | - ((chunk[offset + 12] & 0xFF) << 18); - c[4] = ((chunk[offset + 13] & 0xFF)) | - ((chunk[offset + 14] & 0xFF) << 8) | - ((chunk[offset + 15] & 0xFF) << 16); - if (!finalChunk) - c[4] |= (1 << 24); - - // Compute h = ((h + c) * r) mod (2^130 - 5) - - // Start with h += c. We assume that h is less than (2^130 - 5) * 6 - // and that c is less than 2^129, so the result will be less than 2^133. - h[0] += c[0]; - h[1] += c[1]; - h[2] += c[2]; - h[3] += c[3]; - h[4] += c[4]; - - // Multiply h by r. We know that r is less than 2^124 because the - // top 4 bits were AND-ed off by reset(). That makes h * r less - // than 2^257. Which is less than the (2^130 - 6)^2 we want for - // the modulo reduction step that follows. The intermediate limbs - // are 52 bits in size, which allows us to collect up carries in the - // extra bits of the 64 bit longs and propagate them later. - long hv = h[0]; - t[0] = hv * r[0]; - t[1] = hv * r[1]; - t[2] = hv * r[2]; - t[3] = hv * r[3]; - t[4] = hv * r[4]; - for (x = 1; x < 5; ++x) { - hv = h[x]; - t[x] += hv * r[0]; - t[x + 1] += hv * r[1]; - t[x + 2] += hv * r[2]; - t[x + 3] += hv * r[3]; - t[x + 4] = hv * r[4]; - } - - // Propagate carries to convert the t limbs from 52-bit back to 26-bit. - // The low bits are placed into h and the high bits are placed into c. - h[0] = ((int)t[0]) & 0x03FFFFFF; - hv = t[1] + (t[0] >> 26); - h[1] = ((int)hv) & 0x03FFFFFF; - hv = t[2] + (hv >> 26); - h[2] = ((int)hv) & 0x03FFFFFF; - hv = t[3] + (hv >> 26); - h[3] = ((int)hv) & 0x03FFFFFF; - hv = t[4] + (hv >> 26); - h[4] = ((int)hv) & 0x03FFFFFF; - hv = t[5] + (hv >> 26); - c[0] = ((int)hv) & 0x03FFFFFF; - hv = t[6] + (hv >> 26); - c[1] = ((int)hv) & 0x03FFFFFF; - hv = t[7] + (hv >> 26); - c[2] = ((int)hv) & 0x03FFFFFF; - hv = t[8] + (hv >> 26); - c[3] = ((int)hv) & 0x03FFFFFF; - hv = t[9] + (hv >> 26); - c[4] = ((int)hv); - - // Reduce h * r modulo (2^130 - 5) by multiplying the high 130 bits by 5 - // and adding them to the low 130 bits. This will leave the result at - // most 5 subtractions away from the answer we want. - int carry = h[0] + c[0] * 5; - h[0] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[1] + c[1] * 5; - h[1] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[2] + c[2] * 5; - h[2] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[3] + c[3] * 5; - h[3] = carry & 0x03FFFFFF; - carry = (carry >> 26) + h[4] + c[4] * 5; - h[4] = carry; - } - - @Override - public void destroy() { - Arrays.fill(nonce, (byte)0); - Arrays.fill(block, (byte)0); - Arrays.fill(h, (int)0); - Arrays.fill(r, (int)0); - Arrays.fill(c, (int)0); - Arrays.fill(t, (long)0); - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/RijndaelAES.java b/src/main/java/com/southernstorm/noise/crypto/RijndaelAES.java deleted file mode 100644 index f8f200ed8..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/RijndaelAES.java +++ /dev/null @@ -1,1099 +0,0 @@ -// This implementation is a straight C-to-Java port of the -// public domain code from the original Rijndael authors: -// http://web.cs.ucdavis.edu/~rogaway/ocb/ocb-ref/ -// The original license declaration follows (all modifications -// are released under the same terms): - -/* - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen - * @author Antoon Bosselaers - * @author Paulo Barreto - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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 com.southernstorm.noise.crypto; - -import java.util.Arrays; - -/** - * Public domain fallback implementation of AES in ECB mode. - */ -public class RijndaelAES { - - private int[] rk; - private int Nr; - - /** - * Constructs a new key schedule object for AES encryption/decryption. - */ - public RijndaelAES() - { - rk = new int [60]; - Nr = 14; - } - - /** - * Destroys the sensitive state in this key schedule. - */ - public void destroy() { - Arrays.fill(rk, 0); - } - - private static int GETU32(byte[] buf, int offset) - { - return ((buf[offset ] & 0xFF) << 24) | - ((buf[offset + 1] & 0xFF) << 16) | - ((buf[offset + 2] & 0xFF) << 8) | - (buf[offset + 3] & 0xFF); - } - - private static void PUTU32(byte[] buf, int offset, int value) - { - buf[offset] = (byte)(value >> 24); - buf[offset + 1] = (byte)(value >> 16); - buf[offset + 2] = (byte)(value >> 8); - buf[offset + 3] = (byte)value; - } - - /** - * Expand the cipher key into the encryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ - public int setupEnc(byte[] cipherKey, int offset, int keyBits) { - int i = 0; - int temp; - - rk[0] = GETU32(cipherKey, offset ); - rk[1] = GETU32(cipherKey, offset + 4); - rk[2] = GETU32(cipherKey, offset + 8); - rk[3] = GETU32(cipherKey, offset + 12); - int rkoffset = 0; - if (keyBits == 128) { - for (;;) { - temp = rk[rkoffset + 3]; - rk[rkoffset + 4] = rk[rkoffset] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) & 0xff] & 0x000000ff) ^ - rcon[i]; - rk[rkoffset + 5] = rk[rkoffset + 1] ^ rk[rkoffset + 4]; - rk[rkoffset + 6] = rk[rkoffset + 2] ^ rk[rkoffset + 5]; - rk[rkoffset + 7] = rk[rkoffset + 3] ^ rk[rkoffset + 6]; - if (++i == 10) { - Nr = 10; - return Nr; - } - rkoffset += 4; - } - } - rk[rkoffset + 4] = GETU32(cipherKey, offset + 16); - rk[rkoffset + 5] = GETU32(cipherKey, offset + 20); - if (keyBits == 192) { - for (;;) { - temp = rk[rkoffset + 5]; - rk[rkoffset + 6] = rk[rkoffset] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) & 0xff] & 0x000000ff) ^ - rcon[i]; - rk[rkoffset + 7] = rk[rkoffset + 1] ^ rk[rkoffset + 6]; - rk[rkoffset + 8] = rk[rkoffset + 2] ^ rk[rkoffset + 7]; - rk[rkoffset + 9] = rk[rkoffset + 3] ^ rk[rkoffset + 8]; - if (++i == 8) { - Nr = 12; - return Nr; - } - rk[rkoffset + 10] = rk[rkoffset + 4] ^ rk[rkoffset + 9]; - rk[rkoffset + 11] = rk[rkoffset + 5] ^ rk[rkoffset + 10]; - rkoffset += 6; - } - } - rk[rkoffset + 6] = GETU32(cipherKey, offset + 24); - rk[rkoffset + 7] = GETU32(cipherKey, offset + 28); - if (keyBits == 256) { - for (;;) { - temp = rk[rkoffset + 7]; - rk[rkoffset + 8] = rk[rkoffset + 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) & 0xff] & 0x000000ff) ^ - rcon[i]; - rk[rkoffset + 9] = rk[rkoffset + 1] ^ rk[rkoffset + 8]; - rk[rkoffset + 10] = rk[rkoffset + 2] ^ rk[rkoffset + 9]; - rk[rkoffset + 11] = rk[rkoffset + 3] ^ rk[rkoffset + 10]; - if (++i == 7) { - Nr = 14; - return Nr; - } - temp = rk[rkoffset + 11]; - rk[rkoffset + 12] = rk[rkoffset + 4] ^ - (Te4[(temp >> 24) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(temp ) & 0xff] & 0x000000ff); - rk[rkoffset + 13] = rk[rkoffset + 5] ^ rk[rkoffset + 12]; - rk[rkoffset + 14] = rk[rkoffset + 6] ^ rk[rkoffset + 13]; - rk[rkoffset + 15] = rk[rkoffset + 7] ^ rk[rkoffset + 14]; - - rkoffset += 8; - } - } - return 0; - } - - /** - * Expand the cipher key into the decryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ - public int setupDec(byte[] cipherKey, int offset, int keyBits) { - int Nr, i, j; - int temp; - - /* expand the cipher key: */ - Nr = setupEnc(cipherKey, offset, keyBits); - /* invert the order of the round keys: */ - for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - /* apply the inverse MixColumn transform to all round keys but the first and the last: */ - int rkoffset = 0; - for (i = 1; i < Nr; i++) { - rkoffset += 4; - rk[rkoffset + 0] = - Td0[Te4[(rk[rkoffset ] >> 24) & 0xff] & 0xff] ^ - Td1[Te4[(rk[rkoffset ] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[rkoffset ] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[rkoffset ] ) & 0xff] & 0xff]; - rk[rkoffset + 1] = - Td0[Te4[(rk[rkoffset + 1] >> 24) & 0xff] & 0xff] ^ - Td1[Te4[(rk[rkoffset + 1] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[rkoffset + 1] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[rkoffset + 1] ) & 0xff] & 0xff]; - rk[rkoffset + 2] = - Td0[Te4[(rk[rkoffset + 2] >> 24) & 0xff] & 0xff] ^ - Td1[Te4[(rk[rkoffset + 2] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[rkoffset + 2] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[rkoffset + 2] ) & 0xff] & 0xff]; - rk[rkoffset + 3] = - Td0[Te4[(rk[rkoffset + 3] >> 24) & 0xff] & 0xff] ^ - Td1[Te4[(rk[rkoffset + 3] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[rkoffset + 3] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[rkoffset + 3] ) & 0xff] & 0xff]; - } - this.Nr = Nr; - return Nr; - } - - public void encrypt(byte[] pt, int ptoffset, byte[] ct, int ctoffset) { - int s0, s1, s2, s3, t0, t1, t2, t3; - int r, rkoffset; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(pt, ptoffset ) ^ rk[0]; - s1 = GETU32(pt, ptoffset + 4) ^ rk[1]; - s2 = GETU32(pt, ptoffset + 8) ^ rk[2]; - s3 = GETU32(pt, ptoffset + 12) ^ rk[3]; - - /* - * Nr - 1 full rounds: - */ - r = Nr >> 1; - rkoffset = 0; - for (;;) { - t0 = - Te0[(s0 >> 24) & 0xff] ^ - Te1[(s1 >> 16) & 0xff] ^ - Te2[(s2 >> 8) & 0xff] ^ - Te3[(s3 ) & 0xff] ^ - rk[rkoffset + 4]; - t1 = - Te0[(s1 >> 24) & 0xff] ^ - Te1[(s2 >> 16) & 0xff] ^ - Te2[(s3 >> 8) & 0xff] ^ - Te3[(s0 ) & 0xff] ^ - rk[rkoffset + 5]; - t2 = - Te0[(s2 >> 24) & 0xff] ^ - Te1[(s3 >> 16) & 0xff] ^ - Te2[(s0 >> 8) & 0xff] ^ - Te3[(s1 ) & 0xff] ^ - rk[rkoffset + 6]; - t3 = - Te0[(s3 >> 24) & 0xff] ^ - Te1[(s0 >> 16) & 0xff] ^ - Te2[(s1 >> 8) & 0xff] ^ - Te3[(s2 ) & 0xff] ^ - rk[rkoffset + 7]; - - rkoffset += 8; - if (--r == 0) { - break; - } - - s0 = - Te0[(t0 >> 24) & 0xff] ^ - Te1[(t1 >> 16) & 0xff] ^ - Te2[(t2 >> 8) & 0xff] ^ - Te3[(t3 ) & 0xff] ^ - rk[rkoffset]; - s1 = - Te0[(t1 >> 24) & 0xff] ^ - Te1[(t2 >> 16) & 0xff] ^ - Te2[(t3 >> 8) & 0xff] ^ - Te3[(t0 ) & 0xff] ^ - rk[rkoffset + 1]; - s2 = - Te0[(t2 >> 24) & 0xff] ^ - Te1[(t3 >> 16) & 0xff] ^ - Te2[(t0 >> 8) & 0xff] ^ - Te3[(t1 ) & 0xff] ^ - rk[rkoffset + 2]; - s3 = - Te0[(t3 >> 24) & 0xff] ^ - Te1[(t0 >> 16) & 0xff] ^ - Te2[(t1 >> 8) & 0xff] ^ - Te3[(t2 ) & 0xff] ^ - rk[rkoffset + 3]; - } - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Te4[(t0 >> 24) & 0xff] & 0xff000000) ^ - (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[rkoffset]; - PUTU32(ct, ctoffset , s0); - s1 = - (Te4[(t1 >> 24) & 0xff] & 0xff000000) ^ - (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[rkoffset + 1]; - PUTU32(ct, ctoffset + 4, s1); - s2 = - (Te4[(t2 >> 24) & 0xff] & 0xff000000) ^ - (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[rkoffset + 2]; - PUTU32(ct, ctoffset + 8, s2); - s3 = - (Te4[(t3 >> 24) & 0xff] & 0xff000000) ^ - (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[rkoffset + 3]; - PUTU32(ct, ctoffset + 12, s3); - } - - public void decrypt(byte[] ct, int ctoffset, byte[] pt, int ptoffset) { - int s0, s1, s2, s3, t0, t1, t2, t3; - int r, rkoffset; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(ct, ctoffset ) ^ rk[0]; - s1 = GETU32(ct, ctoffset + 4) ^ rk[1]; - s2 = GETU32(ct, ctoffset + 8) ^ rk[2]; - s3 = GETU32(ct, ctoffset + 12) ^ rk[3]; - - /* - * Nr - 1 full rounds: - */ - r = Nr >> 1; - rkoffset = 0; - for (;;) { - t0 = - Td0[(s0 >> 24) & 0xff] ^ - Td1[(s3 >> 16) & 0xff] ^ - Td2[(s2 >> 8) & 0xff] ^ - Td3[(s1 ) & 0xff] ^ - rk[rkoffset + 4]; - t1 = - Td0[(s1 >> 24) & 0xff] ^ - Td1[(s0 >> 16) & 0xff] ^ - Td2[(s3 >> 8) & 0xff] ^ - Td3[(s2 ) & 0xff] ^ - rk[rkoffset + 5]; - t2 = - Td0[(s2 >> 24) & 0xff] ^ - Td1[(s1 >> 16) & 0xff] ^ - Td2[(s0 >> 8) & 0xff] ^ - Td3[(s3 ) & 0xff] ^ - rk[rkoffset + 6]; - t3 = - Td0[(s3 >> 24) & 0xff] ^ - Td1[(s2 >> 16) & 0xff] ^ - Td2[(s1 >> 8) & 0xff] ^ - Td3[(s0 ) & 0xff] ^ - rk[rkoffset + 7]; - - rkoffset += 8; - if (--r == 0) { - break; - } - - s0 = - Td0[(t0 >> 24) & 0xff] ^ - Td1[(t3 >> 16) & 0xff] ^ - Td2[(t2 >> 8) & 0xff] ^ - Td3[(t1 ) & 0xff] ^ - rk[rkoffset]; - s1 = - Td0[(t1 >> 24) & 0xff] ^ - Td1[(t0 >> 16) & 0xff] ^ - Td2[(t3 >> 8) & 0xff] ^ - Td3[(t2 ) & 0xff] ^ - rk[rkoffset + 1]; - s2 = - Td0[(t2 >> 24) & 0xff] ^ - Td1[(t1 >> 16) & 0xff] ^ - Td2[(t0 >> 8) & 0xff] ^ - Td3[(t3 ) & 0xff] ^ - rk[rkoffset + 2]; - s3 = - Td0[(t3 >> 24) & 0xff] ^ - Td1[(t2 >> 16) & 0xff] ^ - Td2[(t1 >> 8) & 0xff] ^ - Td3[(t0 ) & 0xff] ^ - rk[rkoffset + 3]; - } - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Td4[(t0 >> 24) & 0xff] & 0xff000000) ^ - (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[rkoffset]; - PUTU32(pt, ptoffset , s0); - s1 = - (Td4[(t1 >> 24) & 0xff] & 0xff000000) ^ - (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[rkoffset + 1]; - PUTU32(pt, ptoffset + 4, s1); - s2 = - (Td4[(t2 >> 24) & 0xff] & 0xff000000) ^ - (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[rkoffset + 2]; - PUTU32(pt, ptoffset + 8, s2); - s3 = - (Td4[(t3 >> 24) & 0xff] & 0xff000000) ^ - (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[rkoffset + 3]; - PUTU32(pt, ptoffset + 12, s3); - } - - private static final int[] Te0 = { - 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, - 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, - 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, - 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, - 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, - 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, - 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, - 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, - 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, - 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, - 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, - 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, - 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, - 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, - 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, - 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, - 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, - 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, - 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, - 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, - 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, - 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, - 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, - 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, - 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, - 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, - 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, - 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, - 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, - 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, - 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, - 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, - 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, - 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, - 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, - 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, - 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, - 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, - 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, - 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, - 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, - 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, - 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, - 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, - 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, - 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, - 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, - 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, - 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, - 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, - 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, - 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, - 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, - 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, - 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, - 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, - 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, - 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, - 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, - 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, - 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, - 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, - 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, - 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, - }; - private static final int[] Te1 = { - 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, - 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, - 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, - 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, - 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, - 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, - 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, - 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, - 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, - 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, - 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, - 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, - 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, - 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, - 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, - 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, - 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, - 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, - 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, - 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, - 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, - 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, - 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, - 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, - 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, - 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, - 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, - 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, - 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, - 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, - 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, - 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, - 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, - 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, - 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, - 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, - 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, - 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, - 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, - 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, - 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, - 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, - 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, - 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, - 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, - 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, - 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, - 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, - 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, - 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, - 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, - 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, - 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, - 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, - 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, - 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, - 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, - 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, - 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, - 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, - 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, - 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, - 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, - 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, - }; - private static final int[] Te2 = { - 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, - 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, - 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, - 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, - 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, - 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, - 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, - 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, - 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, - 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, - 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, - 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, - 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, - 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, - 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, - 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, - 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, - 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, - 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, - 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, - 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, - 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, - 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, - 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, - 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, - 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, - 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, - 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, - 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, - 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, - 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, - 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, - 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, - 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, - 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, - 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, - 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, - 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, - 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, - 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, - 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, - 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, - 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, - 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, - 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, - 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, - 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, - 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, - 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, - 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, - 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, - 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, - 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, - 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, - 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, - 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, - 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, - 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, - 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, - 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, - 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, - 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, - 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, - 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, - }; - private static final int[] Te3 = { - - 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, - 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, - 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, - 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, - 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, - 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, - 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, - 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, - 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, - 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, - 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, - 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, - 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, - 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, - 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, - 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, - 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, - 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, - 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, - 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, - 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, - 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, - 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, - 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, - 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, - 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, - 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, - 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, - 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, - 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, - 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, - 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, - 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, - 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, - 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, - 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, - 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, - 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, - 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, - 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, - 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, - 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, - 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, - 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, - 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, - 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, - 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, - 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, - 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, - 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, - 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, - 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, - 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, - 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, - 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, - 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, - 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, - 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, - 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, - 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, - 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, - 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, - 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, - 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, - }; - private static final int[] Te4 = { - 0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, - 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, - 0x30303030, 0x01010101, 0x67676767, 0x2b2b2b2b, - 0xfefefefe, 0xd7d7d7d7, 0xabababab, 0x76767676, - 0xcacacaca, 0x82828282, 0xc9c9c9c9, 0x7d7d7d7d, - 0xfafafafa, 0x59595959, 0x47474747, 0xf0f0f0f0, - 0xadadadad, 0xd4d4d4d4, 0xa2a2a2a2, 0xafafafaf, - 0x9c9c9c9c, 0xa4a4a4a4, 0x72727272, 0xc0c0c0c0, - 0xb7b7b7b7, 0xfdfdfdfd, 0x93939393, 0x26262626, - 0x36363636, 0x3f3f3f3f, 0xf7f7f7f7, 0xcccccccc, - 0x34343434, 0xa5a5a5a5, 0xe5e5e5e5, 0xf1f1f1f1, - 0x71717171, 0xd8d8d8d8, 0x31313131, 0x15151515, - 0x04040404, 0xc7c7c7c7, 0x23232323, 0xc3c3c3c3, - 0x18181818, 0x96969696, 0x05050505, 0x9a9a9a9a, - 0x07070707, 0x12121212, 0x80808080, 0xe2e2e2e2, - 0xebebebeb, 0x27272727, 0xb2b2b2b2, 0x75757575, - 0x09090909, 0x83838383, 0x2c2c2c2c, 0x1a1a1a1a, - 0x1b1b1b1b, 0x6e6e6e6e, 0x5a5a5a5a, 0xa0a0a0a0, - 0x52525252, 0x3b3b3b3b, 0xd6d6d6d6, 0xb3b3b3b3, - 0x29292929, 0xe3e3e3e3, 0x2f2f2f2f, 0x84848484, - 0x53535353, 0xd1d1d1d1, 0x00000000, 0xedededed, - 0x20202020, 0xfcfcfcfc, 0xb1b1b1b1, 0x5b5b5b5b, - 0x6a6a6a6a, 0xcbcbcbcb, 0xbebebebe, 0x39393939, - 0x4a4a4a4a, 0x4c4c4c4c, 0x58585858, 0xcfcfcfcf, - 0xd0d0d0d0, 0xefefefef, 0xaaaaaaaa, 0xfbfbfbfb, - 0x43434343, 0x4d4d4d4d, 0x33333333, 0x85858585, - 0x45454545, 0xf9f9f9f9, 0x02020202, 0x7f7f7f7f, - 0x50505050, 0x3c3c3c3c, 0x9f9f9f9f, 0xa8a8a8a8, - 0x51515151, 0xa3a3a3a3, 0x40404040, 0x8f8f8f8f, - 0x92929292, 0x9d9d9d9d, 0x38383838, 0xf5f5f5f5, - 0xbcbcbcbc, 0xb6b6b6b6, 0xdadadada, 0x21212121, - 0x10101010, 0xffffffff, 0xf3f3f3f3, 0xd2d2d2d2, - 0xcdcdcdcd, 0x0c0c0c0c, 0x13131313, 0xecececec, - 0x5f5f5f5f, 0x97979797, 0x44444444, 0x17171717, - 0xc4c4c4c4, 0xa7a7a7a7, 0x7e7e7e7e, 0x3d3d3d3d, - 0x64646464, 0x5d5d5d5d, 0x19191919, 0x73737373, - 0x60606060, 0x81818181, 0x4f4f4f4f, 0xdcdcdcdc, - 0x22222222, 0x2a2a2a2a, 0x90909090, 0x88888888, - 0x46464646, 0xeeeeeeee, 0xb8b8b8b8, 0x14141414, - 0xdededede, 0x5e5e5e5e, 0x0b0b0b0b, 0xdbdbdbdb, - 0xe0e0e0e0, 0x32323232, 0x3a3a3a3a, 0x0a0a0a0a, - 0x49494949, 0x06060606, 0x24242424, 0x5c5c5c5c, - 0xc2c2c2c2, 0xd3d3d3d3, 0xacacacac, 0x62626262, - 0x91919191, 0x95959595, 0xe4e4e4e4, 0x79797979, - 0xe7e7e7e7, 0xc8c8c8c8, 0x37373737, 0x6d6d6d6d, - 0x8d8d8d8d, 0xd5d5d5d5, 0x4e4e4e4e, 0xa9a9a9a9, - 0x6c6c6c6c, 0x56565656, 0xf4f4f4f4, 0xeaeaeaea, - 0x65656565, 0x7a7a7a7a, 0xaeaeaeae, 0x08080808, - 0xbabababa, 0x78787878, 0x25252525, 0x2e2e2e2e, - 0x1c1c1c1c, 0xa6a6a6a6, 0xb4b4b4b4, 0xc6c6c6c6, - 0xe8e8e8e8, 0xdddddddd, 0x74747474, 0x1f1f1f1f, - 0x4b4b4b4b, 0xbdbdbdbd, 0x8b8b8b8b, 0x8a8a8a8a, - 0x70707070, 0x3e3e3e3e, 0xb5b5b5b5, 0x66666666, - 0x48484848, 0x03030303, 0xf6f6f6f6, 0x0e0e0e0e, - 0x61616161, 0x35353535, 0x57575757, 0xb9b9b9b9, - 0x86868686, 0xc1c1c1c1, 0x1d1d1d1d, 0x9e9e9e9e, - 0xe1e1e1e1, 0xf8f8f8f8, 0x98989898, 0x11111111, - 0x69696969, 0xd9d9d9d9, 0x8e8e8e8e, 0x94949494, - 0x9b9b9b9b, 0x1e1e1e1e, 0x87878787, 0xe9e9e9e9, - 0xcececece, 0x55555555, 0x28282828, 0xdfdfdfdf, - 0x8c8c8c8c, 0xa1a1a1a1, 0x89898989, 0x0d0d0d0d, - 0xbfbfbfbf, 0xe6e6e6e6, 0x42424242, 0x68686868, - 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f, - 0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616, - }; - private static final int[] Td0 = { - 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, - 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, - 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, - 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, - 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, - 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, - 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, - 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, - 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, - 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, - 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, - 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, - 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, - 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, - 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, - 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, - 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, - 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, - 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, - 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, - 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, - 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, - 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, - 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, - 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, - 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, - 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, - 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, - 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, - 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, - 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, - 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, - 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, - 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, - 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, - 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, - 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, - 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, - 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, - 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, - 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, - 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, - 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, - 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, - 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, - 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, - 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, - 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, - 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, - 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, - 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, - 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, - 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, - 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, - 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, - 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, - 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, - 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, - 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, - 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, - 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, - 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, - 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, - 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, - }; - private static final int[] Td1 = { - 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, - 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, - 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, - 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, - 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, - 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, - 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, - 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, - 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, - 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, - 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, - 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, - 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, - 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, - 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, - 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, - 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, - 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, - 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, - 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, - 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, - 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, - 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, - 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, - 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, - 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, - 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, - 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, - 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, - 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, - 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, - 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, - 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, - 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, - 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, - 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, - 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, - 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, - 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, - 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, - 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, - 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, - 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, - 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, - 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, - 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, - 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, - 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, - 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, - 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, - 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, - 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, - 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, - 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, - 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, - 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, - 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, - 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, - 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, - 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, - 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, - 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, - 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, - 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857, - }; - private static final int[] Td2 = { - 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, - 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, - 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, - 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, - 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, - 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, - 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, - 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, - 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, - 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, - 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, - 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, - 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, - 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, - 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, - 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, - 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, - 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, - 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, - 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, - - 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, - 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, - 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, - 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, - 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, - 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, - 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, - 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, - 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, - 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, - 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, - 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, - 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, - 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, - 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, - 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, - 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, - 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, - 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, - 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, - 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, - 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, - 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, - 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, - 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, - 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, - 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, - 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, - 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, - 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, - 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, - 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, - 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, - 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, - 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, - 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, - 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, - 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, - 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, - 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, - 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, - 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, - 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, - 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8, - }; - private static final int[] Td3 = { - 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, - 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, - 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, - 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, - 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, - 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, - 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, - 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, - 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, - 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, - 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, - 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, - 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, - 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, - 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, - 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, - 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, - 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, - 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, - 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, - 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, - 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, - 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, - 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, - 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, - 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, - 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, - 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, - 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, - 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, - 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, - 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, - 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, - 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, - 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, - 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, - 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, - 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, - 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, - 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, - 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, - 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, - 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, - 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, - 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, - 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, - 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, - 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, - 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, - 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, - 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, - 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, - 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, - 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, - 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, - 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, - 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, - 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, - 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, - 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, - 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, - 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, - 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, - 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0, - }; - private static final int[] Td4 = { - 0x52525252, 0x09090909, 0x6a6a6a6a, 0xd5d5d5d5, - 0x30303030, 0x36363636, 0xa5a5a5a5, 0x38383838, - 0xbfbfbfbf, 0x40404040, 0xa3a3a3a3, 0x9e9e9e9e, - 0x81818181, 0xf3f3f3f3, 0xd7d7d7d7, 0xfbfbfbfb, - 0x7c7c7c7c, 0xe3e3e3e3, 0x39393939, 0x82828282, - 0x9b9b9b9b, 0x2f2f2f2f, 0xffffffff, 0x87878787, - 0x34343434, 0x8e8e8e8e, 0x43434343, 0x44444444, - 0xc4c4c4c4, 0xdededede, 0xe9e9e9e9, 0xcbcbcbcb, - 0x54545454, 0x7b7b7b7b, 0x94949494, 0x32323232, - 0xa6a6a6a6, 0xc2c2c2c2, 0x23232323, 0x3d3d3d3d, - 0xeeeeeeee, 0x4c4c4c4c, 0x95959595, 0x0b0b0b0b, - 0x42424242, 0xfafafafa, 0xc3c3c3c3, 0x4e4e4e4e, - 0x08080808, 0x2e2e2e2e, 0xa1a1a1a1, 0x66666666, - 0x28282828, 0xd9d9d9d9, 0x24242424, 0xb2b2b2b2, - 0x76767676, 0x5b5b5b5b, 0xa2a2a2a2, 0x49494949, - 0x6d6d6d6d, 0x8b8b8b8b, 0xd1d1d1d1, 0x25252525, - 0x72727272, 0xf8f8f8f8, 0xf6f6f6f6, 0x64646464, - 0x86868686, 0x68686868, 0x98989898, 0x16161616, - 0xd4d4d4d4, 0xa4a4a4a4, 0x5c5c5c5c, 0xcccccccc, - 0x5d5d5d5d, 0x65656565, 0xb6b6b6b6, 0x92929292, - 0x6c6c6c6c, 0x70707070, 0x48484848, 0x50505050, - 0xfdfdfdfd, 0xedededed, 0xb9b9b9b9, 0xdadadada, - 0x5e5e5e5e, 0x15151515, 0x46464646, 0x57575757, - 0xa7a7a7a7, 0x8d8d8d8d, 0x9d9d9d9d, 0x84848484, - 0x90909090, 0xd8d8d8d8, 0xabababab, 0x00000000, - 0x8c8c8c8c, 0xbcbcbcbc, 0xd3d3d3d3, 0x0a0a0a0a, - 0xf7f7f7f7, 0xe4e4e4e4, 0x58585858, 0x05050505, - 0xb8b8b8b8, 0xb3b3b3b3, 0x45454545, 0x06060606, - 0xd0d0d0d0, 0x2c2c2c2c, 0x1e1e1e1e, 0x8f8f8f8f, - 0xcacacaca, 0x3f3f3f3f, 0x0f0f0f0f, 0x02020202, - 0xc1c1c1c1, 0xafafafaf, 0xbdbdbdbd, 0x03030303, - 0x01010101, 0x13131313, 0x8a8a8a8a, 0x6b6b6b6b, - 0x3a3a3a3a, 0x91919191, 0x11111111, 0x41414141, - 0x4f4f4f4f, 0x67676767, 0xdcdcdcdc, 0xeaeaeaea, - 0x97979797, 0xf2f2f2f2, 0xcfcfcfcf, 0xcececece, - 0xf0f0f0f0, 0xb4b4b4b4, 0xe6e6e6e6, 0x73737373, - 0x96969696, 0xacacacac, 0x74747474, 0x22222222, - 0xe7e7e7e7, 0xadadadad, 0x35353535, 0x85858585, - 0xe2e2e2e2, 0xf9f9f9f9, 0x37373737, 0xe8e8e8e8, - 0x1c1c1c1c, 0x75757575, 0xdfdfdfdf, 0x6e6e6e6e, - 0x47474747, 0xf1f1f1f1, 0x1a1a1a1a, 0x71717171, - 0x1d1d1d1d, 0x29292929, 0xc5c5c5c5, 0x89898989, - 0x6f6f6f6f, 0xb7b7b7b7, 0x62626262, 0x0e0e0e0e, - 0xaaaaaaaa, 0x18181818, 0xbebebebe, 0x1b1b1b1b, - 0xfcfcfcfc, 0x56565656, 0x3e3e3e3e, 0x4b4b4b4b, - 0xc6c6c6c6, 0xd2d2d2d2, 0x79797979, 0x20202020, - 0x9a9a9a9a, 0xdbdbdbdb, 0xc0c0c0c0, 0xfefefefe, - 0x78787878, 0xcdcdcdcd, 0x5a5a5a5a, 0xf4f4f4f4, - 0x1f1f1f1f, 0xdddddddd, 0xa8a8a8a8, 0x33333333, - 0x88888888, 0x07070707, 0xc7c7c7c7, 0x31313131, - 0xb1b1b1b1, 0x12121212, 0x10101010, 0x59595959, - 0x27272727, 0x80808080, 0xecececec, 0x5f5f5f5f, - 0x60606060, 0x51515151, 0x7f7f7f7f, 0xa9a9a9a9, - 0x19191919, 0xb5b5b5b5, 0x4a4a4a4a, 0x0d0d0d0d, - 0x2d2d2d2d, 0xe5e5e5e5, 0x7a7a7a7a, 0x9f9f9f9f, - 0x93939393, 0xc9c9c9c9, 0x9c9c9c9c, 0xefefefef, - 0xa0a0a0a0, 0xe0e0e0e0, 0x3b3b3b3b, 0x4d4d4d4d, - 0xaeaeaeae, 0x2a2a2a2a, 0xf5f5f5f5, 0xb0b0b0b0, - 0xc8c8c8c8, 0xebebebeb, 0xbbbbbbbb, 0x3c3c3c3c, - 0x83838383, 0x53535353, 0x99999999, 0x61616161, - 0x17171717, 0x2b2b2b2b, 0x04040404, 0x7e7e7e7e, - 0xbabababa, 0x77777777, 0xd6d6d6d6, 0x26262626, - 0xe1e1e1e1, 0x69696969, 0x14141414, 0x63636363, - 0x55555555, 0x21212121, 0x0c0c0c0c, 0x7d7d7d7d, - }; - private static final int[] rcon = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ - }; -} diff --git a/src/main/java/com/southernstorm/noise/crypto/SHA256MessageDigest.java b/src/main/java/com/southernstorm/noise/crypto/SHA256MessageDigest.java deleted file mode 100644 index f2fb85dc5..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/SHA256MessageDigest.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.crypto; - -import com.southernstorm.noise.protocol.Destroyable; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.util.Arrays; - -/** - * Fallback implementation of SHA256. - */ -public class SHA256MessageDigest extends MessageDigest implements Destroyable { - - private int[] h; - private byte[] block; - private int[] w; - private long length; - private int posn; - - /** - * Constructs a new SHA256 message digest object. - */ - public SHA256MessageDigest() { - super("SHA-256"); - h = new int [8]; - block = new byte [64]; - w = new int [64]; - engineReset(); - } - - @Override - public void destroy() { - Arrays.fill(h, (int)0); - Arrays.fill(block, (byte)0); - Arrays.fill(w, (int)0); - } - - private static void writeBE32(byte[] buf, int offset, int value) - { - buf[offset] = (byte)(value >> 24); - buf[offset + 1] = (byte)(value >> 16); - buf[offset + 2] = (byte)(value >> 8); - buf[offset + 3] = (byte)value; - } - - @Override - protected byte[] engineDigest() { - byte[] digest = new byte [32]; - try { - engineDigest(digest, 0, 32); - } catch (DigestException e) { - // Shouldn't happen, but just in case. - Arrays.fill(digest, (byte)0); - } - return digest; - } - - @Override - protected int engineDigest(byte[] buf, int offset, int len) throws DigestException - { - if (len < 32) - throw new DigestException("Invalid digest length for SHA256"); - if (posn <= (64 - 9)) { - block[posn] = (byte)0x80; - Arrays.fill(block, posn + 1, 64 - 8, (byte)0); - } else { - block[posn] = (byte)0x80; - Arrays.fill(block, posn + 1, 64, (byte)0); - transform(block, 0); - Arrays.fill(block, 0, 64 - 8, (byte)0); - } - writeBE32(block, 64 - 8, (int)(length >> 32)); - writeBE32(block, 64 - 4, (int)length); - transform(block, 0); - posn = 0; - for (int index = 0; index < 8; ++index) - writeBE32(buf, offset + index * 4, h[index]); - return 32; - } - - @Override - protected int engineGetDigestLength() { - return 32; - } - - @Override - protected void engineReset() { - h[0] = 0x6A09E667; - h[1] = 0xBB67AE85; - h[2] = 0x3C6EF372; - h[3] = 0xA54FF53A; - h[4] = 0x510E527F; - h[5] = 0x9B05688C; - h[6] = 0x1F83D9AB; - h[7] = 0x5BE0CD19; - length = 0; - posn = 0; - } - - @Override - protected void engineUpdate(byte input) { - block[posn++] = input; - length += 8; - if (posn >= 64) { - transform(block, 0); - posn = 0; - } - } - - @Override - protected void engineUpdate(byte[] input, int offset, int len) { - while (len > 0) { - if (posn == 0 && len >= 64) { - transform(input, offset); - offset += 64; - len -= 64; - length += 64 * 8; - } else { - int temp = 64 - posn; - if (temp > len) - temp = len; - System.arraycopy(input, offset, block, posn, temp); - posn += temp; - length += temp * 8; - if (posn >= 64) { - transform(block, 0); - posn = 0; - } - offset += temp; - len -= temp; - } - } - } - - private static final int[] k = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - }; - - private static int rightRotate(int value, int n) - { - return (value >>> n) | (value << (32 - n)); - } - - private void transform(byte[] m, int offset) - { - int a, b, c, d, e, f, g, h; - int temp1, temp2; - int index; - - // Initialize working variables to the current hash value. - a = this.h[0]; - b = this.h[1]; - c = this.h[2]; - d = this.h[3]; - e = this.h[4]; - f = this.h[5]; - g = this.h[6]; - h = this.h[7]; - - // Convert the 16 input message words from big endian to host byte order. - for (index = 0; index < 16; ++index) { - w[index] = ((m[offset] & 0xFF) << 24) | - ((m[offset + 1] & 0xFF) << 16) | - ((m[offset + 2] & 0xFF) << 8) | - (m[offset + 3] & 0xFF); - offset += 4; - } - - // Extend the first 16 words to 64. - for (index = 16; index < 64; ++index) { - w[index] = w[index - 16] + w[index - 7] + - (rightRotate(w[index - 15], 7) ^ - rightRotate(w[index - 15], 18) ^ - (w[index - 15] >>> 3)) + - (rightRotate(w[index - 2], 17) ^ - rightRotate(w[index - 2], 19) ^ - (w[index - 2] >>> 10)); - } - - // Compression function main loop. - for (index = 0; index < 64; ++index) { - temp1 = (h) + k[index] + w[index] + - (rightRotate((e), 6) ^ rightRotate((e), 11) ^ rightRotate((e), 25)) + - (((e) & (f)) ^ ((~(e)) & (g))); - temp2 = (rightRotate((a), 2) ^ rightRotate((a), 13) ^ rightRotate((a), 22)) + - (((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c))); - h = g; - g = f; - f = e; - e = d + temp1; - d = c; - c = b; - b = a; - a = temp1 + temp2; - } - - // Add the compressed chunk to the current hash value. - this.h[0] += a; - this.h[1] += b; - this.h[2] += c; - this.h[3] += d; - this.h[4] += e; - this.h[5] += f; - this.h[6] += g; - this.h[7] += h; - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/SHA512MessageDigest.java b/src/main/java/com/southernstorm/noise/crypto/SHA512MessageDigest.java deleted file mode 100644 index 54b1eaedf..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/SHA512MessageDigest.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.crypto; - -import com.southernstorm.noise.protocol.Destroyable; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.util.Arrays; - -/** - * Fallback implementation of SHA512. - * - * Note: This implementation is limited to a maximum 2^56 - 1 bytes of input. - * That is, we don't bother trying to implement 128-bit length values. - */ -public class SHA512MessageDigest extends MessageDigest implements Destroyable { - - private long[] h; - private byte[] block; - private long[] w; - private long length; - private int posn; - - /** - * Constructs a new SHA512 message digest object. - */ - public SHA512MessageDigest() { - super("SHA-512"); - h = new long [8]; - block = new byte [128]; - w = new long [80]; - engineReset(); - } - - @Override - public void destroy() { - Arrays.fill(h, (long)0); - Arrays.fill(block, (byte)0); - Arrays.fill(w, (long)0); - } - - private static void writeBE64(byte[] buf, int offset, long value) - { - buf[offset] = (byte)(value >> 56); - buf[offset + 1] = (byte)(value >> 48); - buf[offset + 2] = (byte)(value >> 40); - buf[offset + 3] = (byte)(value >> 32); - buf[offset + 4] = (byte)(value >> 24); - buf[offset + 5] = (byte)(value >> 16); - buf[offset + 6] = (byte)(value >> 8); - buf[offset + 7] = (byte)value; - } - - @Override - protected byte[] engineDigest() { - byte[] digest = new byte [64]; - try { - engineDigest(digest, 0, 64); - } catch (DigestException e) { - // Shouldn't happen, but just in case. - Arrays.fill(digest, (byte)0); - } - return digest; - } - - @Override - protected int engineDigest(byte[] buf, int offset, int len) throws DigestException - { - if (len < 64) - throw new DigestException("Invalid digest length for SHA512"); - if (posn <= (128 - 17)) { - block[posn] = (byte)0x80; - Arrays.fill(block, posn + 1, 128 - 8, (byte)0); - } else { - block[posn] = (byte)0x80; - Arrays.fill(block, posn + 1, 128, (byte)0); - transform(block, 0); - Arrays.fill(block, 0, 128 - 8, (byte)0); - } - writeBE64(block, 128 - 8, length); - transform(block, 0); - posn = 0; - for (int index = 0; index < 8; ++index) - writeBE64(buf, offset + index * 8, h[index]); - return 64; - } - - @Override - protected int engineGetDigestLength() { - return 64; - } - - @Override - protected void engineReset() { - h[0] = 0x6a09e667f3bcc908L; - h[1] = 0xbb67ae8584caa73bL; - h[2] = 0x3c6ef372fe94f82bL; - h[3] = 0xa54ff53a5f1d36f1L; - h[4] = 0x510e527fade682d1L; - h[5] = 0x9b05688c2b3e6c1fL; - h[6] = 0x1f83d9abfb41bd6bL; - h[7] = 0x5be0cd19137e2179L; - length = 0; - posn = 0; - } - - @Override - protected void engineUpdate(byte input) { - block[posn++] = input; - length += 8; - if (posn >= 128) { - transform(block, 0); - posn = 0; - } - } - - @Override - protected void engineUpdate(byte[] input, int offset, int len) { - while (len > 0) { - if (posn == 0 && len >= 128) { - transform(input, offset); - offset += 128; - len -= 128; - length += 128 * 8; - } else { - int temp = 128 - posn; - if (temp > len) - temp = len; - System.arraycopy(input, offset, block, posn, temp); - posn += temp; - length += temp * 8; - if (posn >= 128) { - transform(block, 0); - posn = 0; - } - offset += temp; - len -= temp; - } - } - } - - private static final long[] k = { - 0x428A2F98D728AE22L, 0x7137449123EF65CDL, 0xB5C0FBCFEC4D3B2FL, - 0xE9B5DBA58189DBBCL, 0x3956C25BF348B538L, 0x59F111F1B605D019L, - 0x923F82A4AF194F9BL, 0xAB1C5ED5DA6D8118L, 0xD807AA98A3030242L, - 0x12835B0145706FBEL, 0x243185BE4EE4B28CL, 0x550C7DC3D5FFB4E2L, - 0x72BE5D74F27B896FL, 0x80DEB1FE3B1696B1L, 0x9BDC06A725C71235L, - 0xC19BF174CF692694L, 0xE49B69C19EF14AD2L, 0xEFBE4786384F25E3L, - 0x0FC19DC68B8CD5B5L, 0x240CA1CC77AC9C65L, 0x2DE92C6F592B0275L, - 0x4A7484AA6EA6E483L, 0x5CB0A9DCBD41FBD4L, 0x76F988DA831153B5L, - 0x983E5152EE66DFABL, 0xA831C66D2DB43210L, 0xB00327C898FB213FL, - 0xBF597FC7BEEF0EE4L, 0xC6E00BF33DA88FC2L, 0xD5A79147930AA725L, - 0x06CA6351E003826FL, 0x142929670A0E6E70L, 0x27B70A8546D22FFCL, - 0x2E1B21385C26C926L, 0x4D2C6DFC5AC42AEDL, 0x53380D139D95B3DFL, - 0x650A73548BAF63DEL, 0x766A0ABB3C77B2A8L, 0x81C2C92E47EDAEE6L, - 0x92722C851482353BL, 0xA2BFE8A14CF10364L, 0xA81A664BBC423001L, - 0xC24B8B70D0F89791L, 0xC76C51A30654BE30L, 0xD192E819D6EF5218L, - 0xD69906245565A910L, 0xF40E35855771202AL, 0x106AA07032BBD1B8L, - 0x19A4C116B8D2D0C8L, 0x1E376C085141AB53L, 0x2748774CDF8EEB99L, - 0x34B0BCB5E19B48A8L, 0x391C0CB3C5C95A63L, 0x4ED8AA4AE3418ACBL, - 0x5B9CCA4F7763E373L, 0x682E6FF3D6B2B8A3L, 0x748F82EE5DEFB2FCL, - 0x78A5636F43172F60L, 0x84C87814A1F0AB72L, 0x8CC702081A6439ECL, - 0x90BEFFFA23631E28L, 0xA4506CEBDE82BDE9L, 0xBEF9A3F7B2C67915L, - 0xC67178F2E372532BL, 0xCA273ECEEA26619CL, 0xD186B8C721C0C207L, - 0xEADA7DD6CDE0EB1EL, 0xF57D4F7FEE6ED178L, 0x06F067AA72176FBAL, - 0x0A637DC5A2C898A6L, 0x113F9804BEF90DAEL, 0x1B710B35131C471BL, - 0x28DB77F523047D84L, 0x32CAAB7B40C72493L, 0x3C9EBE0A15C9BEBCL, - 0x431D67C49C100D4CL, 0x4CC5D4BECB3E42B6L, 0x597F299CFC657E2AL, - 0x5FCB6FAB3AD6FAECL, 0x6C44198C4A475817L - }; - - private static long rightRotate(long value, int n) - { - return (value >>> n) | (value << (64 - n)); - } - - private void transform(byte[] m, int offset) - { - long a, b, c, d, e, f, g, h; - long temp1, temp2; - int index; - - // Initialize working variables to the current hash value. - a = this.h[0]; - b = this.h[1]; - c = this.h[2]; - d = this.h[3]; - e = this.h[4]; - f = this.h[5]; - g = this.h[6]; - h = this.h[7]; - - // Convert the 16 input message words from big endian to host byte order. - for (index = 0; index < 16; ++index) { - w[index] = ((m[offset] & 0xFFL) << 56) | - ((m[offset + 1] & 0xFFL) << 48) | - ((m[offset + 2] & 0xFFL) << 40) | - ((m[offset + 3] & 0xFFL) << 32) | - ((m[offset + 4] & 0xFFL) << 24) | - ((m[offset + 5] & 0xFFL) << 16) | - ((m[offset + 6] & 0xFFL) << 8) | - (m[offset + 7] & 0xFFL); - offset += 8; - } - - // Extend the first 16 words to 80. - for (index = 16; index < 80; ++index) { - w[index] = w[index - 16] + w[index - 7] + - (rightRotate(w[index - 15], 1) ^ - rightRotate(w[index - 15], 8) ^ - (w[index - 15] >>> 7)) + - (rightRotate(w[index - 2], 19) ^ - rightRotate(w[index - 2], 61) ^ - (w[index - 2] >>> 6)); - } - - // Compression function main loop. - for (index = 0; index < 80; ++index) { - temp1 = (h) + k[index] + w[index] + - (rightRotate((e), 14) ^ rightRotate((e), 18) ^ rightRotate((e), 41)) + - (((e) & (f)) ^ ((~(e)) & (g))); - temp2 = (rightRotate((a), 28) ^ rightRotate((a), 34) ^ rightRotate((a), 39)) + - (((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c))); - h = g; - g = f; - f = e; - e = d + temp1; - d = c; - c = b; - b = a; - a = temp1 + temp2; - } - - // Add the compressed chunk to the current hash value. - this.h[0] += a; - this.h[1] += b; - this.h[2] += c; - this.h[3] += d; - this.h[4] += e; - this.h[5] += f; - this.h[6] += g; - this.h[7] += h; - } -} diff --git a/src/main/java/com/southernstorm/noise/crypto/package-info.java b/src/main/java/com/southernstorm/noise/crypto/package-info.java deleted file mode 100644 index 8552009a1..000000000 --- a/src/main/java/com/southernstorm/noise/crypto/package-info.java +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * Fallback implementations of cryptographic primitives. - * - * This package provides plain Java implementations of the - * cryptographic primitives that Noise requires which do not - * normally come with standard JDK's. - * - * Applications that use Noise won't normally use these classes - * directly. - */ -package com.southernstorm.noise.crypto; diff --git a/src/main/java/com/southernstorm/noise/protocol/AESGCMFallbackCipherState.java b/src/main/java/com/southernstorm/noise/protocol/AESGCMFallbackCipherState.java deleted file mode 100644 index a7ff0d063..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/AESGCMFallbackCipherState.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import com.southernstorm.noise.crypto.GHASH; -import com.southernstorm.noise.crypto.RijndaelAES; - -import javax.crypto.BadPaddingException; -import javax.crypto.ShortBufferException; -import java.util.Arrays; - -/** - * Fallback implementation of "AESGCM" on platforms where - * the JCA/JCE does not have a suitable GCM or CTR provider. - */ -class AESGCMFallbackCipherState implements CipherState { - - private RijndaelAES aes; - private long n; - private byte[] iv; - private byte[] enciv; - private byte[] hashKey; - private GHASH ghash; - private boolean haskey; - - /** - * Constructs a new cipher state for the "AESGCM" algorithm. - */ - public AESGCMFallbackCipherState() - { - aes = new RijndaelAES(); - n = 0; - iv = new byte [16]; - enciv = new byte [16]; - hashKey = new byte [16]; - ghash = new GHASH(); - haskey = false; - } - - @Override - public void destroy() { - aes.destroy(); - ghash.destroy(); - Noise.destroy(hashKey); - Noise.destroy(iv); - Noise.destroy(enciv); - } - - @Override - public String getCipherName() { - return "AESGCM"; - } - - @Override - public int getKeyLength() { - return 32; - } - - @Override - public int getMACLength() { - return haskey ? 16 : 0; - } - - @Override - public void initializeKey(byte[] key, int offset) { - // Set up the AES key. - aes.setupEnc(key, offset, 256); - haskey = true; - - // Generate the hashing key by encrypting a block of zeroes. - Arrays.fill(hashKey, (byte)0); - aes.encrypt(hashKey, 0, hashKey, 0); - ghash.reset(hashKey, 0); - - // Reset the nonce. - n = 0; - } - - @Override - public boolean hasKey() { - return haskey; - } - - /** - * Set up to encrypt or decrypt the next packet. - * - * @param ad The associated data for the packet. - */ - private void setup(byte[] ad) - { - // Check for nonce wrap-around. - if (n == -1L) - throw new IllegalStateException("Nonce has wrapped around"); - - // Format the counter/IV block. - iv[0] = 0; - iv[1] = 0; - iv[2] = 0; - iv[3] = 0; - iv[4] = (byte)(n >> 56); - iv[5] = (byte)(n >> 48); - iv[6] = (byte)(n >> 40); - iv[7] = (byte)(n >> 32); - iv[8] = (byte)(n >> 24); - iv[9] = (byte)(n >> 16); - iv[10] = (byte)(n >> 8); - iv[11] = (byte)n; - iv[12] = 0; - iv[13] = 0; - iv[14] = 0; - iv[15] = 1; - ++n; - - // Encrypt a block of zeroes to generate the hash key to XOR - // the GHASH tag with at the end of the encrypt/decrypt operation. - Arrays.fill(hashKey, (byte)0); - aes.encrypt(iv, 0, hashKey, 0); - - // Initialize the GHASH with the associated data value. - ghash.reset(); - if (ad != null) { - ghash.update(ad, 0, ad.length); - ghash.pad(); - } - } - - /** - * Encrypts a block in CTR mode. - * - * @param plaintext The plaintext to encrypt. - * @param plaintextOffset Offset of the first plaintext byte. - * @param ciphertext The resulting ciphertext. - * @param ciphertextOffset Offset of the first ciphertext byte. - * @param length The number of bytes to encrypt. - * - * This function can also be used to decrypt. - */ - private void encryptCTR(byte[] plaintext, int plaintextOffset, byte[] ciphertext, int ciphertextOffset, int length) - { - while (length > 0) { - // Increment the IV and encrypt it to get the next keystream block. - if (++(iv[15]) == 0) - if (++(iv[14]) == 0) - if (++(iv[13]) == 0) - ++(iv[12]); - aes.encrypt(iv, 0, enciv, 0); - - // XOR the keystream block with the plaintext to create the ciphertext. - int temp = length; - if (temp > 16) - temp = 16; - for (int index = 0; index < temp; ++index) - ciphertext[ciphertextOffset + index] = (byte)(plaintext[plaintextOffset + index] ^ enciv[index]); - - // Advance to the next block. - plaintextOffset += temp; - ciphertextOffset += temp; - length -= temp; - } - } - - @Override - public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset, - byte[] ciphertext, int ciphertextOffset, int length) - throws ShortBufferException { - int space; - if (ciphertextOffset > ciphertext.length) - space = 0; - else - space = ciphertext.length - ciphertextOffset; - if (!haskey) { - // The key is not set yet - return the plaintext as-is. - if (length > space) - throw new ShortBufferException(); - if (plaintext != ciphertext || plaintextOffset != ciphertextOffset) - System.arraycopy(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length); - return length; - } - if (space < 16 || length > (space - 16)) - throw new ShortBufferException(); - setup(ad); - encryptCTR(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length); - ghash.update(ciphertext, ciphertextOffset, length); - ghash.pad(ad != null ? ad.length : 0, length); - ghash.finish(ciphertext, ciphertextOffset + length, 16); - for (int index = 0; index < 16; ++index) - ciphertext[ciphertextOffset + length + index] ^= hashKey[index]; - return length + 16; - } - - @Override - public int decryptWithAd(byte[] ad, byte[] ciphertext, - int ciphertextOffset, byte[] plaintext, int plaintextOffset, - int length) throws ShortBufferException, BadPaddingException { - int space; - if (ciphertextOffset > ciphertext.length) - space = 0; - else - space = ciphertext.length - ciphertextOffset; - if (length > space) - throw new ShortBufferException(); - if (plaintextOffset > plaintext.length) - space = 0; - else - space = plaintext.length - plaintextOffset; - if (!haskey) { - // The key is not set yet - return the ciphertext as-is. - if (length > space) - throw new ShortBufferException(); - if (plaintext != ciphertext || plaintextOffset != ciphertextOffset) - System.arraycopy(ciphertext, ciphertextOffset, plaintext, plaintextOffset, length); - return length; - } - if (length < 16) - Noise.throwBadTagException(); - int dataLen = length - 16; - if (dataLen > space) - throw new ShortBufferException(); - setup(ad); - ghash.update(ciphertext, ciphertextOffset, dataLen); - ghash.pad(ad != null ? ad.length : 0, dataLen); - ghash.finish(enciv, 0, 16); - int temp = 0; - for (int index = 0; index < 16; ++index) - temp |= (hashKey[index] ^ enciv[index] ^ ciphertext[ciphertextOffset + dataLen + index]); - if ((temp & 0xFF) != 0) - Noise.throwBadTagException(); - encryptCTR(ciphertext, ciphertextOffset, plaintext, plaintextOffset, dataLen); - return dataLen; - } - - @Override - public CipherState fork(byte[] key, int offset) { - CipherState cipher; - cipher = new AESGCMFallbackCipherState(); - cipher.initializeKey(key, offset); - return cipher; - } - - @Override - public void setNonce(long nonce) { - n = nonce; - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/AESGCMOnCtrCipherState.java b/src/main/java/com/southernstorm/noise/protocol/AESGCMOnCtrCipherState.java deleted file mode 100644 index 986672e0d..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/AESGCMOnCtrCipherState.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import com.southernstorm.noise.crypto.GHASH; - -import javax.crypto.*; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -/** - * Emulates the "AESGCM" cipher for Noise using the "AES/CTR/NoPadding" - * transformation from JCA/JCE. - * - * This class is used on platforms that don't have "AES/GCM/NoPadding", - * but which do have the older "AES/CTR/NoPadding". - */ -class AESGCMOnCtrCipherState implements CipherState { - - private Cipher cipher; - private SecretKeySpec keySpec; - private long n; - private byte[] iv; - private byte[] hashKey; - private GHASH ghash; - - /** - * Constructs a new cipher state for the "AESGCM" algorithm. - * - * @throws NoSuchAlgorithmException The system does not have a - * provider for this algorithm. - */ - public AESGCMOnCtrCipherState() throws NoSuchAlgorithmException - { - try { - cipher = Cipher.getInstance("AES/CTR/NoPadding"); - } catch (NoSuchPaddingException e) { - // AES/CTR is available, but not the unpadded version? Huh? - throw new NoSuchAlgorithmException("AES/CTR/NoPadding not available", e); - } - keySpec = null; - n = 0; - iv = new byte [16]; - hashKey = new byte [16]; - ghash = new GHASH(); - - // Try to set a 256-bit key on the cipher. Some JCE's are - // configured to disallow 256-bit AES if an extra policy - // file has not been installed. - try { - SecretKeySpec spec = new SecretKeySpec(new byte [32], "AES"); - IvParameterSpec params = new IvParameterSpec(iv); - cipher.init(Cipher.ENCRYPT_MODE, spec, params); - } catch (InvalidKeyException e) { - throw new NoSuchAlgorithmException("AES/CTR/NoPadding does not support 256-bit keys", e); - } catch (InvalidAlgorithmParameterException e) { - throw new NoSuchAlgorithmException("AES/CTR/NoPadding does not support 256-bit keys", e); - } - } - - @Override - public void destroy() { - // There doesn't seem to be a standard API to clean out a Cipher. - // So we instead set the key and IV to all-zeroes to hopefully - // destroy the sensitive data in the cipher instance. - ghash.destroy(); - Noise.destroy(hashKey); - Noise.destroy(iv); - keySpec = new SecretKeySpec(new byte [32], "AES"); - IvParameterSpec params = new IvParameterSpec(iv); - try { - cipher.init(Cipher.ENCRYPT_MODE, keySpec, params); - } catch (InvalidKeyException e) { - // Shouldn't happen. - } catch (InvalidAlgorithmParameterException e) { - // Shouldn't happen. - } - } - - @Override - public String getCipherName() { - return "AESGCM"; - } - - @Override - public int getKeyLength() { - return 32; - } - - @Override - public int getMACLength() { - return keySpec != null ? 16 : 0; - } - - @Override - public void initializeKey(byte[] key, int offset) { - // Set the encryption key. - keySpec = new SecretKeySpec(key, offset, 32, "AES"); - - // Generate the hashing key by encrypting a block of zeroes. - Arrays.fill(iv, (byte)0); - Arrays.fill(hashKey, (byte)0); - try { - cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); - } catch (InvalidKeyException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } catch (InvalidAlgorithmParameterException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } - try { - int result = cipher.update(hashKey, 0, 16, hashKey, 0); - cipher.doFinal(hashKey, result); - } catch (ShortBufferException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } catch (IllegalBlockSizeException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } catch (BadPaddingException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } - ghash.reset(hashKey, 0); - - // Reset the nonce. - n = 0; - } - - @Override - public boolean hasKey() { - return keySpec != null; - } - - /** - * Set up to encrypt or decrypt the next packet. - * - * @param ad The associated data for the packet. - */ - private void setup(byte[] ad) throws InvalidKeyException, InvalidAlgorithmParameterException - { - // Check for nonce wrap-around. - if (n == -1L) - throw new IllegalStateException("Nonce has wrapped around"); - - // Format the counter/IV block for AES/CTR/NoPadding. - iv[0] = 0; - iv[1] = 0; - iv[2] = 0; - iv[3] = 0; - iv[4] = (byte)(n >> 56); - iv[5] = (byte)(n >> 48); - iv[6] = (byte)(n >> 40); - iv[7] = (byte)(n >> 32); - iv[8] = (byte)(n >> 24); - iv[9] = (byte)(n >> 16); - iv[10] = (byte)(n >> 8); - iv[11] = (byte)n; - iv[12] = 0; - iv[13] = 0; - iv[14] = 0; - iv[15] = 1; - ++n; - - // Initialize the CTR mode cipher with the key and IV. - cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); - - // Encrypt a block of zeroes to generate the hash key to XOR - // the GHASH tag with at the end of the encrypt/decrypt operation. - Arrays.fill(hashKey, (byte)0); - try { - cipher.update(hashKey, 0, 16, hashKey, 0); - } catch (ShortBufferException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } - - // Initialize the GHASH with the associated data value. - ghash.reset(); - if (ad != null) { - ghash.update(ad, 0, ad.length); - ghash.pad(); - } - } - - @Override - public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset, - byte[] ciphertext, int ciphertextOffset, int length) - throws ShortBufferException { - int space; - if (ciphertextOffset > ciphertext.length) - space = 0; - else - space = ciphertext.length - ciphertextOffset; - if (keySpec == null) { - // The key is not set yet - return the plaintext as-is. - if (length > space) - throw new ShortBufferException(); - if (plaintext != ciphertext || plaintextOffset != ciphertextOffset) - System.arraycopy(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length); - return length; - } - if (space < 16 || length > (space - 16)) - throw new ShortBufferException(); - try { - setup(ad); - int result = cipher.update(plaintext, plaintextOffset, length, ciphertext, ciphertextOffset); - cipher.doFinal(ciphertext, ciphertextOffset + result); - } catch (InvalidKeyException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } catch (InvalidAlgorithmParameterException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } catch (IllegalBlockSizeException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } catch (BadPaddingException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } - ghash.update(ciphertext, ciphertextOffset, length); - ghash.pad(ad != null ? ad.length : 0, length); - ghash.finish(ciphertext, ciphertextOffset + length, 16); - for (int index = 0; index < 16; ++index) - ciphertext[ciphertextOffset + length + index] ^= hashKey[index]; - return length + 16; - } - - @Override - public int decryptWithAd(byte[] ad, byte[] ciphertext, - int ciphertextOffset, byte[] plaintext, int plaintextOffset, - int length) throws ShortBufferException, BadPaddingException { - int space; - if (ciphertextOffset > ciphertext.length) - space = 0; - else - space = ciphertext.length - ciphertextOffset; - if (length > space) - throw new ShortBufferException(); - if (plaintextOffset > plaintext.length) - space = 0; - else - space = plaintext.length - plaintextOffset; - if (keySpec == null) { - // The key is not set yet - return the ciphertext as-is. - if (length > space) - throw new ShortBufferException(); - if (plaintext != ciphertext || plaintextOffset != ciphertextOffset) - System.arraycopy(ciphertext, ciphertextOffset, plaintext, plaintextOffset, length); - return length; - } - if (length < 16) - Noise.throwBadTagException(); - int dataLen = length - 16; - if (dataLen > space) - throw new ShortBufferException(); - try { - setup(ad); - } catch (InvalidKeyException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } catch (InvalidAlgorithmParameterException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } - ghash.update(ciphertext, ciphertextOffset, dataLen); - ghash.pad(ad != null ? ad.length : 0, dataLen); - ghash.finish(iv, 0, 16); - int temp = 0; - for (int index = 0; index < 16; ++index) - temp |= (hashKey[index] ^ iv[index] ^ ciphertext[ciphertextOffset + dataLen + index]); - if ((temp & 0xFF) != 0) - Noise.throwBadTagException(); - try { - int result = cipher.update(ciphertext, ciphertextOffset, dataLen, plaintext, plaintextOffset); - cipher.doFinal(plaintext, plaintextOffset + result); - } catch (IllegalBlockSizeException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } catch (BadPaddingException e) { - // Shouldn't happen. - throw new IllegalStateException(e); - } - return dataLen; - } - - @Override - public CipherState fork(byte[] key, int offset) { - CipherState cipher; - try { - cipher = new AESGCMOnCtrCipherState(); - } catch (NoSuchAlgorithmException e) { - // Shouldn't happen. - return null; - } - cipher.initializeKey(key, offset); - return cipher; - } - - @Override - public void setNonce(long nonce) { - n = nonce; - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/ChaChaPolyCipherState.java b/src/main/java/com/southernstorm/noise/protocol/ChaChaPolyCipherState.java deleted file mode 100644 index 47563e2d8..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/ChaChaPolyCipherState.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import com.southernstorm.noise.crypto.ChaChaCore; -import com.southernstorm.noise.crypto.Poly1305; - -import javax.crypto.BadPaddingException; -import javax.crypto.ShortBufferException; -import java.util.Arrays; - -/** - * Implements the ChaChaPoly cipher for Noise. - */ -class ChaChaPolyCipherState implements CipherState { - - private Poly1305 poly; - private int[] input; - private int[] output; - private byte[] polyKey; - long n; - private boolean haskey; - - /** - * Constructs a new cipher state for the "ChaChaPoly" algorithm. - */ - public ChaChaPolyCipherState() - { - poly = new Poly1305(); - input = new int [16]; - output = new int [16]; - polyKey = new byte [32]; - n = 0; - haskey = false; - } - - @Override - public void destroy() { - poly.destroy(); - Arrays.fill(input, 0); - Arrays.fill(output, 0); - Noise.destroy(polyKey); - } - - @Override - public String getCipherName() { - return "ChaChaPoly"; - } - - @Override - public int getKeyLength() { - return 32; - } - - @Override - public int getMACLength() { - return haskey ? 16 : 0; - } - - @Override - public void initializeKey(byte[] key, int offset) { - ChaChaCore.initKey256(input, key, offset); - n = 0; - haskey = true; - } - - @Override - public boolean hasKey() { - return haskey; - } - - /** - * XOR's the output of ChaCha20 with a byte buffer. - * - * @param input The input byte buffer. - * @param inputOffset The offset of the first input byte. - * @param output The output byte buffer (can be the same as the input). - * @param outputOffset The offset of the first output byte. - * @param length The number of bytes to XOR between 1 and 64. - * @param block The ChaCha20 output block. - */ - private static void xorBlock(byte[] input, int inputOffset, byte[] output, int outputOffset, int length, int[] block) - { - int posn = 0; - int value; - while (length >= 4) { - value = block[posn++]; - output[outputOffset] = (byte)(input[inputOffset] ^ value); - output[outputOffset + 1] = (byte)(input[inputOffset + 1] ^ (value >> 8)); - output[outputOffset + 2] = (byte)(input[inputOffset + 2] ^ (value >> 16)); - output[outputOffset + 3] = (byte)(input[inputOffset + 3] ^ (value >> 24)); - inputOffset += 4; - outputOffset += 4; - length -= 4; - } - if (length == 3) { - value = block[posn]; - output[outputOffset] = (byte)(input[inputOffset] ^ value); - output[outputOffset + 1] = (byte)(input[inputOffset + 1] ^ (value >> 8)); - output[outputOffset + 2] = (byte)(input[inputOffset + 2] ^ (value >> 16)); - } else if (length == 2) { - value = block[posn]; - output[outputOffset] = (byte)(input[inputOffset] ^ value); - output[outputOffset + 1] = (byte)(input[inputOffset + 1] ^ (value >> 8)); - } else if (length == 1) { - value = block[posn]; - output[outputOffset] = (byte)(input[inputOffset] ^ value); - } - } - - /** - * Set up to encrypt or decrypt the next packet. - * - * @param ad The associated data for the packet. - */ - private void setup(byte[] ad) - { - if (n == -1L) - throw new IllegalStateException("Nonce has wrapped around"); - ChaChaCore.initIV(input, n++); - ChaChaCore.hash(output, input); - Arrays.fill(polyKey, (byte)0); - xorBlock(polyKey, 0, polyKey, 0, 32, output); - poly.reset(polyKey, 0); - if (ad != null) { - poly.update(ad, 0, ad.length); - poly.pad(); - } - if (++(input[12]) == 0) - ++(input[13]); - } - - /** - * Puts a 64-bit integer into a buffer in little-endian order. - * - * @param output The output buffer. - * @param offset The offset into the output buffer. - * @param value The 64-bit integer value. - */ - private static void putLittleEndian64(byte[] output, int offset, long value) - { - output[offset] = (byte)value; - output[offset + 1] = (byte)(value >> 8); - output[offset + 2] = (byte)(value >> 16); - output[offset + 3] = (byte)(value >> 24); - output[offset + 4] = (byte)(value >> 32); - output[offset + 5] = (byte)(value >> 40); - output[offset + 6] = (byte)(value >> 48); - output[offset + 7] = (byte)(value >> 56); - } - - /** - * Finishes up the authentication tag for a packet. - * - * @param ad The associated data. - * @param length The length of the plaintext data. - */ - private void finish(byte[] ad, int length) - { - poly.pad(); - putLittleEndian64(polyKey, 0, ad != null ? ad.length : 0); - putLittleEndian64(polyKey, 8, length); - poly.update(polyKey, 0, 16); - poly.finish(polyKey, 0); - } - - /** - * Encrypts or decrypts a buffer of bytes for the active packet. - * - * @param plaintext The plaintext data to be encrypted. - * @param plaintextOffset The offset to the first plaintext byte. - * @param ciphertext The ciphertext data that results from encryption. - * @param ciphertextOffset The offset to the first ciphertext byte. - * @param length The number of bytes to encrypt. - */ - private void encrypt(byte[] plaintext, int plaintextOffset, - byte[] ciphertext, int ciphertextOffset, int length) { - while (length > 0) { - int tempLen = 64; - if (tempLen > length) - tempLen = length; - ChaChaCore.hash(output, input); - xorBlock(plaintext, plaintextOffset, ciphertext, ciphertextOffset, tempLen, output); - if (++(input[12]) == 0) - ++(input[13]); - plaintextOffset += tempLen; - ciphertextOffset += tempLen; - length -= tempLen; - } - } - - @Override - public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset, - byte[] ciphertext, int ciphertextOffset, int length) throws ShortBufferException { - int space; - if (ciphertextOffset > ciphertext.length) - space = 0; - else - space = ciphertext.length - ciphertextOffset; - if (!haskey) { - // The key is not set yet - return the plaintext as-is. - if (length > space) - throw new ShortBufferException(); - if (plaintext != ciphertext || plaintextOffset != ciphertextOffset) - System.arraycopy(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length); - return length; - } - if (space < 16 || length > (space - 16)) - throw new ShortBufferException(); - setup(ad); - encrypt(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length); - poly.update(ciphertext, ciphertextOffset, length); - finish(ad, length); - System.arraycopy(polyKey, 0, ciphertext, ciphertextOffset + length, 16); - return length + 16; - } - - @Override - public int decryptWithAd(byte[] ad, byte[] ciphertext, - int ciphertextOffset, byte[] plaintext, int plaintextOffset, - int length) throws ShortBufferException, BadPaddingException { - int space; - if (ciphertextOffset > ciphertext.length) - space = 0; - else - space = ciphertext.length - ciphertextOffset; - if (length > space) - throw new ShortBufferException(); - if (plaintextOffset > plaintext.length) - space = 0; - else - space = plaintext.length - plaintextOffset; - if (!haskey) { - // The key is not set yet - return the ciphertext as-is. - if (length > space) - throw new ShortBufferException(); - if (plaintext != ciphertext || plaintextOffset != ciphertextOffset) - System.arraycopy(ciphertext, ciphertextOffset, plaintext, plaintextOffset, length); - return length; - } - if (length < 16) - Noise.throwBadTagException(); - int dataLen = length - 16; - if (dataLen > space) - throw new ShortBufferException(); - setup(ad); - poly.update(ciphertext, ciphertextOffset, dataLen); - finish(ad, dataLen); - int temp = 0; - for (int index = 0; index < 16; ++index) - temp |= (polyKey[index] ^ ciphertext[ciphertextOffset + dataLen + index]); - if ((temp & 0xFF) != 0) - Noise.throwBadTagException(); - encrypt(ciphertext, ciphertextOffset, plaintext, plaintextOffset, dataLen); - return dataLen; - } - - @Override - public CipherState fork(byte[] key, int offset) { - CipherState cipher = new ChaChaPolyCipherState(); - cipher.initializeKey(key, offset); - return cipher; - } - - @Override - public void setNonce(long nonce) { - n = nonce; - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/CipherState.java b/src/main/java/com/southernstorm/noise/protocol/CipherState.java deleted file mode 100644 index 3168139f4..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/CipherState.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import javax.crypto.BadPaddingException; -import javax.crypto.ShortBufferException; - -/** - * Interface to an authenticated cipher for use in the Noise protocol. - * - * CipherState objects are used to encrypt or decrypt data during a - * session. Once the handshake has completed, HandshakeState.split() - * will create two CipherState objects for encrypting packets sent to - * the other party, and decrypting packets received from the other party. - */ -public interface CipherState extends Destroyable { - - /** - * Gets the Noise protocol name for this cipher. - * - * @return The cipher name. - */ - String getCipherName(); - - /** - * Gets the length of the key values for this cipher. - * - * @return The length of the key in bytes; usually 32. - */ - int getKeyLength(); - - /** - * Gets the length of the MAC values for this cipher. - * - * @return The length of MAC values in bytes, or zero if the - * key has not yet been initialized. - */ - int getMACLength(); - - /** - * Initializes the key on this cipher object. - * - * @param key Points to a buffer that contains the key. - * @param offset The offset of the key in the key buffer. - * - * The key buffer must contain at least getKeyLength() bytes - * starting at offset. - * - * @see #hasKey() - */ - void initializeKey(byte[] key, int offset); - - /** - * Determine if this cipher object has been configured with a key. - * - * @return true if this cipher object has a key; false if the - * key has not yet been set with initializeKey(). - * - * @see #initializeKey(byte[], int) - */ - boolean hasKey(); - - /** - * Encrypts a plaintext buffer using the cipher and a block of associated data. - * - * @param ad The associated data, or null if there is none. - * @param plaintext The buffer containing the plaintext to encrypt. - * @param plaintextOffset The offset within the plaintext buffer of the - * first byte or plaintext data. - * @param ciphertext The buffer to place the ciphertext in. This can - * be the same as the plaintext buffer. - * @param ciphertextOffset The first offset within the ciphertext buffer - * to place the ciphertext and the MAC tag. - * @param length The length of the plaintext. - * @return The length of the ciphertext plus the MAC tag, or -1 if the - * ciphertext buffer is not large enough to hold the result. - * - * @throws ShortBufferException The ciphertext buffer does not have - * enough space to hold the ciphertext plus MAC. - * - * @throws IllegalStateException The nonce has wrapped around. - * - * The plaintext and ciphertext buffers can be the same for in-place - * encryption. In that case, plaintextOffset must be identical to - * ciphertextOffset. - * - * There must be enough space in the ciphertext buffer to accomodate - * length + getMACLength() bytes of data starting at ciphertextOffset. - */ - int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset, byte[] ciphertext, int ciphertextOffset, int length) throws ShortBufferException; - - /** - * Decrypts a ciphertext buffer using the cipher and a block of associated data. - * - * @param ad The associated data, or null if there is none. - * @param ciphertext The buffer containing the ciphertext to decrypt. - * @param ciphertextOffset The offset within the ciphertext buffer of - * the first byte of ciphertext data. - * @param plaintext The buffer to place the plaintext in. This can be - * the same as the ciphertext buffer. - * @param plaintextOffset The first offset within the plaintext buffer - * to place the plaintext. - * @param length The length of the incoming ciphertext plus the MAC tag. - * @return The length of the plaintext with the MAC tag stripped off. - * - * @throws ShortBufferException The plaintext buffer does not have - * enough space to store the decrypted data. - * - * @throws BadPaddingException The MAC value failed to verify. - * - * @throws IllegalStateException The nonce has wrapped around. - * - * The plaintext and ciphertext buffers can be the same for in-place - * decryption. In that case, ciphertextOffset must be identical to - * plaintextOffset. - */ - int decryptWithAd(byte[] ad, byte[] ciphertext, int ciphertextOffset, byte[] plaintext, int plaintextOffset, int length) throws ShortBufferException, BadPaddingException; - - /** - * Creates a new instance of this cipher and initializes it with a key. - * - * @param key The buffer containing the key. - * @param offset The offset into the key buffer of the first key byte. - * @return A new CipherState of the same class as this one. - */ - CipherState fork(byte[] key, int offset); - - /** - * Sets the nonce value. - * - * @param nonce The new nonce value, which must be greater than or equal - * to the current value. - * - * This function is intended for testing purposes only. If the nonce - * value goes backwards then security may be compromised. - */ - void setNonce(long nonce); -} diff --git a/src/main/java/com/southernstorm/noise/protocol/CipherStatePair.java b/src/main/java/com/southernstorm/noise/protocol/CipherStatePair.java deleted file mode 100644 index 8ec07f29b..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/CipherStatePair.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -/** - * Class that contains a pair of CipherState objects. - * - * CipherState pairs typically arise when HandshakeState.split() is called. - */ -public final class CipherStatePair implements Destroyable { - - private CipherState send; - private CipherState recv; - - /** - * Constructs a pair of CipherState objects. - * - * @param sender The CipherState to use to send packets to the remote party. - * @param receiver The CipherState to use to receive packets from the remote party. - */ - public CipherStatePair(CipherState sender, CipherState receiver) - { - send = sender; - recv = receiver; - } - - /** - * Gets the CipherState to use to send packets to the remote party. - * - * @return The sending CipherState. - */ - public CipherState getSender() { - return send; - } - - /** - * Gets the CipherState to use to receive packets from the remote party. - * - * @return The receiving CipherState. - */ - public CipherState getReceiver() { - return recv; - } - - /** - * Destroys the receiving CipherState and retains only the sending CipherState. - * - * This function is intended for use with one-way handshake patterns. - */ - public void senderOnly() - { - if (recv != null) { - recv.destroy(); - recv = null; - } - } - - /** - * Destroys the sending CipherState and retains only the receiving CipherState. - * - * This function is intended for use with one-way handshake patterns. - */ - public void receiverOnly() - { - if (send != null) { - send.destroy(); - send = null; - } - } - - /** - * Swaps the sender and receiver. - */ - public void swap() - { - CipherState temp = send; - send = recv; - recv = temp; - } - - @Override - public void destroy() { - senderOnly(); - receiverOnly(); - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/Curve25519DHState.java b/src/main/java/com/southernstorm/noise/protocol/Curve25519DHState.java deleted file mode 100644 index 9fd421d70..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/Curve25519DHState.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import com.southernstorm.noise.crypto.Curve25519; - -import java.util.Arrays; - -/** - * Implementation of the Curve25519 algorithm for the Noise protocol. - */ -class Curve25519DHState implements DHState { - - private byte[] publicKey; - private byte[] privateKey; - private int mode; - - /** - * Constructs a new Diffie-Hellman object for Curve25519. - */ - public Curve25519DHState() - { - publicKey = new byte [32]; - privateKey = new byte [32]; - mode = 0; - } - - @Override - public void destroy() { - clearKey(); - } - - @Override - public String getDHName() { - return "25519"; - } - - @Override - public int getPublicKeyLength() { - return 32; - } - - @Override - public int getPrivateKeyLength() { - return 32; - } - - @Override - public int getSharedKeyLength() { - return 32; - } - - @Override - public void generateKeyPair() { - Noise.random(privateKey); - Curve25519.eval(publicKey, 0, privateKey, null); - mode = 0x03; - } - - @Override - public void getPublicKey(byte[] key, int offset) { - System.arraycopy(publicKey, 0, key, offset, 32); - } - - @Override - public void setPublicKey(byte[] key, int offset) { - System.arraycopy(key, offset, publicKey, 0, 32); - Arrays.fill(privateKey, (byte)0); - mode = 0x01; - } - - @Override - public void getPrivateKey(byte[] key, int offset) { - System.arraycopy(privateKey, 0, key, offset, 32); - } - - @Override - public void setPrivateKey(byte[] key, int offset) { - System.arraycopy(key, offset, privateKey, 0, 32); - Curve25519.eval(publicKey, 0, privateKey, null); - mode = 0x03; - } - - @Override - public void setToNullPublicKey() { - Arrays.fill(publicKey, (byte)0); - Arrays.fill(privateKey, (byte)0); - mode = 0x01; - } - - @Override - public void clearKey() { - Noise.destroy(publicKey); - Noise.destroy(privateKey); - mode = 0; - } - - @Override - public boolean hasPublicKey() { - return (mode & 0x01) != 0; - } - - @Override - public boolean hasPrivateKey() { - return (mode & 0x02) != 0; - } - - @Override - public boolean isNullPublicKey() { - if ((mode & 0x01) == 0) - return false; - int temp = 0; - for (int index = 0; index < 32; ++index) - temp |= publicKey[index]; - return temp == 0; - } - - @Override - public void calculate(byte[] sharedKey, int offset, DHState publicDH) { - if (!(publicDH instanceof Curve25519DHState)) - throw new IllegalArgumentException("Incompatible DH algorithms"); - Curve25519.eval(sharedKey, offset, privateKey, ((Curve25519DHState)publicDH).publicKey); - } - - @Override - public void copyFrom(DHState other) { - if (!(other instanceof Curve25519DHState)) - throw new IllegalStateException("Mismatched DH key objects"); - if (other == this) - return; - Curve25519DHState dh = (Curve25519DHState)other; - System.arraycopy(dh.privateKey, 0, privateKey, 0, 32); - System.arraycopy(dh.publicKey, 0, publicKey, 0, 32); - mode = dh.mode; - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/Curve448DHState.java b/src/main/java/com/southernstorm/noise/protocol/Curve448DHState.java deleted file mode 100644 index bad26abad..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/Curve448DHState.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import com.southernstorm.noise.crypto.Curve448; - -import java.util.Arrays; - -/** - * Implementation of the Curve448 algorithm for the Noise protocol. - */ -class Curve448DHState implements DHState { - - private byte[] publicKey; - private byte[] privateKey; - private int mode; - - /** - * Constructs a new Diffie-Hellman object for Curve448. - */ - public Curve448DHState() - { - publicKey = new byte [56]; - privateKey = new byte [56]; - mode = 0; - } - - @Override - public void destroy() { - clearKey(); - } - - @Override - public String getDHName() { - return "448"; - } - - @Override - public int getPublicKeyLength() { - return 56; - } - - @Override - public int getPrivateKeyLength() { - return 56; - } - - @Override - public int getSharedKeyLength() { - return 56; - } - - @Override - public void generateKeyPair() { - Noise.random(privateKey); - Curve448.eval(publicKey, 0, privateKey, null); - mode = 0x03; - } - - @Override - public void getPublicKey(byte[] key, int offset) { - System.arraycopy(publicKey, 0, key, offset, 56); - } - - @Override - public void setPublicKey(byte[] key, int offset) { - System.arraycopy(key, offset, publicKey, 0, 56); - Arrays.fill(privateKey, (byte)0); - mode = 0x01; - } - - @Override - public void getPrivateKey(byte[] key, int offset) { - System.arraycopy(privateKey, 0, key, offset, 56); - } - - @Override - public void setPrivateKey(byte[] key, int offset) { - System.arraycopy(key, offset, privateKey, 0, 56); - Curve448.eval(publicKey, 0, privateKey, null); - mode = 0x03; - } - - @Override - public void setToNullPublicKey() { - Arrays.fill(publicKey, (byte)0); - Arrays.fill(privateKey, (byte)0); - mode = 0x01; - } - - @Override - public void clearKey() { - Noise.destroy(publicKey); - Noise.destroy(privateKey); - mode = 0; - } - - @Override - public boolean hasPublicKey() { - return (mode & 0x01) != 0; - } - - @Override - public boolean hasPrivateKey() { - return (mode & 0x02) != 0; - } - - @Override - public boolean isNullPublicKey() { - if ((mode & 0x01) == 0) - return false; - int temp = 0; - for (int index = 0; index < 56; ++index) - temp |= publicKey[index]; - return temp == 0; - } - - @Override - public void calculate(byte[] sharedKey, int offset, DHState publicDH) { - if (!(publicDH instanceof Curve448DHState)) - throw new IllegalArgumentException("Incompatible DH algorithms"); - Curve448.eval(sharedKey, offset, privateKey, ((Curve448DHState)publicDH).publicKey); - } - - @Override - public void copyFrom(DHState other) { - if (!(other instanceof Curve448DHState)) - throw new IllegalStateException("Mismatched DH key objects"); - if (other == this) - return; - Curve448DHState dh = (Curve448DHState)other; - System.arraycopy(dh.privateKey, 0, privateKey, 0, 56); - System.arraycopy(dh.publicKey, 0, publicKey, 0, 56); - mode = dh.mode; - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/DHState.java b/src/main/java/com/southernstorm/noise/protocol/DHState.java deleted file mode 100644 index 6e997c602..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/DHState.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -/** - * Interface to a Diffie-Hellman algorithm for the Noise protocol. - */ -public interface DHState extends Destroyable { - - /** - * Gets the Noise protocol name for this Diffie-Hellman algorithm. - * - * @return The algorithm name. - */ - String getDHName(); - - /** - * Gets the length of public keys for this algorithm. - * - * @return The length of public keys in bytes. - */ - int getPublicKeyLength(); - - /** - * Gets the length of private keys for this algorithm. - * - * @return The length of private keys in bytes. - */ - int getPrivateKeyLength(); - - /** - * Gets the length of shared keys for this algorithm. - * - * @return The length of shared keys in bytes. - */ - int getSharedKeyLength(); - - /** - * Generates a new random keypair. - */ - void generateKeyPair(); - - /** - * Gets the public key associated with this object. - * - * @param key The buffer to copy the public key to. - * @param offset The first offset in the key buffer to copy to. - */ - void getPublicKey(byte[] key, int offset); - - /** - * Sets the public key for this object. - * - * @param key The buffer containing the public key. - * @param offset The first offset in the buffer that contains the key. - * - * If this object previously held a key pair, then this function - * will change it into a public key only object. - */ - void setPublicKey(byte[] key, int offset); - - /** - * Gets the private key associated with this object. - * - * @param key The buffer to copy the private key to. - * @param offset The first offset in the key buffer to copy to. - */ - void getPrivateKey(byte[] key, int offset); - - /** - * Sets the private key for this object. - * - * @param key The buffer containing the [rivate key. - * @param offset The first offset in the buffer that contains the key. - * - * If this object previously held only a public key, then - * this function will change it into a key pair. - */ - void setPrivateKey(byte[] key, int offset); - - /** - * Sets this object to the null public key and clears the private key. - */ - void setToNullPublicKey(); - - /** - * Clears the key pair. - */ - void clearKey(); - - /** - * Determine if this object contains a public key. - * - * @return Returns true if this object contains a public key, - * or false if the public key has not yet been set. - */ - boolean hasPublicKey(); - - /** - * Determine if this object contains a private key. - * - * @return Returns true if this object contains a private key, - * or false if the private key has not yet been set. - */ - boolean hasPrivateKey(); - - /** - * Determine if the public key in this object is the special null value. - * - * @return Returns true if the public key is the special null value, - * or false otherwise. - */ - boolean isNullPublicKey(); - - /** - * Performs a Diffie-Hellman calculation with this object as the private key. - * - * @param sharedKey Buffer to put the shared key into. - * @param offset Offset of the first byte for the shared key. - * @param publicDH Object that contains the public key for the calculation. - * - * @throws IllegalArgumentException The publicDH object is not the same - * type as this object, or one of the objects does not contain a valid key. - */ - void calculate(byte[] sharedKey, int offset, DHState publicDH); - - /** - * Copies the key values from another DH object of the same type. - * - * @param other The other DH object to copy from - * - * @throws IllegalStateException The other DH object does not have - * the same type as this object. - */ - void copyFrom(DHState other); -} diff --git a/src/main/java/com/southernstorm/noise/protocol/DHStateHybrid.java b/src/main/java/com/southernstorm/noise/protocol/DHStateHybrid.java deleted file mode 100644 index 34321edbb..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/DHStateHybrid.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -/** - * Additional API for DH objects that need special handling for - * hybrid operations. - */ -public interface DHStateHybrid extends DHState { - - /** - * Generates a new random keypair relative to the parameters - * in another object. - * - * @param remote The remote party in this communication to obtain parameters. - * - * @throws IllegalStateException The other or remote DH object does not have - * the same type as this object. - */ - void generateKeyPair(DHState remote); - - /** - * Copies the key values from another DH object of the same type. - * - * @param other The other DH object to copy from - * @param remote The remote party in this communication to obtain parameters. - * - * @throws IllegalStateException The other or remote DH object does not have - * the same type as this object. - */ - void copyFrom(DHState other, DHState remote); - - /** - * Specifies the local peer object prior to setting a public key - * on a remote object. - * - * @param local The local peer object. - */ - void specifyPeer(DHState local); -} diff --git a/src/main/java/com/southernstorm/noise/protocol/Destroyable.java b/src/main/java/com/southernstorm/noise/protocol/Destroyable.java deleted file mode 100644 index 17785ed22..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/Destroyable.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -/** - * Interface for objects that implement destroying. - * - * Applications that use the Noise protocol can inadvertently leave - * sensitive data in the heap if steps are not taken to clean up. - * - * This interface can be implemented by objects that know how to - * securely clean up after themselves. - * - * The Noise.destroy() function can help with destroying byte arrays - * that hold sensitive values. - */ -public interface Destroyable { - - /** - * Destroys all sensitive state in the current object. - */ - void destroy(); -} diff --git a/src/main/java/com/southernstorm/noise/protocol/HandshakeState.java b/src/main/java/com/southernstorm/noise/protocol/HandshakeState.java deleted file mode 100644 index cb8e2b0c8..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/HandshakeState.java +++ /dev/null @@ -1,1259 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import javax.crypto.BadPaddingException; -import javax.crypto.ShortBufferException; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -/** - * Interface to a Noise handshake. - */ -public class HandshakeState implements Destroyable { - - private SymmetricState symmetric; - private boolean isInitiator; - private DHState localKeyPair; - private DHState localEphemeral; - private DHState localHybrid; - private DHState remotePublicKey; - private DHState remoteEphemeral; - private DHState remoteHybrid; - private DHState fixedEphemeral; - private DHState fixedHybrid; - private int action; - private int requirements; - private short[] pattern; - private int patternIndex; - private byte[] preSharedKey; - private byte[] prologue; - - /** - * Enumerated value that indicates that the handshake object - * is handling the initiator role. - */ - public static final int INITIATOR = 1; - - /** - * Enumerated value that indicates that the handshake object - * is handling the responder role. - */ - public static final int RESPONDER = 2; - - /** - * No action is required of the application yet because the - * handshake has not started. - */ - public static final int NO_ACTION = 0; - - /** - * The HandshakeState expects the application to write the - * next message payload for the handshake. - */ - public static final int WRITE_MESSAGE = 1; - - /** - * The HandshakeState expects the application to read the - * next message payload from the handshake. - */ - public static final int READ_MESSAGE = 2; - - /** - * The handshake has failed due to some kind of error. - */ - public static final int FAILED = 3; - - /** - * The handshake is over and the application is expected to call - * split() and begin data session communications. - */ - public static final int SPLIT = 4; - - /** - * The handshake is complete and the data session ciphers - * have been split() out successfully. - */ - public static final int COMPLETE = 5; - - /** - * Local static keypair is required for the handshake. - */ - private static final int LOCAL_REQUIRED = 0x01; - - /** - * Remote static keypai is required for the handshake. - */ - private static final int REMOTE_REQUIRED = 0x02; - - /** - * Pre-shared key is required for the handshake. - */ - private static final int PSK_REQUIRED = 0x04; - - /** - * Ephemeral key for fallback pre-message has been provided. - */ - private static final int FALLBACK_PREMSG = 0x08; - - /** - * The local public key is part of the pre-message. - */ - private static final int LOCAL_PREMSG = 0x10; - - /** - * The remote public key is part of the pre-message. - */ - private static final int REMOTE_PREMSG = 0x20; - - /** - * Fallback is possible from this pattern (two-way, ends in "K"). - */ - private static final int FALLBACK_POSSIBLE = 0x40; - - /** - * Creates a new Noise handshake. - * - * @param protocolName The name of the Noise protocol. - * @param role The role, HandshakeState.INITIATOR or HandshakeState.RESPONDER. - * - * @throws IllegalArgumentException The protocolName is not - * formatted correctly, or the role is not recognized. - * - * @throws NoSuchAlgorithmException One of the cryptographic algorithms - * that is specified in the protocolName is not supported. - */ - public HandshakeState(String protocolName, int role) throws NoSuchAlgorithmException - { - // Parse the protocol name into its components. - String[] components = protocolName.split("_"); - if (components.length != 5) - throw new IllegalArgumentException("Protocol name must have 5 components"); - String prefix = components[0]; - String patternId = components[1]; - String dh = components[2]; - String hybrid = null; - String cipher = components[3]; - String hash = components[4]; - if (!prefix.equals("Noise") && !prefix.equals("NoisePSK")) - throw new IllegalArgumentException("Prefix must be Noise or NoisePSK"); - pattern = Pattern.lookup(patternId); - if (pattern == null) - throw new IllegalArgumentException("Handshake pattern is not recognized"); - short flags = pattern[0]; - int extraReqs = 0; - if ((flags & Pattern.FLAG_REMOTE_REQUIRED) != 0 && patternId.length() > 1) - extraReqs |= FALLBACK_POSSIBLE; - if (role == RESPONDER) { - // Reverse the pattern flags so that the responder is "local". - flags = Pattern.reverseFlags(flags); - } - int index = dh.indexOf('+'); - if (index != -1) { - // The DH name has two components: regular and hybrid. - hybrid = dh.substring(index + 1); - dh = dh.substring(0, index); - if ((flags & Pattern.FLAG_LOCAL_HYBRID) == 0 || (flags & Pattern.FLAG_REMOTE_HYBRID) == 0) - throw new IllegalArgumentException("Hybrid function specified for non-hybrid pattern"); - } else { - if ((flags & Pattern.FLAG_LOCAL_HYBRID) != 0 || (flags & Pattern.FLAG_REMOTE_HYBRID) != 0) - throw new IllegalArgumentException("Hybrid function not specified for hybrid pattern"); - } - - // Check that the role is correctly specified. - if (role != INITIATOR && role != RESPONDER) - throw new IllegalArgumentException("Role must be initiator or responder"); - - // Initialize this object. This will also create the cipher and hash objects. - symmetric = new SymmetricState(protocolName, cipher, hash); - isInitiator = (role == INITIATOR); - action = NO_ACTION; - requirements = extraReqs | computeRequirements(flags, prefix, role, false); - patternIndex = 1; - - // Create the DH objects that we will need later. - if ((flags & Pattern.FLAG_LOCAL_STATIC) != 0) - localKeyPair = Noise.createDH(dh); - if ((flags & Pattern.FLAG_LOCAL_EPHEMERAL) != 0) - localEphemeral = Noise.createDH(dh); - if ((flags & Pattern.FLAG_LOCAL_HYBRID) != 0) - localHybrid = Noise.createDH(hybrid); - if ((flags & Pattern.FLAG_REMOTE_STATIC) != 0) - remotePublicKey = Noise.createDH(dh); - if ((flags & Pattern.FLAG_REMOTE_EPHEMERAL) != 0) - remoteEphemeral = Noise.createDH(dh); - if ((flags & Pattern.FLAG_REMOTE_HYBRID) != 0) - remoteHybrid = Noise.createDH(hybrid); - - // We cannot use hybrid algorithms like New Hope for ephemeral or static keys, - // as the unbalanced nature of the algorithm only works with "f" and "ff" tokens. - if (localKeyPair instanceof DHStateHybrid) - throw new NoSuchAlgorithmException("Cannot use '" + localKeyPair.getDHName() + "' for static keys"); - if (localEphemeral instanceof DHStateHybrid) - throw new NoSuchAlgorithmException("Cannot use '" + localEphemeral.getDHName() + "' for ephemeral keys"); - if (remotePublicKey instanceof DHStateHybrid) - throw new NoSuchAlgorithmException("Cannot use '" + remotePublicKey.getDHName() + "' for static keys"); - if (remoteEphemeral instanceof DHStateHybrid) - throw new NoSuchAlgorithmException("Cannot use '" + remoteEphemeral.getDHName() + "' for ephemeral keys"); - } - - /** - * Gets the name of the Noise protocol. - * - * @return The protocol name. - */ - public String getProtocolName() - { - return symmetric.getProtocolName(); - } - - /** - * Gets the role for this handshake. - * - * @return The role, HandshakeState.INITIATOR or HandshakeState.RESPONDER. - */ - public int getRole() - { - return isInitiator ? INITIATOR : RESPONDER; - } - - /** - * Determine if this handshake needs a pre-shared key value - * and one has not been configured yet. - * - * @return true if a pre-shared key is needed; false if not. - */ - public boolean needsPreSharedKey() - { - if (preSharedKey != null) - return false; - else - return (requirements & PSK_REQUIRED) != 0; - } - - /** - * Determine if this object has already been configured with a - * pre-shared key. - * - * @return true if the pre-shared key has already been configured; - * false if one is not needed or it has not been configured yet. - */ - public boolean hasPreSharedKey() - { - return preSharedKey != null; - } - - /** - * Sets the pre-shared key for this handshake. - * - * @param key Buffer containing the pre-shared key value. - * @param offset Offset into the buffer of the first byte of the key. - * @param length The length of the pre-shared key, which must be 32. - * - * @throws IllegalArgumentException The length is not 32. - * - * @throws UnsupportedOperationException Pre-shared keys are not - * supported for this handshake type. - * - * @throws IllegalStateException The handshake has already started, - * so the pre-shared key can no longer be set. - */ - public void setPreSharedKey(byte[] key, int offset, int length) - { - if (length != 32) { - throw new IllegalArgumentException - ("Pre-shared keys must be 32 bytes in length"); - } - if ((requirements & PSK_REQUIRED) == 0) { - throw new UnsupportedOperationException - ("Pre-shared keys are not supported for this handshake"); - } - if (action != NO_ACTION) { - throw new IllegalStateException - ("Handshake has already started; cannot set pre-shared key"); - } - if (preSharedKey != null) { - Noise.destroy(preSharedKey); - preSharedKey = null; - } - preSharedKey = Noise.copySubArray(key, offset, length); - } - - /** - * Sets the prologue for this handshake. - * - * @param prologue Buffer containing the prologue value. - * @param offset Offset into the buffer of the first byte of the prologue. - * @param length The length of the prologue in bytes. - * - * @throws IllegalStateException The handshake has already started, - * so the prologue can no longer be set. - */ - public void setPrologue(byte[] prologue, int offset, int length) - { - if (action != NO_ACTION) { - throw new IllegalStateException - ("Handshake has already started; cannot set prologue"); - } - if (this.prologue != null) { - Noise.destroy(this.prologue); - this.prologue = null; - } - this.prologue = Noise.copySubArray(prologue, offset, length); - } - - /** - * Gets the keypair object for the local static key. - * - * @return The keypair, or null if a local static key is not required. - */ - public DHState getLocalKeyPair() - { - return localKeyPair; - } - - /** - * Determine if this handshake requires a local static key. - * - * @return true if a local static key is needed; false if not. - * - * If the local static key has already been set, then this function - * will return false. - */ - public boolean needsLocalKeyPair() - { - if (localKeyPair != null) - return !localKeyPair.hasPrivateKey(); - else - return false; - } - - /** - * Determine if this handshake has already been configured - * with a local static key. - * - * @return true if the local static key has been configured; - * false if not. - */ - public boolean hasLocalKeyPair() - { - if (localKeyPair != null) - return localKeyPair.hasPrivateKey(); - else - return false; - } - - /** - * Gets the public key object for the remote static key. - * - * @return The public key, or null if a remote static key - * is not required. - */ - public DHState getRemotePublicKey() - { - return remotePublicKey; - } - - /** - * Determine if this handshake requires a remote static key. - * - * @return true if a remote static key is needed; false if not. - * - * If the remote static key has already been set, then this function - * will return false. - */ - public boolean needsRemotePublicKey() - { - if (remotePublicKey != null) - return !remotePublicKey.hasPublicKey(); - else - return false; - } - - /** - * Determine if this handshake has already been configured - * with a remote static key. - * - * @return true if the remote static key has been configured; - * false if not. - */ - public boolean hasRemotePublicKey() - { - if (remotePublicKey != null) - return remotePublicKey.hasPublicKey(); - else - return false; - } - - /** - * Gets the DHState object containing a fixed local ephemeral - * key value for this handshake. - * - * @return The fixed ephemeral key object, or null if a local - * ephemeral key is not required by this handshake. - * - * This function is intended for testing only. It can be used - * to establish a fixed ephemeral key for test vectors. This - * function should not be used in real applications. - */ - public DHState getFixedEphemeralKey() - { - if (fixedEphemeral != null) - return fixedEphemeral; - if (localEphemeral == null) - return null; - try { - fixedEphemeral = Noise.createDH(localEphemeral.getDHName()); - } catch (NoSuchAlgorithmException e) { - // This shouldn't happen - the local ephemeral key would - // have already been created with the same name! - fixedEphemeral = null; - } - return fixedEphemeral; - } - - /** - * Gets the DHState object containing a fixed local hybrid - * key value for this handshake. - * - * @return The fixed hybrid key object, or null if a local - * hybrid key is not required by this handshake. - * - * This function is intended for testing only. It can be used - * to establish a fixed hybrid key for test vectors. This - * function should not be used in real applications. - */ - public DHState getFixedHybridKey() - { - if (fixedHybrid != null) - return fixedHybrid; - if (localHybrid == null) - return null; - try { - fixedHybrid = Noise.createDH(localHybrid.getDHName()); - } catch (NoSuchAlgorithmException e) { - // This shouldn't happen - the local hybrid key would - // have already been created with the same name! - fixedHybrid = null; - } - return fixedHybrid; - } - - // Empty value for when the prologue is not supplied. - private static final byte[] emptyPrologue = new byte [0]; - - /** - * Starts the handshake running. - * - * This function is called after all of the handshake parameters have been - * provided to the HandshakeState object. This function should be followed - * by calls to writeMessage() or readMessage() to process the handshake - * messages. The getAction() function indicates the action to take next. - * - * @throws IllegalStateException The handshake has already started, or one or - * more of the required parameters has not been supplied. - * - * @throws UnsupportedOperationException An attempt was made to start a - * fallback handshake pattern without first calling fallback() on a - * previous handshake. - * - * @see #getAction() - * @see #writeMessage(byte[], int, byte[], int, int) - * @see #readMessage(byte[], int, int, byte[], int) - * @see #fallback() - */ - public void start() - { - if (action != NO_ACTION) { - throw new IllegalStateException - ("Handshake has already started; cannot start again"); - } - if ((pattern[0] & Pattern.FLAG_REMOTE_EPHEM_REQ) != 0 && - (requirements & FALLBACK_PREMSG) == 0) { - throw new UnsupportedOperationException - ("Cannot start a fallback pattern"); - } - - // Check that we have satisfied all of the pattern requirements. - if ((requirements & LOCAL_REQUIRED) != 0) { - if (localKeyPair == null || !localKeyPair.hasPrivateKey()) - throw new IllegalStateException("Local static key required"); - } - if ((requirements & REMOTE_REQUIRED) != 0) { - if (remotePublicKey == null || !remotePublicKey.hasPublicKey()) - throw new IllegalStateException("Remote static key required"); - } - if ((requirements & PSK_REQUIRED) != 0) { - if (preSharedKey == null) - throw new IllegalStateException("Pre-shared key required"); - } - - // Hash the prologue value. - if (prologue != null) - symmetric.mixHash(prologue, 0, prologue.length); - else - symmetric.mixHash(emptyPrologue, 0, 0); - - // Hash the pre-shared key into the chaining key and handshake hash. - if (preSharedKey != null) - symmetric.mixPreSharedKey(preSharedKey); - - // Mix the pre-supplied public keys into the handshake hash. - if (isInitiator) { - if ((requirements & LOCAL_PREMSG) != 0) - symmetric.mixPublicKey(localKeyPair); - if ((requirements & FALLBACK_PREMSG) != 0) { - symmetric.mixPublicKey(remoteEphemeral); - if (remoteHybrid != null) - symmetric.mixPublicKey(remoteHybrid); - if (preSharedKey != null) - symmetric.mixPublicKeyIntoCK(remoteEphemeral); - } - if ((requirements & REMOTE_PREMSG) != 0) - symmetric.mixPublicKey(remotePublicKey); - } else { - if ((requirements & REMOTE_PREMSG) != 0) - symmetric.mixPublicKey(remotePublicKey); - if ((requirements & FALLBACK_PREMSG) != 0) { - symmetric.mixPublicKey(localEphemeral); - if (localHybrid != null) - symmetric.mixPublicKey(localHybrid); - if (preSharedKey != null) - symmetric.mixPublicKeyIntoCK(localEphemeral); - } - if ((requirements & LOCAL_PREMSG) != 0) - symmetric.mixPublicKey(localKeyPair); - } - - // The handshake has officially started - set the first action. - if (isInitiator) - action = WRITE_MESSAGE; - else - action = READ_MESSAGE; - } - - /** - * Falls back to the "XXfallback" handshake pattern. - * - * This function is intended used to help implement the "Noise Pipes" protocol. - * It resets a HandshakeState object with the original handshake pattern - * (usually "IK"), converting it into an object with the handshake pattern - * "XXfallback". Information from the previous session such as the local - * keypair, the initiator's ephemeral key, the prologue value, and the - * pre-shared key, are passed to the new session. - * - * Once the fallback has been initiated, the application can set - * new values for the handshake parameters if the values from the - * previous session do not apply. For example, the application may - * use a different prologue for the fallback than for the original - * session. - * - * After setting any new parameters, the application calls start() - * again to restart the handshake from where it left off before the fallback. - * - * Note that this function reverses the roles of initiator and responder. - * - * @throws UnsupportedOperationException The current handshake pattern - * is not compatible with "XXfallback". - * - * @throws IllegalStateException The previous protocol has not started - * or it has not reached the fallback position yet. - * - * @throws NoSuchAlgorithmException One of the cryptographic algorithms - * that is specified in the new protocolName is not supported. - * - * @see #start() - */ - public void fallback() throws NoSuchAlgorithmException - { - fallback("XXfallback"); - } - - /** - * Falls back to another handshake pattern. - * - * @param patternName The name of the pattern to fall back to; - * e.g. "XXfallback", "NXfallback", etc. - * - * This function resets a HandshakeState object with the original - * handshake pattern, and converts it into an object with the new handshake - * patternName. Information from the previous session such as the local - * keypair, the initiator's ephemeral key, the prologue value, and the - * pre-shared key, are passed to the new session. - * - * Once the fallback has been initiated, the application can set - * new values for the handshake parameters if the values from the - * previous session do not apply. For example, the application may - * use a different prologue for the fallback than for the original - * session. - * - * After setting any new parameters, the application calls start() - * again to restart the handshake from where it left off before the fallback. - * - * The new pattern may have greater key requirements than the original; - * for example changing from "NK" from "XXfallback" requires that the - * initiator's static public key be set. The application is responsible for - * setting any extra keys before calling start(). - * - * Note that this function reverses the roles of initiator and responder. - * - * @throws UnsupportedOperationException The current handshake pattern - * is not compatible with the patternName, or patternName is not a - * fallback pattern. - * - * @throws IllegalStateException The previous protocol has not started - * or it has not reached the fallback position yet. - * - * @throws NoSuchAlgorithmException One of the cryptographic algorithms - * that is specified in the new protocolName is not supported. - * - * @see #start() - */ - public void fallback(String patternName) throws NoSuchAlgorithmException - { - // The original pattern must end in "K" for fallback to be possible. - if ((requirements & FALLBACK_POSSIBLE) == 0) - throw new UnsupportedOperationException("Previous handshake pattern does not support fallback"); - - // Check that "patternName" supports fallback. - short[] newPattern = Pattern.lookup(patternName); - if (newPattern == null || (newPattern[0] & Pattern.FLAG_REMOTE_EPHEM_REQ) == 0) - throw new UnsupportedOperationException("New pattern is not a fallback pattern"); - - // The initiator should be waiting for a return message from the - // responder, and the responder should have failed on the first - // handshake message from the initiator. We also allow the - // responder to fallback after processing the first message - // successfully; it decides to always fall back anyway. - if (isInitiator) { - if ((action != FAILED && action != READ_MESSAGE) || !localEphemeral.hasPublicKey()) - throw new IllegalStateException("Initiator cannot fall back from this state"); - } else { - if ((action != FAILED && action != WRITE_MESSAGE) || !remoteEphemeral.hasPublicKey()) - throw new IllegalStateException("Responder cannot fall back from this state"); - } - - // Format a new protocol name for the fallback variant - // and recreate the SymmetricState object. - String[] components = symmetric.getProtocolName().split("_"); - components[1] = patternName; - StringBuilder builder = new StringBuilder(); - builder.append(components[0]); - for (int index = 1; index < components.length; ++index) { - builder.append('_'); - builder.append(components[index]); - } - String name = builder.toString(); - SymmetricState newSymmetric = new SymmetricState(name, components[3], components[4]); - symmetric.destroy(); - symmetric = newSymmetric; - - // Convert the HandshakeState to the "XXfallback" pattern. - if (isInitiator) { - if (remoteEphemeral != null) - remoteEphemeral.clearKey(); - if (remoteHybrid != null) - remoteHybrid.clearKey(); - if (remotePublicKey != null) - remotePublicKey.clearKey(); - isInitiator = false; - } else { - if (localEphemeral != null) - localEphemeral.clearKey(); - if (localHybrid != null) - localHybrid.clearKey(); - if ((newPattern[0] & Pattern.FLAG_REMOTE_REQUIRED) == 0 && remotePublicKey != null) - remotePublicKey.clearKey(); - isInitiator = true; - } - action = NO_ACTION; - pattern = newPattern; - patternIndex = 1; - short flags = pattern[0]; - if (!isInitiator) { - // Reverse the pattern flags so that the responder is "local". - flags = Pattern.reverseFlags(flags); - } - requirements = computeRequirements(flags, components[0], isInitiator ? INITIATOR : RESPONDER, true); - } - - /** - * Gets the next action that the application should perform for - * the handshake part of the protocol. - * - * @return One of HandshakeState.NO_ACTION, HandshakeState.WRITE_MESSAGE, - * HandshakeState.READ_MESSAGE, HandshakeState.SPLIT, or - * HandshakeState.FAILED. - */ - public int getAction() - { - return action; - } - - /** - * Mixes the result of a Diffie-Hellman calculation into the chaining key. - * - * @param local Local private key object. - * @param remote Remote public key object. - */ - private void mixDH(DHState local, DHState remote) - { - if (local == null || remote == null) - throw new IllegalStateException("Pattern definition error"); - int len = local.getSharedKeyLength(); - byte[] shared = new byte [len]; - try { - local.calculate(shared, 0, remote); - symmetric.mixKey(shared, 0, len); - } finally { - Noise.destroy(shared); - } - } - - /** - * Writes a message payload during the handshake. - * - * @param message The buffer that will be populated with the - * handshake packet to be written to the transport. - * @param messageOffset First offset within the message buffer - * to be populated. - * @param payload Buffer containing the payload to add to the - * handshake message; can be null if there is no payload. - * @param payloadOffset Offset into the payload buffer of the - * first payload buffer. - * @param payloadLength Length of the payload in bytes. - * - * @return The length of the data written to the message buffer. - * - * @throws IllegalStateException The action is not WRITE_MESSAGE. - * - * @throws IllegalArgumentException The payload is null, but - * payloadOffset or payloadLength is non-zero. - * - * @throws ShortBufferException The message buffer does not have - * enough space for the handshake message. - * - * @see #getAction() - * @see #readMessage(byte[], int, int, byte[], int) - */ - public int writeMessage(byte[] message, int messageOffset, byte[] payload, int payloadOffset, int payloadLength) throws ShortBufferException - { - int messagePosn = messageOffset; - boolean success = false; - - // Validate the parameters and state. - if (action != WRITE_MESSAGE) { - throw new IllegalStateException - ("Handshake state does not allow writing messages"); - } - if (payload == null && (payloadOffset != 0 || payloadLength != 0)) { - throw new IllegalArgumentException("Invalid payload argument"); - } - if (messageOffset > message.length) { - throw new ShortBufferException(); - } - - // Format the message. - try { - // Process tokens until the direction changes or the patten ends. - for (;;) { - if (patternIndex >= pattern.length) { - // The pattern has finished, so the next action is "split". - action = SPLIT; - break; - } - short token = pattern[patternIndex++]; - if (token == Pattern.FLIP_DIR) { - // Change directions, so this message is complete and the - // next action is "read message". - action = READ_MESSAGE; - break; - } - int space = message.length - messagePosn; - int len, macLen; - switch (token) { - case Pattern.E: - { - // Generate a local ephemeral keypair and add the public - // key to the message. If we are running fixed vector tests, - // then the ephemeral key may have already been provided. - if (localEphemeral == null) - throw new IllegalStateException("Pattern definition error"); - if (fixedEphemeral == null) - localEphemeral.generateKeyPair(); - else - localEphemeral.copyFrom(fixedEphemeral); - len = localEphemeral.getPublicKeyLength(); - if (space < len) - throw new ShortBufferException(); - localEphemeral.getPublicKey(message, messagePosn); - symmetric.mixHash(message, messagePosn, len); - - // If the protocol is using pre-shared keys, then also mix - // the local ephemeral key into the chaining key. - if (preSharedKey != null) - symmetric.mixKey(message, messagePosn, len); - messagePosn += len; - } - break; - - case Pattern.S: - { - // Encrypt the local static public key and add it to the message. - if (localKeyPair == null) - throw new IllegalStateException("Pattern definition error"); - len = localKeyPair.getPublicKeyLength(); - macLen = symmetric.getMACLength(); - if (space < (len + macLen)) - throw new ShortBufferException(); - localKeyPair.getPublicKey(message, messagePosn); - messagePosn += symmetric.encryptAndHash(message, messagePosn, message, messagePosn, len); - } - break; - - case Pattern.EE: - { - // DH operation with initiator and responder ephemeral keys. - mixDH(localEphemeral, remoteEphemeral); - } - break; - - case Pattern.ES: - { - // DH operation with initiator ephemeral and responder static keys. - if (isInitiator) - mixDH(localEphemeral, remotePublicKey); - else - mixDH(localKeyPair, remoteEphemeral); - } - break; - - case Pattern.SE: - { - // DH operation with initiator static and responder ephemeral keys. - if (isInitiator) - mixDH(localKeyPair, remoteEphemeral); - else - mixDH(localEphemeral, remotePublicKey); - } - break; - - case Pattern.SS: - { - // DH operation with initiator and responder static keys. - mixDH(localKeyPair, remotePublicKey); - } - break; - - case Pattern.F: - { - // Generate a local hybrid keypair and add the public - // key to the message. If we are running fixed vector tests, - // then a fixed hybrid key may have already been provided. - if (localHybrid == null) - throw new IllegalStateException("Pattern definition error"); - if (localHybrid instanceof DHStateHybrid) { - // The DH object is something like New Hope which needs to - // generate keys relative to the other party's public key. - DHStateHybrid hybrid = (DHStateHybrid)localHybrid; - if (fixedHybrid == null) - hybrid.generateKeyPair(remoteHybrid); - else - hybrid.copyFrom(fixedHybrid, remoteHybrid); - } else { - if (fixedHybrid == null) - localHybrid.generateKeyPair(); - else - localHybrid.copyFrom(fixedHybrid); - } - len = localHybrid.getPublicKeyLength(); - if (space < len) - throw new ShortBufferException(); - macLen = symmetric.getMACLength(); - if (space < (len + macLen)) - throw new ShortBufferException(); - localHybrid.getPublicKey(message, messagePosn); - messagePosn += symmetric.encryptAndHash(message, messagePosn, message, messagePosn, len); - } - break; - - case Pattern.FF: - { - // DH operation with initiator and responder hybrid keys. - mixDH(localHybrid, remoteHybrid); - } - break; - - default: - { - // Unknown token code. Abort. - throw new IllegalStateException("Unknown handshake token " + Integer.toString(token)); - } - } - } - - // Add the payload to the message buffer and encrypt it. - if (payload != null) - messagePosn += symmetric.encryptAndHash(payload, payloadOffset, message, messagePosn, payloadLength); - else - messagePosn += symmetric.encryptAndHash(message, messagePosn, message, messagePosn, 0); - success = true; - } finally { - // If we failed, then clear any sensitive data that may have - // already been written to the message buffer. - if (!success) { - Arrays.fill(message, messageOffset, message.length - messageOffset, (byte)0); - action = FAILED; - } - } - return messagePosn - messageOffset; - } - - /** - * Reads a message payload during the handshake. - * - * @param message Buffer containing the incoming handshake - * that was read from the transport. - * @param messageOffset Offset of the first message byte. - * @param messageLength The length of the incoming message. - * @param payload Buffer that will be populated with the message payload. - * @param payloadOffset Offset of the first byte in the - * payload buffer to be populated with payload data. - * - * @return The length of the payload. - * - * @throws IllegalStateException The action is not READ_MESSAGE. - * - * @throws ShortBufferException The message buffer does not have - * sufficient bytes for a valid message or the payload buffer does - * not have enough space for the decrypted payload. - * - * @throws BadPaddingException A MAC value in the message failed - * to verify. - * - * @see #getAction() - * @see #writeMessage(byte[], int, byte[], int, int) - */ - public int readMessage(byte[] message, int messageOffset, int messageLength, byte[] payload, int payloadOffset) throws ShortBufferException, BadPaddingException - { - boolean success = false; - int messageEnd = messageOffset + messageLength; - - // Validate the parameters. - if (action != READ_MESSAGE) { - throw new IllegalStateException - ("Handshake state does not allow reading messages"); - } - if (messageOffset > message.length || payloadOffset > payload.length) { - throw new ShortBufferException(); - } - if (messageLength > (message.length - messageOffset)) { - throw new ShortBufferException(); - } - - // Process the message. - try { - // Process tokens until the direction changes or the patten ends. - for (;;) { - if (patternIndex >= pattern.length) { - // The pattern has finished, so the next action is "split". - action = SPLIT; - break; - } - short token = pattern[patternIndex++]; - if (token == Pattern.FLIP_DIR) { - // Change directions, so this message is complete and the - // next action is "write message". - action = WRITE_MESSAGE; - break; - } - int space = messageEnd - messageOffset; - int len, macLen; - switch (token) { - case Pattern.E: - { - // Save the remote ephemeral key and hash it. - if (remoteEphemeral == null) - throw new IllegalStateException("Pattern definition error"); - len = remoteEphemeral.getPublicKeyLength(); - if (space < len) - throw new ShortBufferException(); - symmetric.mixHash(message, messageOffset, len); - remoteEphemeral.setPublicKey(message, messageOffset); - if (remoteEphemeral.isNullPublicKey()) { - // The remote ephemeral key is null, which means that it is - // not contributing anything to the security of the session - // and is in fact downgrading the security to "none at all" - // in some of the message patterns. Reject all such keys. - throw new BadPaddingException("Null remote public key"); - } - - // If the protocol is using pre-shared keys, then also mix - // the remote ephemeral key into the chaining key. - if (preSharedKey != null) - symmetric.mixKey(message, messageOffset, len); - messageOffset += len; - } - break; - - case Pattern.S: - { - // Decrypt and read the remote static key. - if (remotePublicKey == null) - throw new IllegalStateException("Pattern definition error"); - len = remotePublicKey.getPublicKeyLength(); - macLen = symmetric.getMACLength(); - if (space < (len + macLen)) - throw new ShortBufferException(); - byte[] temp = new byte [len]; - try { - if (symmetric.decryptAndHash(message, messageOffset, temp, 0, len + macLen) != len) - throw new ShortBufferException(); - remotePublicKey.setPublicKey(temp, 0); - } finally { - Noise.destroy(temp); - } - messageOffset += len + macLen; - } - break; - - case Pattern.EE: - { - // DH operation with initiator and responder ephemeral keys. - mixDH(localEphemeral, remoteEphemeral); - } - break; - - case Pattern.ES: - { - // DH operation with initiator ephemeral and responder static keys. - if (isInitiator) - mixDH(localEphemeral, remotePublicKey); - else - mixDH(localKeyPair, remoteEphemeral); - } - break; - - case Pattern.SE: - { - // DH operation with initiator static and responder ephemeral keys. - if (isInitiator) - mixDH(localKeyPair, remoteEphemeral); - else - mixDH(localEphemeral, remotePublicKey); - } - break; - - case Pattern.SS: - { - // DH operation with initiator and responder static keys. - mixDH(localKeyPair, remotePublicKey); - } - break; - - case Pattern.F: - { - // Decrypt and read the remote hybrid ephemeral key. - if (remoteHybrid == null) - throw new IllegalStateException("Pattern definition error"); - if (remoteHybrid instanceof DHStateHybrid) { - // The DH object is something like New Hope. The public key - // length may need to change based on whether we already have - // generated a local hybrid keypair or not. - ((DHStateHybrid)remoteHybrid).specifyPeer(localHybrid); - } - len = remoteHybrid.getPublicKeyLength(); - macLen = symmetric.getMACLength(); - if (space < (len + macLen)) - throw new ShortBufferException(); - byte[] temp = new byte [len]; - try { - if (symmetric.decryptAndHash(message, messageOffset, temp, 0, len + macLen) != len) - throw new ShortBufferException(); - remoteHybrid.setPublicKey(temp, 0); - } finally { - Noise.destroy(temp); - } - messageOffset += len + macLen; - } - break; - - case Pattern.FF: - { - // DH operation with initiator and responder hybrid keys. - mixDH(localHybrid, remoteHybrid); - } - break; - - default: - { - // Unknown token code. Abort. - throw new IllegalStateException("Unknown handshake token " + Integer.toString(token)); - } - } - } - - // Decrypt the message payload. - int payloadLength = symmetric.decryptAndHash(message, messageOffset, payload, payloadOffset, messageEnd - messageOffset); - success = true; - return payloadLength; - } finally { - // If we failed, then clear any sensitive data that may have - // already been written to the payload buffer. - if (!success) { - Arrays.fill(payload, payloadOffset, payload.length - payloadOffset, (byte)0); - action = FAILED; - } - } - } - - /** - * Splits the transport encryption CipherState objects out of - * this HandshakeState object once the handshake completes. - * - * @return The pair of ciphers for sending and receiving. - * - * @throws IllegalStateException The action is not SPLIT. - */ - public CipherStatePair split() - { - if (action != SPLIT) { - throw new IllegalStateException - ("Handshake has not finished"); - } - CipherStatePair pair = symmetric.split(); - if (!isInitiator) - pair.swap(); - action = COMPLETE; - return pair; - } - - /** - * Splits the transport encryption CipherState objects out of - * this HandshakeObject after mixing in a secondary symmetric key. - * - * @param secondaryKey The buffer containing the secondary key. - * @param offset The offset of the first secondary key byte. - * @param length The length of the secondary key in bytes, which - * must be either 0 or 32. - * @return The pair of ciphers for sending and receiving. - * - * @throws IllegalStateException The action is not SPLIT. - * - * @throws IllegalArgumentException The length is not 0 or 32. - */ - public CipherStatePair split(byte[] secondaryKey, int offset, int length) - { - if (action != SPLIT) { - throw new IllegalStateException - ("Handshake has not finished"); - } - CipherStatePair pair = symmetric.split(secondaryKey, offset, length); - if (!isInitiator) { - // Swap the sender and receiver objects for the responder - // to make it easier on the application to know which is which. - pair.swap(); - } - action = COMPLETE; - return pair; - } - - /** - * Gets the current value of the handshake hash. - * - * @return The handshake hash. This must not be modified by the caller. - * - * @throws IllegalStateException The action is not SPLIT or COMPLETE. - */ - public byte[] getHandshakeHash() - { - if (action != SPLIT && action != COMPLETE) { - throw new IllegalStateException - ("Handshake has not completed"); - } - return symmetric.getHandshakeHash(); - } - - @Override - public void destroy() { - if (symmetric != null) - symmetric.destroy(); - if (localKeyPair != null) - localKeyPair.destroy(); - if (localEphemeral != null) - localEphemeral.destroy(); - if (localHybrid != null) - localHybrid.destroy(); - if (remotePublicKey != null) - remotePublicKey.destroy(); - if (remoteEphemeral != null) - remoteEphemeral.destroy(); - if (remoteHybrid != null) - remoteHybrid.destroy(); - if (fixedEphemeral != null) - fixedEphemeral.destroy(); - if (fixedHybrid != null) - fixedHybrid.destroy(); - if (preSharedKey != null) - Noise.destroy(preSharedKey); - if (prologue != null) - Noise.destroy(prologue); - } - - /** - * Computes the requirements for a handshake. - * - * @param flags The flags from the handshake's pattern. - * @param prefix The prefix from the protocol name; typically - * "Noise" or "NoisePSK". - * @param role The role, HandshakeState.INITIATOR or HandshakeState.RESPONDER. - * @param isFallback Set to true if we need the requirements for a - * fallback pattern; false for a regular pattern. - * - * @return The set of requirements for the handshake. - */ - private static int computeRequirements(short flags, String prefix, int role, boolean isFallback) - { - int requirements = 0; - if ((flags & Pattern.FLAG_LOCAL_STATIC) != 0) { - requirements |= LOCAL_REQUIRED; - } - if ((flags & Pattern.FLAG_LOCAL_REQUIRED) != 0) { - requirements |= LOCAL_REQUIRED; - requirements |= LOCAL_PREMSG; - } - if ((flags & Pattern.FLAG_REMOTE_REQUIRED) != 0) { - requirements |= REMOTE_REQUIRED; - requirements |= REMOTE_PREMSG; - } - if ((flags & (Pattern.FLAG_REMOTE_EPHEM_REQ | - Pattern.FLAG_LOCAL_EPHEM_REQ)) != 0) { - if (isFallback) - requirements |= FALLBACK_PREMSG; - } - if (prefix.equals("NoisePSK")) { - requirements |= PSK_REQUIRED; - } - return requirements; - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/NewHopeDHState.java b/src/main/java/com/southernstorm/noise/protocol/NewHopeDHState.java deleted file mode 100644 index 2d07e8f6f..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/NewHopeDHState.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import com.southernstorm.noise.crypto.NewHope; -import com.southernstorm.noise.crypto.NewHopeTor; - -import java.util.Arrays; - -/** - * Implementation of the New Hope post-quantum algorithm for the Noise protocol. - */ -final class NewHopeDHState implements DHStateHybrid { - - enum KeyType - { - None, - AlicePrivate, - AlicePublic, - BobPrivate, - BobPublic, - BobCalculated; - } - - private NewHopeTor nh; - private byte[] publicKey; - private byte[] privateKey; - private KeyType keyType; - - /** - * Special version of NewHopeTor that allows explicit random data - * to be specified for test vectors. - */ - private class NewHopeWithPrivateKey extends NewHopeTor { - - byte[] randomData; - - public NewHopeWithPrivateKey(byte[] randomData) - { - this.randomData = randomData; - } - - @Override - protected void randombytes(byte[] buffer) - { - System.arraycopy(randomData, 0, buffer, 0, buffer.length); - } - } - - /** - * Constructs a new key exchange object for New Hope. - */ - public NewHopeDHState() { - nh = null; - publicKey = null; - privateKey = null; - keyType = KeyType.None; - } - - private boolean isAlice() { - return keyType == KeyType.AlicePrivate || keyType == KeyType.AlicePublic; - } - - @Override - public void destroy() { - clearKey(); - } - - @Override - public String getDHName() { - return "NewHope"; - } - - @Override - public int getPublicKeyLength() { - if (isAlice()) - return NewHope.SENDABYTES; - else - return NewHope.SENDBBYTES; - } - - @Override - public int getPrivateKeyLength() { - // New Hope doesn't have private keys in the same sense as - // Curve25519 and Curve448. Instead return the number of - // random bytes that we need to generate each key type. - if (isAlice()) - return 64; - else - return 32; - } - - @Override - public int getSharedKeyLength() { - return NewHope.SHAREDBYTES; - } - - @Override - public void generateKeyPair() { - clearKey(); - keyType = KeyType.AlicePrivate; - nh = new NewHopeTor(); - publicKey = new byte [NewHope.SENDABYTES]; - nh.keygen(publicKey, 0); - } - - @Override - public void generateKeyPair(DHState remote) { - if (remote == null) { - // No remote public key, so always generate in Alice mode. - generateKeyPair(); - return; - } else if (!(remote instanceof NewHopeDHState)) { - throw new IllegalStateException("Mismatched DH objects"); - } - NewHopeDHState r = (NewHopeDHState)remote; - if (r.isAlice() && r.publicKey != null) { - // We have a remote public key for Alice, so generate in Bob mode. - clearKey(); - keyType = KeyType.BobCalculated; - nh = new NewHopeTor(); - publicKey = new byte [NewHope.SENDBBYTES]; - privateKey = new byte [NewHope.SHAREDBYTES]; - nh.sharedb(privateKey, 0, publicKey, 0, r.publicKey, 0); - } else { - generateKeyPair(); - } - } - - @Override - public void getPublicKey(byte[] key, int offset) { - if (publicKey != null) - System.arraycopy(publicKey, 0, key, offset, getPublicKeyLength()); - else - Arrays.fill(key, 0, getPublicKeyLength(), (byte)0); - } - - @Override - public void setPublicKey(byte[] key, int offset) { - if (publicKey != null) - Noise.destroy(publicKey); - publicKey = new byte [getPublicKeyLength()]; - System.arraycopy(key, 0, publicKey, 0, publicKey.length); - } - - @Override - public void getPrivateKey(byte[] key, int offset) { - if (privateKey != null) - System.arraycopy(privateKey, 0, key, offset, getPrivateKeyLength()); - else - Arrays.fill(key, 0, getPrivateKeyLength(), (byte)0); - } - - @Override - public void setPrivateKey(byte[] key, int offset) { - clearKey(); - // Guess the key type from the length of the test data. - if (offset == 0 && key.length == 64) - keyType = KeyType.AlicePrivate; - else - keyType = KeyType.BobPrivate; - privateKey = new byte [getPrivateKeyLength()]; - System.arraycopy(key, 0, privateKey, 0, privateKey.length); - } - - @Override - public void setToNullPublicKey() { - // Null public keys are not supported by New Hope. - // Destroy the current values but otherwise ignore. - clearKey(); - } - - @Override - public void clearKey() { - if (nh != null) { - nh.destroy(); - nh = null; - } - if (publicKey != null) { - Noise.destroy(publicKey); - publicKey = null; - } - if (privateKey != null) { - Noise.destroy(privateKey); - privateKey = null; - } - keyType = KeyType.None; - } - - @Override - public boolean hasPublicKey() { - return publicKey != null; - } - - @Override - public boolean hasPrivateKey() { - return privateKey != null; - } - - @Override - public boolean isNullPublicKey() { - return false; - } - - @Override - public void calculate(byte[] sharedKey, int offset, DHState publicDH) { - if (!(publicDH instanceof NewHopeDHState)) - throw new IllegalArgumentException("Incompatible DH algorithms"); - NewHopeDHState other = (NewHopeDHState)publicDH; - if (keyType == KeyType.AlicePrivate) { - // Compute the shared key for Alice. - nh.shareda(sharedKey, 0, other.publicKey, 0); - } else if (keyType == KeyType.BobCalculated) { - // The shared key for Bob was already computed when the key was generated. - System.arraycopy(privateKey, 0, sharedKey, 0, NewHope.SHAREDBYTES); - } else { - throw new IllegalStateException("Cannot calculate with this DH object"); - } - } - - @Override - public void copyFrom(DHState other) { - if (!(other instanceof NewHopeDHState)) - throw new IllegalStateException("Mismatched DH key objects"); - if (other == this) - return; - NewHopeDHState dh = (NewHopeDHState)other; - clearKey(); - switch (dh.keyType) { - case None: - break; - - case AlicePrivate: - if (dh.privateKey != null) { - keyType = KeyType.AlicePrivate; - privateKey = new byte [dh.privateKey.length]; - System.arraycopy(dh.privateKey, 0, privateKey, 0, privateKey.length); - } else { - throw new IllegalStateException("Cannot copy generated key for Alice"); - } - break; - - case BobPrivate: - case BobCalculated: - throw new IllegalStateException("Cannot copy private key for Bob without public key for Alice"); - - case AlicePublic: - case BobPublic: - keyType = dh.keyType; - publicKey = new byte [dh.publicKey.length]; - System.arraycopy(dh.publicKey, 0, publicKey, 0, publicKey.length); - break; - } - } - - @Override - public void copyFrom(DHState other, DHState remote) { - if (remote == null) { - copyFrom(other); - return; - } - if (!(other instanceof NewHopeDHState) || !(remote instanceof NewHopeDHState)) - throw new IllegalStateException("Mismatched DH key objects"); - if (other == this) - return; - NewHopeDHState dh = (NewHopeDHState)other; - NewHopeDHState remotedh = (NewHopeDHState)remote; - clearKey(); - switch (dh.keyType) { - case None: - break; - - case AlicePrivate: - if (dh.privateKey != null) { - // Generate Alice's public and private key now. - keyType = KeyType.AlicePrivate; - nh = new NewHopeWithPrivateKey(dh.privateKey); - publicKey = new byte [NewHope.SENDABYTES]; - nh.keygen(publicKey, 0); - } else { - throw new IllegalStateException("Cannot copy generated key for Alice"); - } - break; - - case BobPrivate: - if (dh.privateKey != null && remotedh.keyType == KeyType.AlicePublic) { - // Now we know the public key for Alice, we can calculate Bob's public and shared keys. - keyType = KeyType.BobCalculated; - nh = new NewHopeWithPrivateKey(dh.privateKey); - publicKey = new byte [NewHope.SENDBBYTES]; - privateKey = new byte [NewHope.SHAREDBYTES]; - nh.sharedb(privateKey, 0, publicKey, 0, remotedh.publicKey, 0); - } else { - throw new IllegalStateException("Cannot copy private key for Bob without public key for Alice"); - } - break; - - case BobCalculated: - throw new IllegalStateException("Cannot copy generated key for Bob"); - - case AlicePublic: - case BobPublic: - keyType = dh.keyType; - publicKey = new byte [dh.publicKey.length]; - System.arraycopy(dh.publicKey, 0, publicKey, 0, publicKey.length); - break; - } - } - - @Override - public void specifyPeer(DHState local) { - if (!(local instanceof NewHopeDHState)) - return; - clearKey(); - if (((NewHopeDHState)local).keyType == KeyType.AlicePrivate) - keyType = KeyType.BobPublic; - else - keyType = KeyType.AlicePublic; - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/Noise.java b/src/main/java/com/southernstorm/noise/protocol/Noise.java deleted file mode 100644 index 98072b560..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/Noise.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import com.southernstorm.noise.crypto.Blake2bMessageDigest; -import com.southernstorm.noise.crypto.Blake2sMessageDigest; -import com.southernstorm.noise.crypto.SHA256MessageDigest; -import com.southernstorm.noise.crypto.SHA512MessageDigest; - -import javax.crypto.BadPaddingException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.Arrays; - -/** - * Utility functions for the Noise protocol library. - */ -public final class Noise { - - /** - * Maximum length for Noise packets. - */ - public static final int MAX_PACKET_LEN = 65535; - - private static SecureRandom random = new SecureRandom(); - - /** - * Generates random data using the system random number generator. - * - * @param data The data buffer to fill with random data. - */ - public static void random(byte[] data) - { - random.nextBytes(data); - } - - private static boolean forceFallbacks = false; - - /** - * Force the use of plain Java fallback crypto implementations. - * - * @param force Set to true for force fallbacks, false to - * try to use the system implementation before falling back. - * - * This function is intended for testing purposes to toggle between - * the system JCA/JCE implementations and the plain Java fallback - * reference implementations. - */ - public static void setForceFallbacks(boolean force) - { - forceFallbacks = force; - } - - /** - * Creates a Diffie-Hellman object from its Noise protocol name. - * - * @param name The name of the DH algorithm; e.g. "25519", "448", etc. - * - * @return The Diffie-Hellman object if the name is recognized. - * - * @throws NoSuchAlgorithmException The name is not recognized as a - * valid Noise protocol name, or there is no cryptography provider - * in the system that implements the algorithm. - */ - public static DHState createDH(String name) throws NoSuchAlgorithmException - { - if (name.equals("25519")) - return new Curve25519DHState(); - if (name.equals("448")) - return new Curve448DHState(); - if (name.equals("NewHope")) - return new NewHopeDHState(); - throw new NoSuchAlgorithmException("Unknown Noise DH algorithm name: " + name); - } - - /** - * Creates a cipher object from its Noise protocol name. - * - * @param name The name of the cipher algorithm; e.g. "AESGCM", "ChaChaPoly", etc. - * - * @return The cipher object if the name is recognized. - * - * @throws NoSuchAlgorithmException The name is not recognized as a - * valid Noise protocol name, or there is no cryptography provider - * in the system that implements the algorithm. - */ - public static CipherState createCipher(String name) throws NoSuchAlgorithmException - { - if (name.equals("AESGCM")) { - if (forceFallbacks) - return new AESGCMFallbackCipherState(); - // "AES/GCM/NoPadding" exists in some recent JDK's but it is flaky - // to use and not easily back-portable to older Android versions. - // We instead emulate AESGCM on top of "AES/CTR/NoPadding". - try { - return new AESGCMOnCtrCipherState(); - } catch (NoSuchAlgorithmException e1) { - // Could not find anything useful in the JCA/JCE so - // use the pure Java fallback implementation instead. - return new AESGCMFallbackCipherState(); - } - } else if (name.equals("ChaChaPoly")) { - return new ChaChaPolyCipherState(); - } - throw new NoSuchAlgorithmException("Unknown Noise cipher algorithm name: " + name); - } - - /** - * Creates a hash object from its Noise protocol name. - * - * @param name The name of the hash algorithm; e.g. "SHA256", "BLAKE2s", etc. - * - * @return The hash object if the name is recognized. - * - * @throws NoSuchAlgorithmException The name is not recognized as a - * valid Noise protocol name, or there is no cryptography provider - * in the system that implements the algorithm. - */ - public static MessageDigest createHash(String name) throws NoSuchAlgorithmException - { - // Look for a JCA/JCE provider first and if that doesn't work, - // use the fallback implementations in this library instead. - // The only algorithm that is required to be implemented by a - // JDK is "SHA-256", although "SHA-512" is fairly common as well. - if (name.equals("SHA256")) { - if (forceFallbacks) - return new SHA256MessageDigest(); - try { - return MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - return new SHA256MessageDigest(); - } - } else if (name.equals("SHA512")) { - if (forceFallbacks) - return new SHA512MessageDigest(); - try { - return MessageDigest.getInstance("SHA-512"); - } catch (NoSuchAlgorithmException e) { - return new SHA512MessageDigest(); - } - } else if (name.equals("BLAKE2b")) { - // Bouncy Castle registers the BLAKE2b variant we - // want under the name "BLAKE2B-512". - if (forceFallbacks) - return new Blake2bMessageDigest(); - try { - return MessageDigest.getInstance("BLAKE2B-512"); - } catch (NoSuchAlgorithmException e) { - return new Blake2bMessageDigest(); - } - } else if (name.equals("BLAKE2s")) { - // Bouncy Castle doesn't currently (June 2016) have an - // implementation of BLAKE2s, but look for the most - // obvious provider name in case one is added in the future. - if (forceFallbacks) - return new Blake2sMessageDigest(); - try { - return MessageDigest.getInstance("BLAKE2S-256"); - } catch (NoSuchAlgorithmException e) { - return new Blake2sMessageDigest(); - } - } - throw new NoSuchAlgorithmException("Unknown Noise hash algorithm name: " + name); - } - - // The rest of this class consists of internal utility functions - // that are not part of the public API. - - /** - * Destroys the contents of a byte array. - * - * @param array The array whose contents should be destroyed. - */ - static void destroy(byte[] array) - { - Arrays.fill(array, (byte)0); - } - - /** - * Makes a copy of part of an array. - * - * @param data The buffer containing the data to copy. - * @param offset Offset of the first byte to copy. - * @param length The number of bytes to copy. - * - * @return A new array with a copy of the sub-array. - */ - static byte[] copySubArray(byte[] data, int offset, int length) - { - byte[] copy = new byte [length]; - System.arraycopy(data, offset, copy, 0, length); - return copy; - } - - /** - * Throws an instance of AEADBadTagException. - * - * @throws BadPaddingException The AEAD exception. - * - * If the underlying JDK does not have the AEADBadTagException - * class, then this function will instead throw an instance of - * the superclass BadPaddingException. - */ - static void throwBadTagException() throws BadPaddingException - { - try { - Class c = Class.forName("javax.crypto.AEADBadTagException"); - throw (BadPaddingException)(c.newInstance()); - } catch (ClassNotFoundException e) { - } catch (InstantiationException e) { - } catch (IllegalAccessException e) { - } - throw new BadPaddingException(); - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/Pattern.java b/src/main/java/com/southernstorm/noise/protocol/Pattern.java deleted file mode 100644 index 157af6ad7..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/Pattern.java +++ /dev/null @@ -1,835 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -/** - * Information about all supported handshake patterns. - */ -class Pattern { - - private Pattern() {} - - // Token codes. - public static final short S = 1; - public static final short E = 2; - public static final short EE = 3; - public static final short ES = 4; - public static final short SE = 5; - public static final short SS = 6; - public static final short F = 7; - public static final short FF = 8; - public static final short FLIP_DIR = 255; - - // Pattern flag bits. - public static final short FLAG_LOCAL_STATIC = 0x0001; - public static final short FLAG_LOCAL_EPHEMERAL = 0x0002; - public static final short FLAG_LOCAL_REQUIRED = 0x0004; - public static final short FLAG_LOCAL_EPHEM_REQ = 0x0008; - public static final short FLAG_LOCAL_HYBRID = 0x0010; - public static final short FLAG_LOCAL_HYBRID_REQ = 0x0020; - public static final short FLAG_REMOTE_STATIC = 0x0100; - public static final short FLAG_REMOTE_EPHEMERAL = 0x0200; - public static final short FLAG_REMOTE_REQUIRED = 0x0400; - public static final short FLAG_REMOTE_EPHEM_REQ = 0x0800; - public static final short FLAG_REMOTE_HYBRID = 0x1000; - public static final short FLAG_REMOTE_HYBRID_REQ = 0x2000; - - private static final short[] noise_pattern_N = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_REQUIRED, - - E, - ES - }; - - private static final short[] noise_pattern_K = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_REQUIRED, - - E, - ES, - SS - }; - - private static final short[] noise_pattern_X = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_REQUIRED, - - E, - ES, - S, - SS - }; - - private static final short[] noise_pattern_NN = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE - }; - - private static final short[] noise_pattern_NK = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - ES, - FLIP_DIR, - E, - EE - }; - - private static final short[] noise_pattern_NX = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - S, - ES - }; - - private static final short[] noise_pattern_XN = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_XK = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - ES, - FLIP_DIR, - E, - EE, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_XX = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - S, - ES, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_KN = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_KK = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - ES, - SS, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_KX = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - EE, - SE, - S, - ES - }; - - private static final short[] noise_pattern_IN = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_EPHEMERAL, - - E, - S, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_IK = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - ES, - S, - SS, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_IX = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - S, - FLIP_DIR, - E, - EE, - SE, - S, - ES - }; - - private static final short[] noise_pattern_XXfallback = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_EPHEM_REQ, - - E, - EE, - S, - SE, - FLIP_DIR, - S, - ES - }; - - private static final short[] noise_pattern_Xnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_REQUIRED, - - E, - S, - ES, - SS - }; - - private static final short[] noise_pattern_NXnoidh = { - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - S, - EE, - ES - }; - - private static final short[] noise_pattern_XXnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - S, - EE, - ES, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_KXnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - FLIP_DIR, - E, - S, - EE, - SE, - ES - }; - - private static final short[] noise_pattern_IKnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_REQUIRED, - - E, - S, - ES, - SS, - FLIP_DIR, - E, - EE, - SE - }; - - private static final short[] noise_pattern_IXnoidh = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL, - - E, - S, - FLIP_DIR, - E, - S, - EE, - SE, - ES - }; - - private static final short[] noise_pattern_NNhfs = { - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF - }; - - private static final short[] noise_pattern_NKhfs = { - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_REQUIRED, - - E, - F, - ES, - FLIP_DIR, - E, - F, - EE, - FF - }; - - private static final short[] noise_pattern_NXhfs = { - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - S, - ES - }; - - private static final short[] noise_pattern_XNhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_XKhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_REQUIRED, - - E, - F, - ES, - FLIP_DIR, - E, - F, - EE, - FF, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_XXhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - S, - ES, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_KNhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_KKhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_REQUIRED, - - E, - F, - ES, - SS, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_KXhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - EE, - FF, - SE, - S, - ES - }; - - private static final short[] noise_pattern_INhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - S, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_IKhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_REQUIRED, - - E, - F, - ES, - S, - SS, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_IXhfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - S, - FLIP_DIR, - E, - F, - EE, - FF, - SE, - S, - ES - }; - - private static final short[] noise_pattern_XXfallback_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_EPHEM_REQ | - FLAG_REMOTE_HYBRID | - FLAG_REMOTE_HYBRID_REQ, - - E, - F, - EE, - FF, - S, - SE, - FLIP_DIR, - S, - ES - }; - - private static final short[] noise_pattern_NXnoidh_hfs = { - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - S, - EE, - FF, - ES - }; - - private static final short[] noise_pattern_XXnoidh_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - S, - EE, - FF, - ES, - FLIP_DIR, - S, - SE - }; - - private static final short[] noise_pattern_KXnoidh_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_REQUIRED | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - FLIP_DIR, - E, - F, - S, - EE, - FF, - SE, - ES - }; - - private static final short[] noise_pattern_IKnoidh_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - S, - ES, - SS, - FLIP_DIR, - E, - F, - EE, - FF, - SE - }; - - private static final short[] noise_pattern_IXnoidh_hfs = { - FLAG_LOCAL_STATIC | - FLAG_LOCAL_EPHEMERAL | - FLAG_LOCAL_HYBRID | - FLAG_REMOTE_STATIC | - FLAG_REMOTE_EPHEMERAL | - FLAG_REMOTE_HYBRID, - - E, - F, - S, - FLIP_DIR, - E, - F, - S, - EE, - FF, - SE, - ES - }; - - /** - * Look up the description information for a pattern. - * - * @param name The name of the pattern. - * @return The pattern description or null. - */ - public static short[] lookup(String name) - { - if (name.equals("N")) - return noise_pattern_N; - else if (name.equals("K")) - return noise_pattern_K; - else if (name.equals("X")) - return noise_pattern_X; - else if (name.equals("NN")) - return noise_pattern_NN; - else if (name.equals("NK")) - return noise_pattern_NK; - else if (name.equals("NX")) - return noise_pattern_NX; - else if (name.equals("XN")) - return noise_pattern_XN; - else if (name.equals("XK")) - return noise_pattern_XK; - else if (name.equals("XX")) - return noise_pattern_XX; - else if (name.equals("KN")) - return noise_pattern_KN; - else if (name.equals("KK")) - return noise_pattern_KK; - else if (name.equals("KX")) - return noise_pattern_KX; - else if (name.equals("IN")) - return noise_pattern_IN; - else if (name.equals("IK")) - return noise_pattern_IK; - else if (name.equals("IX")) - return noise_pattern_IX; - else if (name.equals("XXfallback")) - return noise_pattern_XXfallback; - else if (name.equals("Xnoidh")) - return noise_pattern_Xnoidh; - else if (name.equals("NXnoidh")) - return noise_pattern_NXnoidh; - else if (name.equals("XXnoidh")) - return noise_pattern_XXnoidh; - else if (name.equals("KXnoidh")) - return noise_pattern_KXnoidh; - else if (name.equals("IKnoidh")) - return noise_pattern_IKnoidh; - else if (name.equals("IXnoidh")) - return noise_pattern_IXnoidh; - else if (name.equals("NNhfs")) - return noise_pattern_NNhfs; - else if (name.equals("NKhfs")) - return noise_pattern_NKhfs; - else if (name.equals("NXhfs")) - return noise_pattern_NXhfs; - else if (name.equals("XNhfs")) - return noise_pattern_XNhfs; - else if (name.equals("XKhfs")) - return noise_pattern_XKhfs; - else if (name.equals("XXhfs")) - return noise_pattern_XXhfs; - else if (name.equals("KNhfs")) - return noise_pattern_KNhfs; - else if (name.equals("KKhfs")) - return noise_pattern_KKhfs; - else if (name.equals("KXhfs")) - return noise_pattern_KXhfs; - else if (name.equals("INhfs")) - return noise_pattern_INhfs; - else if (name.equals("IKhfs")) - return noise_pattern_IKhfs; - else if (name.equals("IXhfs")) - return noise_pattern_IXhfs; - else if (name.equals("XXfallback+hfs")) - return noise_pattern_XXfallback_hfs; - else if (name.equals("NXnoidh+hfs")) - return noise_pattern_NXnoidh_hfs; - else if (name.equals("XXnoidh+hfs")) - return noise_pattern_XXnoidh_hfs; - else if (name.equals("KXnoidh+hfs")) - return noise_pattern_KXnoidh_hfs; - else if (name.equals("IKnoidh+hfs")) - return noise_pattern_IKnoidh_hfs; - else if (name.equals("IXnoidh+hfs")) - return noise_pattern_IXnoidh_hfs; - return null; - } - - /** - * Reverses the local and remote flags for a pattern. - * - * @param flags The flags, assuming that the initiator is "local". - * @return The reversed flags, with the responder now being "local". - */ - public static short reverseFlags(short flags) - { - return (short)(((flags >> 8) & 0x00FF) | ((flags << 8) & 0xFF00)); - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/SymmetricState.java b/src/main/java/com/southernstorm/noise/protocol/SymmetricState.java deleted file mode 100644 index 7b6451c5b..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/SymmetricState.java +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. - * - * 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: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * 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. - */ - -package com.southernstorm.noise.protocol; - -import javax.crypto.BadPaddingException; -import javax.crypto.ShortBufferException; -import java.io.UnsupportedEncodingException; -import java.security.DigestException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -/** - * Symmetric state for helping manage a Noise handshake. - */ -class SymmetricState implements Destroyable { - - private String name; - private CipherState cipher; - private MessageDigest hash; - private byte[] ck; - private byte[] h; - private byte[] prev_h; - - /** - * Constructs a new symmetric state object. - * - * @param protocolName The name of the Noise protocol, which is assumed to be valid. - * @param cipherName The name of the cipher within protocolName. - * @param hashName The name of the hash within protocolName. - * - * @throws NoSuchAlgorithmException The cipher or hash algorithm in the - * protocol name is not supported. - */ - public SymmetricState(String protocolName, String cipherName, String hashName) throws NoSuchAlgorithmException - { - name = protocolName; - cipher = Noise.createCipher(cipherName); - hash = Noise.createHash(hashName); - int hashLength = hash.getDigestLength(); - ck = new byte [hashLength]; - h = new byte [hashLength]; - prev_h = new byte [hashLength]; - - byte[] protocolNameBytes; - try { - protocolNameBytes = protocolName.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - // If UTF-8 is not supported, then we are definitely in trouble! - throw new UnsupportedOperationException("UTF-8 encoding is not supported"); - } - - if (protocolNameBytes.length <= hashLength) { - System.arraycopy(protocolNameBytes, 0, h, 0, protocolNameBytes.length); - Arrays.fill(h, protocolNameBytes.length, h.length, (byte)0); - } else { - hashOne(protocolNameBytes, 0, protocolNameBytes.length, h, 0, h.length); - } - - System.arraycopy(h, 0, ck, 0, hashLength); - } - - /** - * Gets the name of the Noise protocol. - * - * @return The protocol name. - */ - public String getProtocolName() - { - return name; - } - - /** - * Gets the length of MAC values in the current state. - * - * @return The length of the MAC value for the underlying cipher - * or zero if the cipher has not yet been initialized with a key. - */ - public int getMACLength() - { - return cipher.getMACLength(); - } - - /** - * Mixes data into the chaining key. - * - * @param data The buffer containing the data to mix in. - * @param offset The offset of the first data byte to mix in. - * @param length The number of bytes to mix in. - */ - public void mixKey(byte[] data, int offset, int length) - { - int keyLength = cipher.getKeyLength(); - byte[] tempKey = new byte [keyLength]; - try { - hkdf(ck, 0, ck.length, data, offset, length, ck, 0, ck.length, tempKey, 0, keyLength); - cipher.initializeKey(tempKey, 0); - } finally { - Noise.destroy(tempKey); - } - } - - /** - * Mixes data into the handshake hash. - * - * @param data The buffer containing the data to mix in. - * @param offset The offset of the first data byte to mix in. - * @param length The number of bytes to mix in. - */ - public void mixHash(byte[] data, int offset, int length) - { - hashTwo(h, 0, h.length, data, offset, length, h, 0, h.length); - } - - /** - * Mixes a pre-shared key into the chaining key and handshake hash. - * - * @param key The pre-shared key value. - */ - public void mixPreSharedKey(byte[] key) - { - byte[] temp = new byte [hash.getDigestLength()]; - try { - hkdf(ck, 0, ck.length, key, 0, key.length, ck, 0, ck.length, temp, 0, temp.length); - mixHash(temp, 0, temp.length); - } finally { - Noise.destroy(temp); - } - } - - /** - * Mixes a pre-supplied public key into the handshake hash. - * - * @param dh The object containing the public key. - */ - public void mixPublicKey(DHState dh) - { - byte[] temp = new byte [dh.getPublicKeyLength()]; - try { - dh.getPublicKey(temp, 0); - mixHash(temp, 0, temp.length); - } finally { - Noise.destroy(temp); - } - } - - /** - * Mixes a pre-supplied public key into the chaining key. - * - * @param dh The object containing the public key. - */ - public void mixPublicKeyIntoCK(DHState dh) - { - byte[] temp = new byte [dh.getPublicKeyLength()]; - try { - dh.getPublicKey(temp, 0); - mixKey(temp, 0, temp.length); - } finally { - Noise.destroy(temp); - } - } - - /** - * Encrypts a block of plaintext and mixes the ciphertext into the handshake hash. - * - * @param plaintext The buffer containing the plaintext to encrypt. - * @param plaintextOffset The offset within the plaintext buffer of the - * first byte or plaintext data. - * @param ciphertext The buffer to place the ciphertext in. This can - * be the same as the plaintext buffer. - * @param ciphertextOffset The first offset within the ciphertext buffer - * to place the ciphertext and the MAC tag. - * @param length The length of the plaintext. - * @return The length of the ciphertext plus the MAC tag. - * - * @throws ShortBufferException There is not enough space in the - * ciphertext buffer for the encrypted data plus MAC value. - * - * The plaintext and ciphertext buffers can be the same for in-place - * encryption. In that case, plaintextOffset must be identical to - * ciphertextOffset. - * - * There must be enough space in the ciphertext buffer to accomodate - * length + getMACLength() bytes of data starting at ciphertextOffset. - */ - public int encryptAndHash(byte[] plaintext, int plaintextOffset, byte[] ciphertext, int ciphertextOffset, int length) throws ShortBufferException - { - int ciphertextLength = cipher.encryptWithAd(h, plaintext, plaintextOffset, ciphertext, ciphertextOffset, length); - mixHash(ciphertext, ciphertextOffset, ciphertextLength); - return ciphertextLength; - } - - /** - * Decrypts a block of ciphertext and mixes it into the handshake hash. - * - * @param ciphertext The buffer containing the ciphertext to decrypt. - * @param ciphertextOffset The offset within the ciphertext buffer of - * the first byte of ciphertext data. - * @param plaintext The buffer to place the plaintext in. This can be - * the same as the ciphertext buffer. - * @param plaintextOffset The first offset within the plaintext buffer - * to place the plaintext. - * @param length The length of the incoming ciphertext plus the MAC tag. - * @return The length of the plaintext with the MAC tag stripped off. - * - * @throws ShortBufferException There is not enough space in the plaintext - * buffer for the decrypted data. - * - * @throws BadPaddingException The MAC value failed to verify. - * - * The plaintext and ciphertext buffers can be the same for in-place - * decryption. In that case, ciphertextOffset must be identical to - * plaintextOffset. - */ - public int decryptAndHash(byte[] ciphertext, int ciphertextOffset, byte[] plaintext, int plaintextOffset, int length) throws ShortBufferException, BadPaddingException - { - System.arraycopy(h, 0, prev_h, 0, h.length); - mixHash(ciphertext, ciphertextOffset, length); - return cipher.decryptWithAd(prev_h, ciphertext, ciphertextOffset, plaintext, plaintextOffset, length); - } - - /** - * Splits the symmetric state into two ciphers for session encryption. - * - * @return The pair of ciphers for sending and receiving. - */ - public CipherStatePair split() - { - return split(new byte[0], 0, 0); - } - - /** - * Splits the symmetric state into two ciphers for session encryption, - * and optionally mixes in a secondary symmetric key. - * - * @param secondaryKey The buffer containing the secondary key. - * @param offset The offset of the first secondary key byte. - * @param length The length of the secondary key in bytes, which - * must be either 0 or 32. - * @return The pair of ciphers for sending and receiving. - * - * @throws IllegalArgumentException The length is not 0 or 32. - */ - public CipherStatePair split(byte[] secondaryKey, int offset, int length) - { - if (length != 0 && length != 32) - throw new IllegalArgumentException("Secondary keys must be 0 or 32 bytes in length"); - int keyLength = cipher.getKeyLength(); - byte[] k1 = new byte [keyLength]; - byte[] k2 = new byte [keyLength]; - try { - hkdf(ck, 0, ck.length, secondaryKey, offset, length, k1, 0, k1.length, k2, 0, k2.length); - CipherState c1 = null; - CipherState c2 = null; - CipherStatePair pair = null; - try { - c1 = cipher.fork(k1, 0); - c2 = cipher.fork(k2, 0); - pair = new CipherStatePair(c1, c2); - } finally { - if (c1 == null || c2 == null || pair == null) { - // Could not create some of the objects. Clean up the others - // to avoid accidental leakage of k1 or k2. - if (c1 != null) - c1.destroy(); - if (c2 != null) - c2.destroy(); - pair = null; - } - } - return pair; - } finally { - Noise.destroy(k1); - Noise.destroy(k2); - } - } - - /** - * Gets the current value of the handshake hash. - * - * @return The handshake hash. This must not be modified by the caller. - * - * The handshake hash value is only of use to the application after - * split() has been called. - */ - public byte[] getHandshakeHash() - { - return h; - } - - @Override - public void destroy() { - if (cipher != null) { - cipher.destroy(); - cipher = null; - } - if (hash != null) { - // The built-in fallback implementations are destroyable. - // JCA/JCE implementations aren't, so try reset() instead. - if (hash instanceof Destroyable) - ((Destroyable)hash).destroy(); - else - hash.reset(); - hash = null; - } - if (ck != null) { - Noise.destroy(ck); - ck = null; - } - if (h != null) { - Noise.destroy(h); - h = null; - } - if (prev_h != null) { - Noise.destroy(prev_h); - prev_h = null; - } - } - - /** - * Hashes a single data buffer. - * - * @param data The buffer containing the data to hash. - * @param offset Offset into the data buffer of the first byte to hash. - * @param length Length of the data to be hashed. - * @param output The buffer to receive the output hash value. - * @param outputOffset Offset into the output buffer to place the hash value. - * @param outputLength The length of the hash output. - * - * The output buffer can be the same as the input data buffer. - */ - private void hashOne(byte[] data, int offset, int length, byte[] output, int outputOffset, int outputLength) - { - hash.reset(); - hash.update(data, offset, length); - try { - hash.digest(output, outputOffset, outputLength); - } catch (DigestException e) { - Arrays.fill(output, outputOffset, outputLength, (byte)0); - } - } - - /** - * Hashes two data buffers. - * - * @param data1 The buffer containing the first data to hash. - * @param offset1 Offset into the first data buffer of the first byte to hash. - * @param length1 Length of the first data to be hashed. - * @param data2 The buffer containing the second data to hash. - * @param offset2 Offset into the second data buffer of the first byte to hash. - * @param length2 Length of the second data to be hashed. - * @param output The buffer to receive the output hash value. - * @param outputOffset Offset into the output buffer to place the hash value. - * @param outputLength The length of the hash output. - * - * The output buffer can be same as either of the input buffers. - */ - private void hashTwo(byte[] data1, int offset1, int length1, - byte[] data2, int offset2, int length2, - byte[] output, int outputOffset, int outputLength) - { - hash.reset(); - hash.update(data1, offset1, length1); - hash.update(data2, offset2, length2); - try { - hash.digest(output, outputOffset, outputLength); - } catch (DigestException e) { - Arrays.fill(output, outputOffset, outputLength, (byte)0); - } - } - - /** - * Computes a HMAC value using key and data values. - * - * @param key The buffer that contains the key. - * @param keyOffset The offset of the key in the key buffer. - * @param keyLength The length of the key in bytes. - * @param data The buffer that contains the data. - * @param dataOffset The offset of the data in the data buffer. - * @param dataLength The length of the data in bytes. - * @param output The output buffer to place the HMAC value in. - * @param outputOffset Offset into the output buffer for the HMAC value. - * @param outputLength The length of the HMAC output. - */ - private void hmac(byte[] key, int keyOffset, int keyLength, - byte[] data, int dataOffset, int dataLength, - byte[] output, int outputOffset, int outputLength) - { - // In all of the algorithms of interest to us, the block length - // is twice the size of the hash length. - int hashLength = hash.getDigestLength(); - int blockLength = hashLength * 2; - byte[] block = new byte [blockLength]; - int index; - try { - if (keyLength <= blockLength) { - System.arraycopy(key, keyOffset, block, 0, keyLength); - Arrays.fill(block, keyLength, blockLength, (byte)0); - } else { - hash.reset(); - hash.update(key, keyOffset, keyLength); - hash.digest(block, 0, hashLength); - Arrays.fill(block, hashLength, blockLength, (byte)0); - } - for (index = 0; index < blockLength; ++index) - block[index] ^= (byte)0x36; - hash.reset(); - hash.update(block, 0, blockLength); - hash.update(data, dataOffset, dataLength); - hash.digest(output, outputOffset, hashLength); - for (index = 0; index < blockLength; ++index) - block[index] ^= (byte)(0x36 ^ 0x5C); - hash.reset(); - hash.update(block, 0, blockLength); - hash.update(output, outputOffset, hashLength); - hash.digest(output, outputOffset, outputLength); - } catch (DigestException e) { - Arrays.fill(output, outputOffset, outputLength, (byte)0); - } finally { - Noise.destroy(block); - } - } - - /** - * Computes a HKDF value. - * - * @param key The buffer that contains the key. - * @param keyOffset The offset of the key in the key buffer. - * @param keyLength The length of the key in bytes. - * @param data The buffer that contains the data. - * @param dataOffset The offset of the data in the data buffer. - * @param dataLength The length of the data in bytes. - * @param output1 The first output buffer. - * @param output1Offset Offset into the first output buffer. - * @param output1Length Length of the first output which can be - * less than the hash length. - * @param output2 The second output buffer. - * @param output2Offset Offset into the second output buffer. - * @param output2Length Length of the second output which can be - * less than the hash length. - */ - private void hkdf(byte[] key, int keyOffset, int keyLength, - byte[] data, int dataOffset, int dataLength, - byte[] output1, int output1Offset, int output1Length, - byte[] output2, int output2Offset, int output2Length) - { - int hashLength = hash.getDigestLength(); - byte[] tempKey = new byte [hashLength]; - byte[] tempHash = new byte [hashLength + 1]; - try { - hmac(key, keyOffset, keyLength, data, dataOffset, dataLength, tempKey, 0, hashLength); - tempHash[0] = (byte)0x01; - hmac(tempKey, 0, hashLength, tempHash, 0, 1, tempHash, 0, hashLength); - System.arraycopy(tempHash, 0, output1, output1Offset, output1Length); - tempHash[hashLength] = (byte)0x02; - hmac(tempKey, 0, hashLength, tempHash, 0, hashLength + 1, tempHash, 0, hashLength); - System.arraycopy(tempHash, 0, output2, output2Offset, output2Length); - } finally { - Noise.destroy(tempKey); - Noise.destroy(tempHash); - } - } -} diff --git a/src/main/java/com/southernstorm/noise/protocol/package-info.java b/src/main/java/com/southernstorm/noise/protocol/package-info.java deleted file mode 100644 index ef85f00b8..000000000 --- a/src/main/java/com/southernstorm/noise/protocol/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ - -/** - * Provides classes for communicating via the Noise protocol. - * - * Reference: http://noiseprotocol.org - */ -package com.southernstorm.noise.protocol; diff --git a/src/main/java/io/libp2p/discovery/mdns/ServiceInfo.java b/src/main/java/io/libp2p/discovery/mdns/ServiceInfo.java index cd7b84d85..482daba5e 100755 --- a/src/main/java/io/libp2p/discovery/mdns/ServiceInfo.java +++ b/src/main/java/io/libp2p/discovery/mdns/ServiceInfo.java @@ -223,13 +223,7 @@ public static ServiceInfo create( * @see java.lang.Object#clone() */ @Override - public ServiceInfo clone() { - try { - return (ServiceInfo) super.clone(); - } catch (CloneNotSupportedException exception) { - // clone is supported - return null; - } + public ServiceInfo clone() throws CloneNotSupportedException { + return (ServiceInfo) super.clone(); } - } diff --git a/src/main/java/io/libp2p/discovery/mdns/impl/DNSRecord.java b/src/main/java/io/libp2p/discovery/mdns/impl/DNSRecord.java index a16ee1df0..bdc3e9ddd 100644 --- a/src/main/java/io/libp2p/discovery/mdns/impl/DNSRecord.java +++ b/src/main/java/io/libp2p/discovery/mdns/impl/DNSRecord.java @@ -4,21 +4,20 @@ package io.libp2p.discovery.mdns.impl; +import io.libp2p.discovery.mdns.impl.DNSOutgoing.MessageOutputStream; +import io.libp2p.discovery.mdns.impl.constants.DNSRecordClass; +import io.libp2p.discovery.mdns.impl.constants.DNSRecordType; +import io.libp2p.discovery.mdns.impl.util.ByteWrangler; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.io.DataOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; - -import io.libp2p.discovery.mdns.impl.constants.DNSRecordClass; -import io.libp2p.discovery.mdns.impl.constants.DNSRecordType; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -import io.libp2p.discovery.mdns.impl.DNSOutgoing.MessageOutputStream; - -import io.libp2p.discovery.mdns.impl.util.ByteWrangler; +import java.util.Objects; /** @@ -46,6 +45,11 @@ public boolean equals(Object other) { return (other instanceof DNSRecord) && super.equals(other) && sameValue((DNSRecord) other); } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), _ttl, _created); + } + abstract boolean sameValue(DNSRecord other); /** diff --git a/src/main/java/io/libp2p/discovery/mdns/impl/JmDNSImpl.java b/src/main/java/io/libp2p/discovery/mdns/impl/JmDNSImpl.java index 101e07359..e8ab32edb 100644 --- a/src/main/java/io/libp2p/discovery/mdns/impl/JmDNSImpl.java +++ b/src/main/java/io/libp2p/discovery/mdns/impl/JmDNSImpl.java @@ -4,6 +4,17 @@ package io.libp2p.discovery.mdns.impl; +import io.libp2p.discovery.mdns.AnswerListener; +import io.libp2p.discovery.mdns.JmDNS; +import io.libp2p.discovery.mdns.ServiceInfo; +import io.libp2p.discovery.mdns.impl.constants.DNSConstants; +import io.libp2p.discovery.mdns.impl.constants.DNSRecordType; +import io.libp2p.discovery.mdns.impl.tasks.Responder; +import io.libp2p.discovery.mdns.impl.tasks.ServiceResolver; +import io.libp2p.discovery.mdns.impl.util.NamedThreadFactory; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.io.IOException; import java.net.DatagramPacket; import java.net.Inet6Address; @@ -12,22 +23,23 @@ import java.net.MulticastSocket; import java.net.SocketAddress; import java.net.SocketException; -import java.util.*; -import java.util.concurrent.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantLock; -import io.libp2p.discovery.mdns.AnswerListener; -import io.libp2p.discovery.mdns.JmDNS; -import io.libp2p.discovery.mdns.ServiceInfo; -import io.libp2p.discovery.mdns.impl.constants.DNSRecordType; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import io.libp2p.discovery.mdns.impl.constants.DNSConstants; -import io.libp2p.discovery.mdns.impl.tasks.Responder; -import io.libp2p.discovery.mdns.impl.tasks.ServiceResolver; -import io.libp2p.discovery.mdns.impl.util.NamedThreadFactory; - /** * Derived from mDNS implementation in Java. * @@ -39,7 +51,7 @@ public class JmDNSImpl extends JmDNS { /** * This is the multicast group, we are listening to for multicast DNS messages. */ - private volatile InetAddress _group; + private volatile InetAddress _group; /** * This is our multicast socket. */ @@ -77,11 +89,9 @@ public class JmDNSImpl extends JmDNS { /** * Create an instance of JmDNS and bind it to a specific network interface given its IP-address. * - * @param address - * IP address to bind to. - * @param name - * name of the newly created JmDNS - * @exception IOException + * @param address IP address to bind to. + * @param name name of the newly created JmDNS + * @throws IOException */ public JmDNSImpl(InetAddress address, String name) { super(); @@ -192,7 +202,7 @@ public HostInfo getLocalHost() { void handleServiceAnswers(List answers) { DNSRecord ptr = answers.get(0); - if(!DNSRecordType.TYPE_PTR.equals(ptr.getRecordType())) + if (!DNSRecordType.TYPE_PTR.equals(ptr.getRecordType())) return; List list = _answerListeners.get(ptr.getKey()); @@ -201,7 +211,7 @@ void handleServiceAnswers(List answers) { synchronized (list) { listCopy = new ArrayList<>(list); } - for (final AnswerListener listener: listCopy) { + for (final AnswerListener listener : listCopy) { _executor.submit(new Runnable() { @Override public void run() { @@ -248,7 +258,7 @@ public void registerService(ServiceInfo infoAbstract) throws IOException { /** * Handle an incoming response. Cache answers, and pass them on to the appropriate questions. * - * @exception IOException + * @throws IOException */ void handleResponse(DNSIncoming msg) throws IOException { List allAnswers = msg.getAllAnswers(); @@ -288,7 +298,7 @@ private List aRecordsLast(List allAnswers) { DNSRecordType type = answer.getRecordType(); if (type.equals(DNSRecordType.TYPE_A) || type.equals(DNSRecordType.TYPE_AAAA)) { arecords.add(answer); - } else if(type.equals(DNSRecordType.TYPE_PTR)) { + } else if (type.equals(DNSRecordType.TYPE_PTR)) { ret.add(0, answer); } else { ret.add(answer); @@ -305,7 +315,7 @@ private List aRecordsLast(List allAnswers) { * @param in * @param addr * @param port - * @exception IOException + * @throws IOException */ void handleQuery(DNSIncoming in, InetAddress addr, int port) throws IOException { logger.debug("{} handle query: {}", this.getName(), in); @@ -322,7 +332,7 @@ void handleQuery(DNSIncoming in, InetAddress addr, int port) throws IOException * Send an outgoing multicast DNS message. * * @param out - * @exception IOException + * @throws IOException */ public void send(DNSOutgoing out) throws IOException { if (!out.isEmpty()) { @@ -386,21 +396,22 @@ public void stop() { // close socket this.closeMulticastSocket(); - while(true) { - boolean allDone = _executor.isShutdown(); - - for (Future f : shutdowns) - allDone &= f.isDone(); - - if (allDone) - break; + logger.debug("JmDNS waiting for service stop..."); + for (Future shutdown : shutdowns) { try { - TimeUnit.MILLISECONDS.sleep(100); - } catch(InterruptedException e) { } + shutdown.get(10, TimeUnit.SECONDS); + } catch (CancellationException e) { + logger.trace("Task was already cancelled", e); + } catch (InterruptedException e) { + logger.trace("Stopping was interrupted", e); + Thread.currentThread().interrupt(); + } catch (ExecutionException | TimeoutException e) { + logger.debug("Exception when stopping JmDNS: ", e); + throw new RuntimeException(e); + } } - - logger.debug("JmDNS Stopping."); + logger.debug("JmDNS stopped."); } /** diff --git a/src/main/java/io/libp2p/discovery/mdns/impl/ServiceInfoImpl.java b/src/main/java/io/libp2p/discovery/mdns/impl/ServiceInfoImpl.java index 2befc1a22..27ddfdd78 100644 --- a/src/main/java/io/libp2p/discovery/mdns/impl/ServiceInfoImpl.java +++ b/src/main/java/io/libp2p/discovery/mdns/impl/ServiceInfoImpl.java @@ -4,18 +4,25 @@ package io.libp2p.discovery.mdns.impl; -import java.io.IOException; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.*; - +import io.libp2p.discovery.mdns.ServiceInfo; import io.libp2p.discovery.mdns.impl.constants.DNSRecordClass; import io.libp2p.discovery.mdns.impl.util.ByteWrangler; -import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; -import io.libp2p.discovery.mdns.ServiceInfo; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * JmDNS service information. @@ -381,6 +388,7 @@ public ServiceInfoImpl clone() { ServiceInfoImpl serviceInfo = new ServiceInfoImpl(this.getQualifiedNameMap(), _port, _weight, _priority, _text); serviceInfo._ipv6Addresses.addAll(Arrays.asList(getInet6Addresses())); serviceInfo._ipv4Addresses.addAll(Arrays.asList(getInet4Addresses())); + serviceInfo._server = _server; return serviceInfo; } diff --git a/src/main/kotlin/io/libp2p/pubsub/AbstractRouter.kt b/src/main/kotlin/io/libp2p/pubsub/AbstractRouter.kt index a2ab2c9dc..ee31d4e92 100644 --- a/src/main/kotlin/io/libp2p/pubsub/AbstractRouter.kt +++ b/src/main/kotlin/io/libp2p/pubsub/AbstractRouter.kt @@ -43,9 +43,11 @@ abstract class AbstractRouter : P2PServiceSemiDuplex(), PubsubRouter, PubsubRout private val peerTopics = MultiSet() private var msgHandler: (Rpc.Message) -> CompletableFuture = { RESULT_VALID } - var maxSeenMessagesSizeSet = 10000 + var maxSeenMessagesLimit = 10000 var validator: PubsubMessageValidator = PubsubMessageValidator.nopValidator() - val seenMessages by lazy { createLRUMap>(maxSeenMessagesSizeSet) } + protected open val seenMessages by lazy { + createLRUMap>(maxSeenMessagesLimit) + } val subscribedTopics = linkedSetOf() val pendingRpcParts = linkedMapOf>() private var debugHandler: ChannelHandler? = null diff --git a/src/main/kotlin/io/libp2p/pubsub/gossip/GossipParams.kt b/src/main/kotlin/io/libp2p/pubsub/gossip/GossipParams.kt index 350b66102..29052d33c 100644 --- a/src/main/kotlin/io/libp2p/pubsub/gossip/GossipParams.kt +++ b/src/main/kotlin/io/libp2p/pubsub/gossip/GossipParams.kt @@ -98,6 +98,11 @@ data class GossipParams( */ val heartbeatInterval: Duration = 1.seconds, + /** + * Expiry time for cache of seen message ids + */ + val seenTTL: Duration = 2.minutes, + /** * [maxPrunePeers] controls the number of peers to include in prune Peer eXchange. * When we prune a peer that's eligible for PX (has a good score, etc), we will try to @@ -315,14 +320,18 @@ data class GossipPeerScoreParams( * - attempting to re-graft before the prune backoff time has elapsed. * - not following up in IWANT requests for messages advertised with IHAVE. * - * The value of the parameter is the square of the counter, which decays with [behaviourPenaltyDecay]. + * The value of the parameter is the square of the counter over the threshold, + * which decays with [behaviourPenaltyDecay]. * The weight of the parameter MUST be negative (or zero to disable). */ val behaviourPenaltyWeight: Weight = 0.0, - /** See [behaviourPenaltyDecay] */ + /** See [behaviourPenaltyWeight] */ val behaviourPenaltyDecay: Double = 0.9, + /** See [behaviourPenaltyWeight] */ + val behaviourPenaltyThreshold: Double = 1.0, + /** the decay interval for parameter counters. */ val decayInterval: Duration = 1.minutes, @@ -342,6 +351,7 @@ data class GossipPeerScoreParams( check(behaviourPenaltyWeight == 0.0 || (behaviourPenaltyDecay > 0.0 && behaviourPenaltyDecay <= 1.0), "behaviourPenaltyDecay should be in range (0.0, 1.0]" ) + check(behaviourPenaltyThreshold >= 0.0, "behaviourPenaltyThreshold should be >= 0") } companion object { @JvmStatic diff --git a/src/main/kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt b/src/main/kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt index 6ba6b9eee..2c49055ca 100644 --- a/src/main/kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt +++ b/src/main/kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt @@ -1,5 +1,7 @@ package io.libp2p.pubsub.gossip +import com.google.common.base.Ticker +import com.google.common.cache.CacheBuilder import io.libp2p.core.InternalErrorException import io.libp2p.core.PeerId import io.libp2p.core.multiformats.Protocol @@ -67,6 +69,17 @@ open class GossipRouter @JvmOverloads constructor( TimeUnit.MILLISECONDS ) } + override val seenMessages by lazy { + val t: Ticker = object : Ticker() { + // Ticker operates with nanos and handles overflows correctly + override fun read() = curTimeMillis() * 1_000_000 + } + CacheBuilder.newBuilder() + .ticker(t) + .expireAfterWrite(params.seenTTL) + .build>() + .asMap() + } private fun setBackOff(peer: PeerHandler, topic: Topic) = setBackOff(peer, topic, params.pruneBackoff.toMillis()) private fun setBackOff(peer: PeerHandler, topic: Topic, delay: Long) { diff --git a/src/main/kotlin/io/libp2p/pubsub/gossip/GossipScore.kt b/src/main/kotlin/io/libp2p/pubsub/gossip/GossipScore.kt index 6e8e17e3f..35054eb71 100644 --- a/src/main/kotlin/io/libp2p/pubsub/gossip/GossipScore.kt +++ b/src/main/kotlin/io/libp2p/pubsub/gossip/GossipScore.kt @@ -132,7 +132,10 @@ class GossipScore( (peersInIp - peerParams.ipColocationFactorThreshold) ).toDouble().pow(2) * peerParams.ipColocationFactorWeight - val routerPenalty = peerScore.behaviorPenalty * peerParams.behaviourPenaltyWeight + val behaviorExcess = peerScore.behaviorPenalty - peerParams.behaviourPenaltyThreshold + val routerPenalty = + if (behaviorExcess < 0) 0.0 + else behaviorExcess.pow(2) * peerParams.behaviourPenaltyWeight return topicsScore + appScore + ipColocationPenalty + routerPenalty } diff --git a/src/main/kotlin/io/libp2p/pubsub/gossip/builders/GossipParamsBuilder.kt b/src/main/kotlin/io/libp2p/pubsub/gossip/builders/GossipParamsBuilder.kt index c91c3fed8..9ba32df37 100644 --- a/src/main/kotlin/io/libp2p/pubsub/gossip/builders/GossipParamsBuilder.kt +++ b/src/main/kotlin/io/libp2p/pubsub/gossip/builders/GossipParamsBuilder.kt @@ -30,6 +30,8 @@ class GossipParamsBuilder { private var heartbeatInterval: Duration? = null + private var seenTTL: Duration? = null + private var maxPrunePeers: Int? = null private var pruneBackoff: Duration? = null @@ -61,6 +63,7 @@ class GossipParamsBuilder { this.gossipSize = source.gossipSize this.gossipHistoryLength = source.gossipHistoryLength this.heartbeatInterval = source.heartbeatInterval + this.seenTTL = source.seenTTL this.maxPrunePeers = source.maxPrunePeers this.pruneBackoff = source.pruneBackoff this.floodPublish = source.floodPublish @@ -95,6 +98,8 @@ class GossipParamsBuilder { fun heartbeatInterval(value: Duration): GossipParamsBuilder = apply { heartbeatInterval = value } + fun seenTTL(value: Duration): GossipParamsBuilder = apply { seenTTL = value } + fun maxPrunePeers(value: Int): GossipParamsBuilder = apply { maxPrunePeers = value } fun pruneBackoff(value: Duration): GossipParamsBuilder = apply { pruneBackoff = value } @@ -141,6 +146,7 @@ class GossipParamsBuilder { gossipSize = gossipSize!!, gossipHistoryLength = gossipHistoryLength!!, heartbeatInterval = heartbeatInterval!!, + seenTTL = seenTTL!!, maxPrunePeers = maxPrunePeers!!, pruneBackoff = pruneBackoff!!, floodPublish = floodPublish!!, @@ -176,6 +182,7 @@ class GossipParamsBuilder { check(gossipSize != null, { "gossipSize must not be null" }) check(gossipHistoryLength != null, { "gossipHistoryLength must not be null" }) check(heartbeatInterval != null, { "heartbeatInterval must not be null" }) + check(seenTTL != null, { "seenTTL must not be null" }) check(maxPrunePeers != null, { "maxPrunePeers must not be null" }) check(pruneBackoff != null, { "pruneBackoff must not be null" }) check(floodPublish != null, { "floodPublish must not be null" }) diff --git a/src/main/kotlin/io/libp2p/security/SecureChannelError.kt b/src/main/kotlin/io/libp2p/security/SecureChannelError.kt index fd2e8d016..1422383e6 100644 --- a/src/main/kotlin/io/libp2p/security/SecureChannelError.kt +++ b/src/main/kotlin/io/libp2p/security/SecureChannelError.kt @@ -1,8 +1,13 @@ package io.libp2p.security -open class SecureChannelError : Exception() +open class SecureChannelError : Exception { + constructor() : super() + constructor(message: String, cause: Throwable) : super(message, cause) +} open class SecureHandshakeError : SecureChannelError() class InvalidRemotePubKey : SecureHandshakeError() class InvalidInitialPacket : SecureHandshakeError() + +class CantDecryptInboundException(message: String, cause: Throwable) : SecureChannelError(message, cause) \ No newline at end of file diff --git a/src/main/kotlin/io/libp2p/security/noise/NoiseXXCodec.kt b/src/main/kotlin/io/libp2p/security/noise/NoiseXXCodec.kt index 3cccbbaa4..e992a982e 100644 --- a/src/main/kotlin/io/libp2p/security/noise/NoiseXXCodec.kt +++ b/src/main/kotlin/io/libp2p/security/noise/NoiseXXCodec.kt @@ -3,6 +3,7 @@ package io.libp2p.security.noise import com.google.common.base.Throwables import com.southernstorm.noise.protocol.CipherState import io.libp2p.etc.types.toByteArray +import io.libp2p.security.CantDecryptInboundException import io.libp2p.security.SecureChannelError import io.netty.buffer.ByteBuf import io.netty.buffer.Unpooled @@ -10,6 +11,7 @@ import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.MessageToMessageCodec import org.apache.logging.log4j.LogManager import java.io.IOException +import java.security.GeneralSecurityException private val logger = LogManager.getLogger(NoiseXXSecureChannel::class.java.name) @@ -25,7 +27,11 @@ class NoiseXXCodec(val aliceCipher: CipherState, val bobCipher: CipherState) : M override fun decode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList) { val buf = msg.toByteArray() - val decryptLen = bobCipher.decryptWithAd(null, buf, 0, buf, 0, buf.size) + val decryptLen = try { + bobCipher.decryptWithAd(null, buf, 0, buf, 0, buf.size) + } catch (e: GeneralSecurityException) { + throw CantDecryptInboundException("Unable to decrypt a message from remote", e) + } out += Unpooled.wrappedBuffer(buf, 0, decryptLen) } diff --git a/src/test/kotlin/io/libp2p/pubsub/gossip/GossipScoreTest.kt b/src/test/kotlin/io/libp2p/pubsub/gossip/GossipScoreTest.kt new file mode 100644 index 000000000..208ace098 --- /dev/null +++ b/src/test/kotlin/io/libp2p/pubsub/gossip/GossipScoreTest.kt @@ -0,0 +1,58 @@ +package io.libp2p.pubsub.gossip + +import io.libp2p.core.PeerId +import io.libp2p.etc.types.minutes +import io.libp2p.etc.types.seconds +import io.libp2p.etc.util.P2PService +import io.libp2p.tools.schedulers.ControlledExecutorServiceImpl +import io.libp2p.tools.schedulers.TimeControllerImpl +import io.mockk.every +import io.mockk.mockk +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test + +class GossipScoreTest { + + @Test + fun `test misbehavior score threshold`() { + val peerId = PeerId.random() + val peerHandler = mockk() + every { peerHandler.peerId } returns peerId + every { peerHandler.getIP() } returns "127.0.0.1" + + val peerScoreParams = GossipPeerScoreParams( + decayInterval = 1.seconds, + behaviourPenaltyWeight = -1.0, + behaviourPenaltyDecay = 0.9, + behaviourPenaltyThreshold = 5.0 + ) + val scoreParams = GossipScoreParams(peerScoreParams) + val timeController = TimeControllerImpl() + val executor = ControlledExecutorServiceImpl(timeController) + + val score = GossipScore(scoreParams, executor, { timeController.time }) + + assertEquals(0.0, score.score(peerHandler)) + + // not hit threshold yet + score.notifyRouterMisbehavior(peerHandler, 5) + assertEquals(0.0, score.score(peerHandler)) + + // behaviourPenaltyThreshold reached + score.notifyRouterMisbehavior(peerHandler, 1) + assertTrue(score.score(peerHandler) < 0) + + // quadratic penalty + score.notifyRouterMisbehavior(peerHandler, 10) + assertTrue(score.score(peerHandler) < -50) + + // negative behaviour should not be forgotten so fast + timeController.addTime(10.seconds) + assertTrue(score.score(peerHandler) < 0) + + // time heals + timeController.addTime(10.minutes) + assertEquals(0.0, score.score(peerHandler)) + } +} \ No newline at end of file diff --git a/src/test/kotlin/io/libp2p/pubsub/gossip/GossipV1_1Tests.kt b/src/test/kotlin/io/libp2p/pubsub/gossip/GossipV1_1Tests.kt index b0cacab6a..36b16711f 100644 --- a/src/test/kotlin/io/libp2p/pubsub/gossip/GossipV1_1Tests.kt +++ b/src/test/kotlin/io/libp2p/pubsub/gossip/GossipV1_1Tests.kt @@ -10,6 +10,7 @@ import io.libp2p.core.pubsub.Subscriber import io.libp2p.core.pubsub.ValidationResult import io.libp2p.core.pubsub.createPubsubApi import io.libp2p.etc.types.millis +import io.libp2p.etc.types.minutes import io.libp2p.etc.types.seconds import io.libp2p.etc.types.times import io.libp2p.etc.types.toBytesBigEndian @@ -98,6 +99,32 @@ class GossipV1_1Tests { test.mockRouter.waitForMessage { it.publishCount > 0 } } + @Test + fun testSeenTTL() { + val test = TwoRoutersTest(GossipParams(seenTTL = 1.minutes)) + + test.mockRouter.subscribe("topic1") + val msg1 = newMessage("topic1", 0L, "Hello-1".toByteArray()) + test.gossipRouter.publish(msg1) + test.mockRouter.waitForMessage { it.publishCount == 1 } + assertTrue(test.mockRouter.inboundMessages.isEmpty()) + + test.fuzz.timeController.addTime(30.seconds) + val msg2 = newMessage("topic1", 1L, "Hello-2".toByteArray()) + test.gossipRouter.publish(msg2) + test.gossipRouter.publish(msg1) // should be in seen set + test.mockRouter.waitForMessage { it.publishCount == 1 } + assertTrue(test.mockRouter.inboundMessages.isEmpty()) + + test.fuzz.timeController.addTime(31.seconds) + val msg3 = newMessage("topic1", 2L, "Hello-3".toByteArray()) + test.gossipRouter.publish(msg3) + test.gossipRouter.publish(msg1) // should be purged from seen and transmitted again + test.mockRouter.waitForMessage { it.publishCount == 1 } + test.mockRouter.waitForMessage { it.publishCount == 1 } + assertTrue(test.mockRouter.inboundMessages.isEmpty()) + } + @Test fun unknownTopicTest() { val test = TwoRoutersTest() From 392f3f1bf27b57092ff474e9dd10797cd85c0ac0 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Tue, 10 Nov 2020 19:50:16 +0300 Subject: [PATCH 05/28] Bump version in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6bdadfa5e..ed3e08e96 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can jcenter() } - implementation 'io.libp2p:jvm-libp2p-minimal:0.5.5-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.6.0-RELEASE' ``` ### Using Maven ``` io.libp2p jvm-libp2p-minimal - 0.5.6-RELEASE + 0.6.0-RELEASE pom ``` From 7cbd90c4c70eedbd6c9a8d09c8c7084cafebc8f4 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Tue, 10 Nov 2020 20:02:11 +0300 Subject: [PATCH 06/28] Fix merge error --- .../kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/main/kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt b/src/main/kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt index 925de45f1..586516278 100644 --- a/src/main/kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt +++ b/src/main/kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt @@ -1,7 +1,5 @@ package io.libp2p.pubsub.gossip -import com.google.common.base.Ticker -import com.google.common.cache.CacheBuilder import io.libp2p.core.InternalErrorException import io.libp2p.core.PeerId import io.libp2p.core.multiformats.Protocol @@ -73,17 +71,6 @@ open class GossipRouter @JvmOverloads constructor( TimeUnit.MILLISECONDS ) } - override val seenMessages by lazy { - val t: Ticker = object : Ticker() { - // Ticker operates with nanos and handles overflows correctly - override fun read() = curTimeMillis() * 1_000_000 - } - CacheBuilder.newBuilder() - .ticker(t) - .expireAfterWrite(params.seenTTL) - .build>() - .asMap() - } override val seenMessages: SeenCache> by lazy { TTLSeenCache(SimpleSeenCache(), params.seenTTL, curTimeMillis) From 3827131c440d35295ef96c1f7c82d6da059602c3 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Wed, 11 Nov 2020 11:02:31 +0300 Subject: [PATCH 07/28] Fix master version to 0.6.0 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index d09c43631..d2185dadd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.5.8-RELEASE" +version = "0.6.0-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From cefb2ea68de81ea7820155217a5b0beed5418d4e Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Tue, 17 Nov 2020 14:46:28 +0300 Subject: [PATCH 08/28] Bump versions to 0.6.1 --- README.md | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ed3e08e96..7df5ab61b 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can jcenter() } - implementation 'io.libp2p:jvm-libp2p-minimal:0.6.0-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.6.1-RELEASE' ``` ### Using Maven ``` io.libp2p jvm-libp2p-minimal - 0.6.0-RELEASE + 0.6.1-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index fb4b276fd..fdcaaa804 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.7.0-RELEASE" +version = "0.6.1-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From d0ab43e15955b86d95c28a2cfef737e5657b0efb Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Thu, 19 Nov 2020 19:32:48 +0300 Subject: [PATCH 09/28] Bump version to 0.6.2 --- README.md | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ed3e08e96..a2d094c7a 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can jcenter() } - implementation 'io.libp2p:jvm-libp2p-minimal:0.6.0-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.6.2-RELEASE' ``` ### Using Maven ``` io.libp2p jvm-libp2p-minimal - 0.6.0-RELEASE + 0.6.2-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index fb4b276fd..1357a5c7c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.7.0-RELEASE" +version = "0.6.2-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 3167a8b0e894af9e8ac90819220b83219625a118 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Fri, 4 Dec 2020 16:51:45 +0300 Subject: [PATCH 10/28] Bump version to 0.6.3 --- README.md | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a2d094c7a..f01e3a615 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can jcenter() } - implementation 'io.libp2p:jvm-libp2p-minimal:0.6.2-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.6.3-RELEASE' ``` ### Using Maven ``` io.libp2p jvm-libp2p-minimal - 0.6.2-RELEASE + 0.6.3-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index e925e7716..f98f892eb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.6.2-RELEASE" +version = "0.6.3-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 46eae8d6fba2df80f57eec35a6212a1f2cfe1512 Mon Sep 17 00:00:00 2001 From: Meredith Baxter Date: Tue, 22 Dec 2020 13:26:19 -0500 Subject: [PATCH 11/28] Update version --- README.md | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ed3e08e96..c235eb9a1 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can jcenter() } - implementation 'io.libp2p:jvm-libp2p-minimal:0.6.0-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.6.4-RELEASE' ``` ### Using Maven ``` io.libp2p jvm-libp2p-minimal - 0.6.0-RELEASE + 0.6.4-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index f42b9ba87..592376c75 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.7.0-RELEASE" +version = "0.6.4-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From cc983084a25ecda8365baf2e880f60e60140abad Mon Sep 17 00:00:00 2001 From: mbaxter Date: Tue, 22 Dec 2020 14:09:24 -0500 Subject: [PATCH 12/28] Update comment Co-authored-by: Anton Nashatyrev --- src/main/kotlin/io/libp2p/pubsub/PubsubRouter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/io/libp2p/pubsub/PubsubRouter.kt b/src/main/kotlin/io/libp2p/pubsub/PubsubRouter.kt index 328e912df..2bc233722 100644 --- a/src/main/kotlin/io/libp2p/pubsub/PubsubRouter.kt +++ b/src/main/kotlin/io/libp2p/pubsub/PubsubRouter.kt @@ -29,7 +29,7 @@ interface PubsubMessage { override fun equals(other: Any?): Boolean /** - * WARNING: Use collision free functions only + * WARNING: Use collision resistant functions only * Else the HashMap collision attack vector is open */ override fun hashCode(): Int From 6e4917cba6ed2d17c613e72fea46fcb4716c73b5 Mon Sep 17 00:00:00 2001 From: Meredith Baxter Date: Fri, 5 Feb 2021 11:05:19 -0500 Subject: [PATCH 13/28] Update version to 0.7.0 --- README.md | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c235eb9a1..8907101f1 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Builds are published to JCenter. Maven Central mirrors JCenter, but updates can jcenter() } - implementation 'io.libp2p:jvm-libp2p-minimal:0.6.4-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.7.0-RELEASE' ``` ### Using Maven ``` io.libp2p jvm-libp2p-minimal - 0.6.4-RELEASE + 0.7.0-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index 592376c75..f42b9ba87 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ import java.nio.file.Paths // ./gradlew bintrayUpload -PbintrayUser= -PbintrayApiKey= group = "io.libp2p" -version = "0.6.4-RELEASE" +version = "0.7.0-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From b9e4dfe38d72123a398fe8841ef0f368cb9bbc63 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 9 Mar 2021 11:47:30 +1000 Subject: [PATCH 14/28] 0.8.0 release. --- README.md | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a246d6b64..b2411a498 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Hosting of artefacts is graciously provided by [Cloudsmith](https://cloudsmith.c maven { url "https://dl.cloudsmith.io/public/libp2p/jvm-libp2p/maven/" } } - implementation 'io.libp2p:jvm-libp2p-minimal:0.7.0-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.8.0-RELEASE' ``` ### Using Maven Add the repository to the `dependencyManagement` section of the pom file: @@ -96,7 +96,7 @@ And then add jvm-libp2p as a dependency: io.libp2p jvm-libp2p-minimal - 0.7.0-RELEASE + 0.8.0-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index f17d3c4c5..3ef8395fa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.7.0-RELEASE" +version = "0.8.0-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 6720047c23c26210c5175be3ae8f72802d1f1798 Mon Sep 17 00:00:00 2001 From: Meredith Baxter Date: Wed, 31 Mar 2021 10:23:51 -0400 Subject: [PATCH 15/28] Update version to 0.8.1 --- README.md | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b2411a498..19f730401 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Hosting of artefacts is graciously provided by [Cloudsmith](https://cloudsmith.c maven { url "https://dl.cloudsmith.io/public/libp2p/jvm-libp2p/maven/" } } - implementation 'io.libp2p:jvm-libp2p-minimal:0.8.0-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.8.1-RELEASE' ``` ### Using Maven Add the repository to the `dependencyManagement` section of the pom file: @@ -96,7 +96,7 @@ And then add jvm-libp2p as a dependency: io.libp2p jvm-libp2p-minimal - 0.8.0-RELEASE + 0.8.1-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index 3ef8395fa..a04e0de9a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.0-RELEASE" +version = "0.8.1-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 08a8417779a35af5f8fc514fc3e0adfe78fd0fb9 Mon Sep 17 00:00:00 2001 From: Meredith Baxter Date: Thu, 22 Apr 2021 14:56:37 -0400 Subject: [PATCH 16/28] Update version to 0.8.2 --- README.md | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 19f730401..fe3dab418 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Hosting of artefacts is graciously provided by [Cloudsmith](https://cloudsmith.c maven { url "https://dl.cloudsmith.io/public/libp2p/jvm-libp2p/maven/" } } - implementation 'io.libp2p:jvm-libp2p-minimal:0.8.1-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.8.2-RELEASE' ``` ### Using Maven Add the repository to the `dependencyManagement` section of the pom file: @@ -96,7 +96,7 @@ And then add jvm-libp2p as a dependency: io.libp2p jvm-libp2p-minimal - 0.8.1-RELEASE + 0.8.2-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index a04e0de9a..8a867673a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.1-RELEASE" +version = "0.8.2-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 259409e58a02b924deeacf01df6b89a1f5453dbc Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Mon, 12 Jul 2021 12:35:41 +1000 Subject: [PATCH 17/28] Update version numbers. --- README.md | 4 ++-- build.gradle.kts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b2411a498..9247a38c4 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Hosting of artefacts is graciously provided by [Cloudsmith](https://cloudsmith.c maven { url "https://dl.cloudsmith.io/public/libp2p/jvm-libp2p/maven/" } } - implementation 'io.libp2p:jvm-libp2p-minimal:0.8.0-RELEASE' + implementation 'io.libp2p:jvm-libp2p-minimal:0.8.3-RELEASE' ``` ### Using Maven Add the repository to the `dependencyManagement` section of the pom file: @@ -96,7 +96,7 @@ And then add jvm-libp2p as a dependency: io.libp2p jvm-libp2p-minimal - 0.8.0-RELEASE + 0.8.3-RELEASE pom ``` diff --git a/build.gradle.kts b/build.gradle.kts index 3ef8395fa..17aeda187 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.0-RELEASE" +version = "0.8.3-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { @@ -235,4 +235,4 @@ fun findProperty(s: String) = project.findProperty(s) as String? val compileKotlin: KotlinCompile by tasks compileKotlin.kotlinOptions { languageVersion = "1.4" -} \ No newline at end of file +} From 06ebda88e26320706d0b6556331222457566f6b0 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Thu, 13 Jan 2022 09:53:57 +1000 Subject: [PATCH 18/28] Update version to 0.8.5-RELEASE --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 7104f0a29..1fd7366ef 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.4-RELEASE" +version = "0.8.5-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 7b7e6bae4d8c5fedc78e786981212ec9192b06dc Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Thu, 13 Jan 2022 10:25:09 +1000 Subject: [PATCH 19/28] 0.8.5 release (#208) * Update build tools. (#207) * Update noise-java and remove jcenter --- build.gradle.kts | 14 +- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 264 +++++++++++++---------- gradlew.bat | 27 +-- 5 files changed, 173 insertions(+), 135 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b550cd30b..1fd7366ef 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.4-RELEASE" +version = "0.8.5-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { @@ -22,25 +22,24 @@ plugins { id("org.jmailen.kotlinter") version "3.2.0" id("com.google.protobuf") version "0.8.13" - `maven` `maven-publish` id("org.jetbrains.dokka") version "0.9.18" } repositories { - jcenter() mavenCentral() + maven("https://artifacts.consensys.net/public/maven/maven/") } val log4j2Version = "2.17.0" dependencies { api("io.netty:netty-all:4.1.69.Final") - api("com.google.protobuf:protobuf-java:3.11.0") + api("com.google.protobuf:protobuf-java:3.19.1") implementation(kotlin("stdlib-jdk8")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0-M1") - implementation("tech.pegasys:noise-java:1.0.0") + implementation("tech.pegasys:noise-java:22.1.0") implementation("com.google.guava:guava:27.1-jre") implementation("org.bouncycastle:bcprov-jdk15on:1.62") @@ -71,7 +70,7 @@ sourceSets { protobuf { protoc { - artifact = "com.google.protobuf:protoc:3.0.0" + artifact = "com.google.protobuf:protoc:3.18.1" } tasks.get("clean").doFirst({ delete(generatedFilesBaseDir) }) @@ -89,6 +88,9 @@ tasks.withType { freeCompilerArgs = listOf("-Xjvm-default=enable") } } +tasks.withType { + duplicatesStrategy = DuplicatesStrategy.INCLUDE +} // Parallel build execution tasks.test { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 26482 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 delta 22605 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 12d38de6a..59250647c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +distributionSha256Sum=b586e04868a22fd817c8971330fec37e298f3242eb85c374181b12d637f80302 +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index b0d6d0ab5..1b6c78733 100755 --- a/gradlew +++ b/gradlew @@ -1,13 +1,13 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 9991c5032..107acd32c 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -5,7 +5,7 @@ @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem -@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From e549b4c50a7656c306b799e530b3ce30554b28f5 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Thu, 13 Jan 2022 11:40:15 +1000 Subject: [PATCH 20/28] Update version number for 0.8.6-RELEASE --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4eddcd9ed..c6e87afcd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.5-RELEASE" +version = "0.8.6-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 7cc9142983e6eabb1ad87fc13be4554030ee3b13 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Fri, 14 Jan 2022 10:20:48 +1000 Subject: [PATCH 21/28] Update version for 0.8.7 release. --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index b2748570c..f2bae74e2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.6-RELEASE" +version = "0.8.7-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From be9898550f365d3d8c5c29b11a8a106f265417c1 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 25 Jan 2022 09:10:33 +1000 Subject: [PATCH 22/28] Update version to 0.8.8 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index f2bae74e2..ed3b04a06 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.7-RELEASE" +version = "0.8.8-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From cbbb061466ffc031e75ef2df3ff938e752660981 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Fri, 18 Feb 2022 08:42:10 +1000 Subject: [PATCH 23/28] Update version to 0.8.9 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index ed3b04a06..71527fc5f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.8-RELEASE" +version = "0.8.9-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 0975f4d2f81ebca14a18b152fc925b44073b0218 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Wed, 11 May 2022 10:19:40 +1000 Subject: [PATCH 24/28] 0.9.0 release --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index fca84eb5a..3ca9d6aa8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.8.9-RELEASE" +version = "0.9.0-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 0041e1acf8b19a05dfde3cbcddde6e79ceb6ef42 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Wed, 27 Jul 2022 09:21:00 +1000 Subject: [PATCH 25/28] 0.9.1 release --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index be95ab233..57fa398b6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.9.0-RELEASE" +version = "0.9.1-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From 8c8a0fa822b65742ace7c3d091d28134a7a3400b Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Fri, 26 Aug 2022 09:09:29 +1000 Subject: [PATCH 26/28] Update version to 0.9.2 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index be3a5e150..cbf1ac3c7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.9.1-RELEASE" +version = "0.9.2-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { From e07c1f0f0bf9304f74f9c7d70b78065e8034eddd Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Mon, 14 Nov 2022 13:55:09 +1000 Subject: [PATCH 27/28] 0.10.0 release --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ea335bab2..19d592387 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ import java.nio.file.Paths // ./gradlew publish -PcloudsmithUser= -PcloudsmithApiKey= group = "io.libp2p" -version = "0.9.2-RELEASE" +version = "0.10.0-RELEASE" description = "a minimal implementation of libp2p for the jvm" plugins { @@ -261,4 +261,4 @@ compileKotlin.kotlinOptions { detekt { config = files("$projectDir/detekt/config.yml") buildUponDefaultConfig = true -} \ No newline at end of file +} From 71c20d587f97b3aa55acd03df44756dd0f9aa54e Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Mon, 21 Aug 2023 12:12:48 +0100 Subject: [PATCH 28/28] 1.0.0 release --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 64ce83673..909cc20d7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,7 +36,7 @@ configure( } ) { group = "io.libp2p" - version = "develop" + version = "1.0.0-RELEASE" apply(plugin = "kotlin") apply(plugin = "idea")