Skip to content

Commit

Permalink
Add validation to HpkeUtil.intToByteArray.
Browse files Browse the repository at this point in the history
- The algorithm implementation used here doesn't work for capacity larger than 4, so we shouldn't allow this.
- The algorithm definition, see https://www.rfc-editor.org/rfc/rfc3447.html#section-4.1, requires that 0 <= value < 256^capacity.

And add unit tests.

PiperOrigin-RevId: 620041132
Change-Id: I39044951e4be1ed993aaaec3f194701cd1e60e44
  • Loading branch information
juergw authored and copybara-github committed Mar 28, 2024
1 parent 9de8d44 commit 3bef329
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ public final class HpkeUtil {
* @param value that should be represented as a byte array
*/
public static byte[] intToByteArray(int capacity, int value) {
if ((capacity > 4) || (capacity < 0)) {
throw new IllegalArgumentException("capacity must be between 0 and 4");
}
// Check that 0 <= value < 256^capacity.
// For capacity == 4, all positive values are valid.
if (value < 0 || (capacity < 4 && (value >= 1 << (8 * capacity)))) {
throw new IllegalArgumentException("value too large");
}
final byte[] result = new byte[capacity];
for (int i = 0; i < capacity; i++) {
result[i] = (byte) ((value >> (8 * (capacity - i - 1))) & 0xFF);
Expand Down
11 changes: 11 additions & 0 deletions src/test/java/com/google/crypto/tink/hybrid/internal/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -322,3 +322,14 @@ java_test(
"@maven//:junit_junit",
],
)

java_test(
name = "HpkeUtilTest",
size = "small",
srcs = ["HpkeUtilTest.java"],
deps = [
"//src/main/java/com/google/crypto/tink/hybrid/internal:hpke_util",
"@maven//:com_google_truth_truth",
"@maven//:junit_junit",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2024 Google LLC
//
// 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.hybrid.internal;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public final class HpkeUtilTest {

@Test
public void intToByteArray_works() {
assertThat(HpkeUtil.intToByteArray(0, 0)).isEqualTo(new byte[] {});
assertThat(HpkeUtil.intToByteArray(1, 42)).isEqualTo(new byte[] {(byte) 42});
assertThat(HpkeUtil.intToByteArray(2, 0x0102)).isEqualTo(new byte[] {(byte) 01, (byte) 0x02});

assertThat(HpkeUtil.intToByteArray(1, 0xaa)).isEqualTo(new byte[] {(byte) 0xaa});
assertThat(HpkeUtil.intToByteArray(1, 256 - 1)).isEqualTo(new byte[] {(byte) 0xff});
assertThat(HpkeUtil.intToByteArray(2, 0xaabb)).isEqualTo(new byte[] {(byte) 0xaa, (byte) 0xbb});
assertThat(HpkeUtil.intToByteArray(2, 256 * 256 - 1))
.isEqualTo(new byte[] {(byte) 0xff, (byte) 0xff});
assertThat(HpkeUtil.intToByteArray(3, 0xaabbcc))
.isEqualTo(new byte[] {(byte) 0xaa, (byte) 0xbb, (byte) 0xcc});
assertThat(HpkeUtil.intToByteArray(3, 256 * 256 * 256 - 1))
.isEqualTo(new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff});
assertThat(HpkeUtil.intToByteArray(4, 0x0abbccdd))
.isEqualTo(new byte[] {(byte) 0x0a, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd});
assertThat(HpkeUtil.intToByteArray(4, Integer.MAX_VALUE))
.isEqualTo(new byte[] {(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff});
}

@Test
public void intToByteArray_failsWithInvalidCapacity() {
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(5, 0));
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(-1, 0));
}

@Test
public void intToByteArray_valueTooLong_fails() {
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(0, 1));
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(0, -1));
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(1, 256));
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(1, -1));
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(2, 256 * 256));
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(2, -1));
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(3, 256 * 256 * 256));
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(3, -1));
assertThrows(IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(4, -1));
assertThrows(
IllegalArgumentException.class, () -> HpkeUtil.intToByteArray(4, Integer.MIN_VALUE));
}
}

0 comments on commit 3bef329

Please sign in to comment.