| // 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 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package com.google.crypto.tink.util; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static org.junit.Assert.assertThrows; |
| |
| import java.security.GeneralSecurityException; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.SecureRandom; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.function.ThrowingRunnable; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| /** Tests some of the more complex functions from TestUtil. */ |
| @RunWith(JUnit4.class) |
| public class TestUtilTest { |
| SecureRandom random; |
| final byte[] randomBytes = new byte[512]; |
| // Correlated to randomBytes: derived by 1 + randomBytes. |
| final byte[] correlatedRandomBytes = new byte[512]; |
| final byte[] moreRandomBytes = new byte[512]; |
| final ArrayList<Integer> randomIndices = new ArrayList<>(512); |
| |
| @Before |
| public void startup() throws NoSuchAlgorithmException { |
| random = SecureRandom.getInstanceStrong(); |
| random.setSeed(1234); |
| random.nextBytes(randomBytes); |
| random.nextBytes(moreRandomBytes); |
| |
| for (int i = 0; i < randomBytes.length; i++) { |
| correlatedRandomBytes[i] = randomBytes[i]; |
| randomIndices.add(i); |
| } |
| Collections.shuffle(randomIndices); |
| } |
| |
| @Test |
| public void testZTestUniformitySucceedsOnRandomData() throws GeneralSecurityException { |
| TestUtil.ztestUniformString(randomBytes); |
| } |
| |
| @Test |
| public void testZTestUniformityFailsOnNonRandomData() { |
| String msg = |
| assertThrows( |
| GeneralSecurityException.class, |
| new ThrowingRunnable() { |
| @Override |
| public void run() throws Throwable { |
| setValueForNBytes(randomBytes, 256, (byte) 1); |
| TestUtil.ztestUniformString(randomBytes); |
| } |
| }) |
| .getMessage(); |
| assertThat(msg).contains("Z test for uniformly distributed variable out of bounds"); |
| } |
| |
| @Test |
| public void testZTestUniformityFailsOnNonRandomNegativeData() { |
| String msg = |
| assertThrows( |
| GeneralSecurityException.class, |
| new ThrowingRunnable() { |
| @Override |
| public void run() throws Throwable { |
| setValueForNBytes(randomBytes, 256, (byte) -120); |
| TestUtil.ztestUniformString(randomBytes); |
| } |
| }) |
| .getMessage(); |
| assertThat(msg).contains("Z test for uniformly distributed variable out of bounds"); |
| } |
| |
| @Test |
| public void testZTestUniformityFailsOnSmallUniformMessage() { |
| String msg = |
| assertThrows( |
| GeneralSecurityException.class, |
| new ThrowingRunnable() { |
| @Override |
| public void run() throws Throwable { |
| byte[] allZeros = new byte[16]; |
| TestUtil.ztestUniformString(allZeros); |
| } |
| }) |
| .getMessage(); |
| assertThat(msg).contains("Z test for uniformly distributed variable out of bounds"); |
| } |
| |
| @Test |
| public void testZTestUniformityFailsWithTooSmallMessage() { |
| String msg = |
| assertThrows( |
| GeneralSecurityException.class, |
| new ThrowingRunnable() { |
| @Override |
| public void run() throws Throwable { |
| byte[] allZeros = new byte[4]; |
| TestUtil.ztestUniformString(allZeros); |
| } |
| }) |
| .getMessage(); |
| assertThat(msg).contains("Use more bytes."); |
| } |
| |
| @Test |
| public void testZTestCrossCorrelationUniformitySucceedsOnRandomData() |
| throws GeneralSecurityException { |
| TestUtil.ztestCrossCorrelationUniformStrings(randomBytes, moreRandomBytes); |
| } |
| |
| @Test |
| public void testZTestCrossCorrelationUniformityFailsOnCorrelatedData() |
| throws GeneralSecurityException { |
| String msg = |
| assertThrows( |
| GeneralSecurityException.class, |
| new ThrowingRunnable() { |
| @Override |
| public void run() throws Throwable { |
| TestUtil.ztestCrossCorrelationUniformStrings( |
| randomBytes, correlatedRandomBytes); |
| } |
| }) |
| .getMessage(); |
| assertThat(msg).contains("Z test for uniformly distributed variable out of bounds"); |
| } |
| |
| @Test |
| public void testZTestAutoCorrelationSucceedsOnRandomData() throws GeneralSecurityException { |
| TestUtil.ztestAutocorrelationUniformString(randomBytes); |
| } |
| |
| @Test |
| public void testZTestAutoCorrelationFailsOnAutoCorrelatedData() throws GeneralSecurityException { |
| byte[] repeatedRandom = new byte[randomBytes.length * 3]; |
| for (int i = 0; i < 3; i++) { |
| System.arraycopy(randomBytes, 0, repeatedRandom, i * randomBytes.length, randomBytes.length); |
| } |
| |
| String msg = |
| assertThrows( |
| GeneralSecurityException.class, |
| new ThrowingRunnable() { |
| @Override |
| public void run() throws Throwable { |
| TestUtil.ztestAutocorrelationUniformString(repeatedRandom); |
| } |
| }) |
| .getMessage(); |
| assertThat(msg).contains("Z test for uniformly distributed variable out of bounds"); |
| } |
| |
| private void setValueForNBytes(byte[] input, int numberBytesToSet, byte valueToSet) { |
| for (int i = 0; i < numberBytesToSet; i++) { |
| input[randomIndices.get(i)] = valueToSet; |
| } |
| } |
| } |