Skip to content
Snippets Groups Projects
Commit ea39ea1f authored by tholenst's avatar tholenst Committed by Copybara-Service
Browse files

Add AesCmac to java, including cross language testing.

PiperOrigin-RevId: 264116863
parent 15bd6702
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,7 @@ package(default_visibility = ["//tools/build_defs:internal_pkg"])
licenses(["notice"])
full_proto_deps = [
"//proto:aes_cmac_java_proto",
"//proto:aes_ctr_hmac_aead_java_proto",
"//proto:aes_ctr_hmac_streaming_java_proto",
"//proto:aes_ctr_java_proto",
......@@ -27,6 +28,7 @@ full_proto_deps = [
]
lite_proto_deps = [
"//proto:aes_cmac_java_proto_lite",
"//proto:aes_ctr_hmac_aead_java_proto_lite",
"//proto:aes_ctr_hmac_streaming_java_proto_lite",
"//proto:aes_ctr_java_proto_lite",
......
// Copyright 2017 Google Inc.
//
// 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.mac;
import com.google.crypto.tink.KeyTypeManager;
import com.google.crypto.tink.Mac;
import com.google.crypto.tink.proto.AesCmacKey;
import com.google.crypto.tink.proto.AesCmacKeyFormat;
import com.google.crypto.tink.proto.AesCmacParams;
import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
import com.google.crypto.tink.subtle.AesCmac;
import com.google.crypto.tink.subtle.Random;
import com.google.crypto.tink.subtle.Validators;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import java.security.GeneralSecurityException;
/**
* This key manager generates new {@code AesCmacKey} keys and produces new instances of {@code
* AesCmac}.
*/
class AesCmacKeyManager extends KeyTypeManager<AesCmacKey> {
public AesCmacKeyManager() {
super(
AesCmacKey.class,
new PrimitiveFactory<Mac, AesCmacKey>(Mac.class) {
@Override
public Mac getPrimitive(AesCmacKey key) throws GeneralSecurityException {
return new AesCmac(key.getKeyValue().toByteArray(), key.getParams().getTagSize());
}
});
}
private static final int VERSION = 0;
private static final int KEY_SIZE_IN_BYTES = 32;
private static final int MIN_TAG_SIZE_IN_BYTES = 10;
private static final int MAX_TAG_SIZE_IN_BYTES = 16;
@Override
public String getKeyType() {
return "type.googleapis.com/google.crypto.tink.AesCmacKey";
}
@Override
public int getVersion() {
return VERSION;
}
@Override
public KeyMaterialType keyMaterialType() {
return KeyMaterialType.SYMMETRIC;
}
@Override
public void validateKey(AesCmacKey key) throws GeneralSecurityException {
Validators.validateVersion(key.getVersion(), getVersion());
validateSize(key.getKeyValue().size());
validateParams(key.getParams());
}
@Override
public AesCmacKey parseKey(ByteString byteString) throws InvalidProtocolBufferException {
return AesCmacKey.parseFrom(byteString);
}
private static void validateParams(AesCmacParams params) throws GeneralSecurityException {
if (params.getTagSize() < MIN_TAG_SIZE_IN_BYTES) {
throw new GeneralSecurityException("tag size too short");
}
if (params.getTagSize() > MAX_TAG_SIZE_IN_BYTES) {
throw new GeneralSecurityException("tag size too long");
}
}
private static void validateSize(int size) throws GeneralSecurityException {
if (size != KEY_SIZE_IN_BYTES) {
throw new GeneralSecurityException("AesCmacKey size wrong, must be 16 bytes");
}
}
@Override
public KeyFactory<AesCmacKeyFormat, AesCmacKey> keyFactory() {
return new KeyFactory<AesCmacKeyFormat, AesCmacKey>(AesCmacKeyFormat.class) {
@Override
public void validateKeyFormat(AesCmacKeyFormat format) throws GeneralSecurityException {
validateParams(format.getParams());
validateSize(format.getKeySize());
}
@Override
public AesCmacKeyFormat parseKeyFormat(ByteString byteString)
throws InvalidProtocolBufferException {
return AesCmacKeyFormat.parseFrom(byteString);
}
@Override
public AesCmacKey createKey(AesCmacKeyFormat format) throws GeneralSecurityException {
return AesCmacKey.newBuilder()
.setVersion(VERSION)
.setKeyValue(ByteString.copyFrom(Random.randBytes(format.getKeySize())))
.setParams(format.getParams())
.build();
}
};
}
}
......@@ -14,6 +14,7 @@ filegroup(
)
full_protos = [
"//proto:aes_cmac_java_proto",
"//proto:common_java_proto",
"//proto:config_java_proto",
"//proto:hmac_java_proto",
......@@ -21,6 +22,7 @@ full_protos = [
]
lite_protos = [
"//proto:aes_cmac_java_proto_lite",
"//proto:common_java_proto_lite",
"//proto:config_java_proto_lite",
"//proto:hmac_java_proto_lite",
......
......@@ -84,6 +84,7 @@ public final class MacConfig {
*/
public static void register() throws GeneralSecurityException {
Registry.registerKeyManager(new HmacKeyManager());
Registry.registerKeyManager(new AesCmacKeyManager(), true);
Registry.registerPrimitiveWrapper(new MacWrapper());
}
......
......@@ -16,6 +16,8 @@
package com.google.crypto.tink.mac;
import com.google.crypto.tink.proto.AesCmacKeyFormat;
import com.google.crypto.tink.proto.AesCmacParams;
import com.google.crypto.tink.proto.HashType;
import com.google.crypto.tink.proto.HmacKeyFormat;
import com.google.crypto.tink.proto.HmacParams;
......@@ -46,6 +48,7 @@ public final class MacKeyTemplates {
* <li>Key size: 32 bytes
* <li>Tag size: 16 bytes
* <li>Hash function: SHA256
* <li>OutputPrefixType: TINK
* </ul>
*/
public static final KeyTemplate HMAC_SHA256_128BITTAG =
......@@ -59,6 +62,7 @@ public final class MacKeyTemplates {
* <li>Key size: 32 bytes
* <li>Tag size: 32 bytes
* <li>Hash function: SHA256
* <li>OutputPrefixType: TINK
* </ul>
*/
public static final KeyTemplate HMAC_SHA256_256BITTAG =
......@@ -72,6 +76,7 @@ public final class MacKeyTemplates {
* <li>Key size: 64 bytes
* <li>Tag size: 32 bytes
* <li>Hash function: SHA512
* <li>OutputPrefixType: TINK
* </ul>
*/
public static final KeyTemplate HMAC_SHA512_256BITTAG =
......@@ -85,11 +90,33 @@ public final class MacKeyTemplates {
* <li>Key size: 64 bytes
* <li>Tag size: 64 bytes
* <li>Hash function: SHA512
* <li>OutputPrefixType: TINK
* </ul>
*/
public static final KeyTemplate HMAC_SHA512_512BITTAG =
createHmacKeyTemplate(64, 64, HashType.SHA512);
/**
* A {@link KeyTemplate} that generates new instances of {@link
* com.google.crypto.tink.proto.CmacKey} with the following parameters:
*
* <ul>
* <li>Key size: 32 bytes
* <li>Tag size: 16 bytes
* <li>OutputPrefixType: TINK
* </ul>
*/
public static final KeyTemplate AES_CMAC =
KeyTemplate.newBuilder()
.setValue(
AesCmacKeyFormat.newBuilder()
.setKeySize(32)
.setParams(AesCmacParams.newBuilder().setTagSize(16).build())
.build().toByteString())
.setTypeUrl(new AesCmacKeyManager().getKeyType())
.setOutputPrefixType(OutputPrefixType.TINK)
.build();
/**
* @return a {@link KeyTemplate} containing a {@link HmacKeyFormat} with some specified
* parameters.
......
// Copyright 2017 Google Inc.
//
// 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.mac;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import com.google.crypto.tink.Mac;
import com.google.crypto.tink.proto.AesCmacKey;
import com.google.crypto.tink.proto.AesCmacKeyFormat;
import com.google.crypto.tink.proto.AesCmacParams;
import com.google.crypto.tink.subtle.AesCmac;
import com.google.crypto.tink.subtle.Random;
import com.google.protobuf.ByteString;
import java.security.GeneralSecurityException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Test for AesCmacKeyManager. */
@RunWith(JUnit4.class)
public class AesCmacKeyManagerTest {
@Test
public void validateKeyFormat_empty() throws Exception {
try {
new AesCmacKeyManager().keyFactory().validateKeyFormat(AesCmacKeyFormat.getDefaultInstance());
fail();
} catch (GeneralSecurityException e) {
// expected.
}
}
private static AesCmacKeyFormat makeAesCmacKeyFormat(int keySize, int tagSize) {
return AesCmacKeyFormat.newBuilder()
.setKeySize(keySize)
.setParams(AesCmacParams.newBuilder().setTagSize(tagSize).build())
.build();
}
@Test
public void validateKeyFormat_valid() throws Exception {
AesCmacKeyManager manager = new AesCmacKeyManager();
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 10));
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 11));
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 12));
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 13));
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 14));
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 15));
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 16));
}
@Test
public void validateKeyFormat_notValid_throws() throws Exception {
AesCmacKeyManager manager = new AesCmacKeyManager();
try {
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 9));
fail();
} catch (GeneralSecurityException e) {
// expected
}
try {
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 17));
fail();
} catch (GeneralSecurityException e) {
// expected
}
try {
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(32, 32));
fail();
} catch (GeneralSecurityException e) {
// expected
}
try {
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(16, 16));
fail();
} catch (GeneralSecurityException e) {
// expected
}
try {
manager.keyFactory().validateKeyFormat(makeAesCmacKeyFormat(64, 16));
fail();
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void createKey_valid() throws Exception {
AesCmacKeyManager manager = new AesCmacKeyManager();
manager.validateKey(manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 16)));
}
@Test
public void createKey_checkValues() throws Exception {
AesCmacKeyFormat keyFormat = makeAesCmacKeyFormat(32, 16);
AesCmacKey key = new AesCmacKeyManager().keyFactory().createKey(keyFormat);
assertThat(key.getKeyValue()).hasSize(keyFormat.getKeySize());
assertThat(key.getParams().getTagSize()).isEqualTo(keyFormat.getParams().getTagSize());
}
@Test
public void createKey_multipleTimes() throws Exception {
AesCmacKeyManager manager = new AesCmacKeyManager();
AesCmacKeyFormat keyFormat = makeAesCmacKeyFormat(32, 16);
assertThat(manager.keyFactory().createKey(keyFormat).getKeyValue())
.isNotEqualTo(manager.keyFactory().createKey(keyFormat).getKeyValue());
}
@Test
public void validateKey_valid() throws Exception {
AesCmacKeyManager manager = new AesCmacKeyManager();
manager.validateKey(manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 10)));
manager.validateKey(manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 11)));
manager.validateKey(manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 12)));
manager.validateKey(manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 13)));
manager.validateKey(manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 14)));
manager.validateKey(manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 15)));
manager.validateKey(manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 16)));
}
@Test
public void validateKey_wrongVersion_throws() throws Exception {
AesCmacKeyManager manager = new AesCmacKeyManager();
try {
AesCmacKey validKey = manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 16));
manager.validateKey(AesCmacKey.newBuilder(validKey).setVersion(1).build());
fail();
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void validateKey_notValid_throws() throws Exception {
AesCmacKeyManager manager = new AesCmacKeyManager();
AesCmacKey validKey = manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 16));
try {
manager.validateKey(
AesCmacKey.newBuilder(validKey)
.setKeyValue(ByteString.copyFrom(Random.randBytes(16)))
.build());
fail();
} catch (GeneralSecurityException e) {
// expected
}
try {
manager.validateKey(
AesCmacKey.newBuilder(validKey)
.setKeyValue(ByteString.copyFrom(Random.randBytes(64)))
.build());
fail();
} catch (GeneralSecurityException e) {
// expected
}
try {
manager
.validateKey(
AesCmacKey.newBuilder(validKey)
.setParams(AesCmacParams.newBuilder(validKey.getParams()).setTagSize(0).build())
.build());
fail();
} catch (GeneralSecurityException e) {
// expected
}
try {
manager
.validateKey(
AesCmacKey.newBuilder(validKey)
.setParams(AesCmacParams.newBuilder(validKey.getParams()).setTagSize(9).build())
.build());
fail();
} catch (GeneralSecurityException e) {
// expected
}
try {
manager
.validateKey(
AesCmacKey.newBuilder(validKey)
.setParams(AesCmacParams.newBuilder(validKey.getParams()).setTagSize(17).build())
.build());
fail();
} catch (GeneralSecurityException e) {
// expected
}
try {
manager
.validateKey(
AesCmacKey.newBuilder(validKey)
.setParams(AesCmacParams.newBuilder(validKey.getParams()).setTagSize(32).build())
.build());
fail();
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void getPrimitive_works() throws Exception {
AesCmacKeyManager manager = new AesCmacKeyManager();
AesCmacKey validKey = manager.keyFactory().createKey(makeAesCmacKeyFormat(32, 16));
Mac managerMac = manager.getPrimitive(validKey, Mac.class);
Mac directMac =
new AesCmac(validKey.getKeyValue().toByteArray(), validKey.getParams().getTagSize());
byte[] message = Random.randBytes(50);
managerMac.verifyMac(directMac.computeMac(message), message);
}
}
......@@ -76,3 +76,9 @@ MAC_CLIS=($CC_MAC_CLI $JAVA_MAC_CLI $GO_MAC_CLI)
VERIFY_CLIS=($CC_MAC_CLI $JAVA_MAC_CLI $GO_MAC_CLI)
mac_basic_test "${MAC_CLIS[*]}" "${VERIFY_CLIS[*]}" \
"${KEY_TEMPLATES[*]}"
KEY_TEMPLATES=(AES_CMAC)
MAC_CLIS=($CC_MAC_CLI $JAVA_MAC_CLI)
VERIFY_CLIS=($CC_MAC_CLI $JAVA_MAC_CLI)
mac_basic_test "${MAC_CLIS[*]}" "${VERIFY_CLIS[*]}" \
"${KEY_TEMPLATES[*]}"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment