blob: 3a99100f01a17e52967f20888094da2938cbc2be [file] [log] [blame]
// 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.signature;
import static org.junit.Assert.fail;
import com.google.crypto.tink.KeysetHandle;
import com.google.crypto.tink.PublicKeySign;
import com.google.crypto.tink.PublicKeyVerify;
import com.google.crypto.tink.Registry;
import com.google.crypto.tink.TestUtil;
import com.google.crypto.tink.proto.EcdsaPrivateKey;
import com.google.crypto.tink.proto.EcdsaSignatureEncoding;
import com.google.crypto.tink.proto.EllipticCurveType;
import com.google.crypto.tink.proto.HashType;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.proto.KeyStatusType;
import com.google.crypto.tink.proto.Keyset.Key;
import com.google.crypto.tink.proto.OutputPrefixType;
import com.google.crypto.tink.subtle.Random;
import java.security.GeneralSecurityException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link PublicKeyVerifyWrapper}. */
@RunWith(JUnit4.class)
// TODO(quannguyen): Add more tests.
public class PublicKeyVerifyWrapperTest {
@Before
public void setUp() throws Exception {
SignatureConfig.register();
}
@Test
public void testMultipleKeys() throws Exception {
EcdsaPrivateKey tinkPrivateKey =
TestUtil.generateEcdsaPrivKey(
EllipticCurveType.NIST_P521, HashType.SHA512, EcdsaSignatureEncoding.DER);
Key tink =
TestUtil.createKey(
TestUtil.createKeyData(
tinkPrivateKey.getPublicKey(),
new EcdsaVerifyKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC),
1,
KeyStatusType.ENABLED,
OutputPrefixType.TINK);
EcdsaPrivateKey legacyPrivateKey =
TestUtil.generateEcdsaPrivKey(
EllipticCurveType.NIST_P256, HashType.SHA256, EcdsaSignatureEncoding.DER);
Key legacy =
TestUtil.createKey(
TestUtil.createKeyData(
legacyPrivateKey.getPublicKey(),
new EcdsaVerifyKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC),
2,
KeyStatusType.ENABLED,
OutputPrefixType.LEGACY);
EcdsaPrivateKey rawPrivateKey =
TestUtil.generateEcdsaPrivKey(
EllipticCurveType.NIST_P384, HashType.SHA512, EcdsaSignatureEncoding.DER);
Key raw =
TestUtil.createKey(
TestUtil.createKeyData(
rawPrivateKey.getPublicKey(),
new EcdsaVerifyKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC),
3,
KeyStatusType.ENABLED,
OutputPrefixType.RAW);
EcdsaPrivateKey crunchyPrivateKey =
TestUtil.generateEcdsaPrivKey(
EllipticCurveType.NIST_P384, HashType.SHA512, EcdsaSignatureEncoding.DER);
Key crunchy =
TestUtil.createKey(
TestUtil.createKeyData(
crunchyPrivateKey.getPublicKey(),
new EcdsaVerifyKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC),
4,
KeyStatusType.ENABLED,
OutputPrefixType.CRUNCHY);
Key[] keys = new Key[] {tink, legacy, raw, crunchy};
EcdsaPrivateKey[] privateKeys =
new EcdsaPrivateKey[] {tinkPrivateKey, legacyPrivateKey, rawPrivateKey, crunchyPrivateKey};
int j = keys.length;
for (int i = 0; i < j; i++) {
KeysetHandle keysetHandle =
TestUtil.createKeysetHandle(
TestUtil.createKeyset(
keys[i], keys[(i + 1) % j], keys[(i + 2) % j], keys[(i + 3) % j]));
PublicKeyVerify verifier =
new PublicKeyVerifyWrapper()
.wrap(Registry.getPrimitives(keysetHandle, PublicKeyVerify.class));
// Signature from any keys in the keyset should be valid.
for (int k = 0; k < j; k++) {
PublicKeySign signer =
PublicKeySignFactory.getPrimitive(
TestUtil.createKeysetHandle(
TestUtil.createKeyset(
TestUtil.createKey(
TestUtil.createKeyData(
privateKeys[k],
new EcdsaSignKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PRIVATE),
keys[k].getKeyId(),
KeyStatusType.ENABLED,
keys[k].getOutputPrefixType()))));
byte[] plaintext = Random.randBytes(1211);
byte[] sig = signer.sign(plaintext);
try {
verifier.verify(sig, plaintext);
} catch (GeneralSecurityException ex) {
fail("Valid signature, should not throw exception: " + k);
}
}
// Signature from a random key should be invalid.
EcdsaPrivateKey randomPrivKey =
TestUtil.generateEcdsaPrivKey(
EllipticCurveType.NIST_P521, HashType.SHA512, EcdsaSignatureEncoding.DER);
PublicKeySign signer =
PublicKeySignFactory.getPrimitive(
TestUtil.createKeysetHandle(
TestUtil.createKeyset(
TestUtil.createKey(
TestUtil.createKeyData(
randomPrivKey,
new EcdsaSignKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PRIVATE),
1,
KeyStatusType.ENABLED,
keys[0].getOutputPrefixType()))));
byte[] plaintext = Random.randBytes(1211);
byte[] sig = signer.sign(plaintext);
try {
verifier.verify(sig, plaintext);
fail("Invalid signature, should have thrown exception");
} catch (GeneralSecurityException expected) {
// Expected
}
}
}
}