blob: db76c49445105b649cbd13ba3ebd870e0a589308 [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.assertArrayEquals;
import static org.junit.Assert.fail;
import com.google.crypto.tink.CryptoFormat;
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 java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link PublicKeySignWrapper}. */
@RunWith(JUnit4.class)
// TODO(quannguyen): Add more tests.
public class PublicKeySignWrapperTest {
@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,
new EcdsaSignKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PRIVATE),
1,
KeyStatusType.ENABLED,
OutputPrefixType.TINK);
EcdsaPrivateKey legacyPrivateKey =
TestUtil.generateEcdsaPrivKey(
EllipticCurveType.NIST_P256, HashType.SHA256, EcdsaSignatureEncoding.DER);
Key legacy =
TestUtil.createKey(
TestUtil.createKeyData(
legacyPrivateKey,
new EcdsaSignKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PRIVATE),
2,
KeyStatusType.ENABLED,
OutputPrefixType.LEGACY);
EcdsaPrivateKey rawPrivateKey =
TestUtil.generateEcdsaPrivKey(
EllipticCurveType.NIST_P384, HashType.SHA512, EcdsaSignatureEncoding.DER);
Key raw =
TestUtil.createKey(
TestUtil.createKeyData(
rawPrivateKey,
new EcdsaSignKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PRIVATE),
3,
KeyStatusType.ENABLED,
OutputPrefixType.RAW);
EcdsaPrivateKey crunchyPrivateKey =
TestUtil.generateEcdsaPrivKey(
EllipticCurveType.NIST_P384, HashType.SHA512, EcdsaSignatureEncoding.DER);
Key crunchy =
TestUtil.createKey(
TestUtil.createKeyData(
crunchyPrivateKey,
new EcdsaSignKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PRIVATE),
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]));
// Signs with the primary private key.
PublicKeySign signer =
new PublicKeySignWrapper()
.wrap(Registry.getPrimitives(keysetHandle, PublicKeySign.class));
byte[] plaintext = Random.randBytes(1211);
byte[] sig = signer.sign(plaintext);
if (keys[i].getOutputPrefixType() != OutputPrefixType.RAW) {
byte[] prefix = Arrays.copyOfRange(sig, 0, CryptoFormat.NON_RAW_PREFIX_SIZE);
assertArrayEquals(prefix, CryptoFormat.getOutputPrefix(keys[i]));
}
// Verifying with the primary public key should work.
PublicKeyVerify verifier =
PublicKeyVerifyFactory.getPrimitive(
TestUtil.createKeysetHandle(
TestUtil.createKeyset(
TestUtil.createKey(
TestUtil.createKeyData(
privateKeys[i].getPublicKey(),
new EcdsaVerifyKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC),
keys[i].getKeyId(),
KeyStatusType.ENABLED,
keys[i].getOutputPrefixType()))));
try {
verifier.verify(sig, plaintext);
} catch (GeneralSecurityException ex) {
fail("Valid signature, should not throw exception");
}
// Verifying with a random public key should fail.
EcdsaPrivateKey randomPrivKey =
TestUtil.generateEcdsaPrivKey(
EllipticCurveType.NIST_P521, HashType.SHA512, EcdsaSignatureEncoding.DER);
verifier =
PublicKeyVerifyFactory.getPrimitive(
TestUtil.createKeysetHandle(
TestUtil.createKeyset(
TestUtil.createKey(
TestUtil.createKeyData(
randomPrivKey.getPublicKey(),
new EcdsaVerifyKeyManager().getKeyType(),
KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC),
keys[i].getKeyId(),
KeyStatusType.ENABLED,
keys[i].getOutputPrefixType()))));
try {
verifier.verify(sig, plaintext);
fail("Invalid signature, should have thrown exception");
} catch (GeneralSecurityException expected) {
// Expected
}
}
}
}