diff options
Diffstat (limited to 'src/main/javatest/com/google/security/cryptauth/lib/securegcm/KeyEncodingTest.java')
-rw-r--r-- | src/main/javatest/com/google/security/cryptauth/lib/securegcm/KeyEncodingTest.java | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/main/javatest/com/google/security/cryptauth/lib/securegcm/KeyEncodingTest.java b/src/main/javatest/com/google/security/cryptauth/lib/securegcm/KeyEncodingTest.java new file mode 100644 index 0000000..7012eae --- /dev/null +++ b/src/main/javatest/com/google/security/cryptauth/lib/securegcm/KeyEncodingTest.java @@ -0,0 +1,189 @@ +// Copyright 2020 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 +// +// https://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.security.cryptauth.lib.securegcm; + +import com.google.security.cryptauth.lib.securemessage.PublicKeyProtoUtil; +import java.security.Key; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Security; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; +import javax.crypto.interfaces.DHPrivateKey; +import javax.crypto.interfaces.DHPublicKey; +import junit.framework.TestCase; + +/** + * Android compatible tests for the {@link KeyEncoding} class. + */ +public class KeyEncodingTest extends TestCase { + private static final byte[] RAW_KEY_BYTES = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, + 1, 2}; + + private Boolean isLegacy; + private KeyPair userKeyPair; + + @Override + protected void setUp() throws Exception { + installSunEcSecurityProviderIfNecessary(); + isLegacy = PublicKeyProtoUtil.isLegacyCryptoRequired(); + setUserKeyPair(); + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + KeyEncoding.setSimulateLegacyCrypto(false); + isLegacy = PublicKeyProtoUtil.isLegacyCryptoRequired(); + super.tearDown(); + } + + private void setUserKeyPair() { + userKeyPair = isLegacy ? PublicKeyProtoUtil.generateRSA2048KeyPair() + : PublicKeyProtoUtil.generateEcP256KeyPair(); + } + + public void testSimulateLegacyCrypto() { + if (isLegacy) { + return; // Nothing to test if we are already stuck in a legacy platform + } + assertFalse(KeyEncoding.isLegacyCryptoRequired()); + KeyEncoding.setSimulateLegacyCrypto(true); + assertTrue(KeyEncoding.isLegacyCryptoRequired()); + } + + public void testMasterKeyEncoding() { + // Require that master keys are encoded/decoded as raw byte arrays + assertTrue(Arrays.equals( + RAW_KEY_BYTES, + KeyEncoding.encodeMasterKey(KeyEncoding.parseMasterKey(RAW_KEY_BYTES)))); + } + + public void testUserPublicKeyEncoding() throws InvalidKeySpecException { + PublicKey pk = userKeyPair.getPublic(); + byte[] encodedPk = KeyEncoding.encodeUserPublicKey(pk); + PublicKey decodedPk = KeyEncoding.parseUserPublicKey(encodedPk); + assertKeysEqual(pk, decodedPk); + } + + public void testUserPrivateKeyEncoding() throws InvalidKeySpecException { + PrivateKey sk = userKeyPair.getPrivate(); + byte[] encodedSk = KeyEncoding.encodeUserPrivateKey(sk); + PrivateKey decodedSk = KeyEncoding.parseUserPrivateKey(encodedSk, isLegacy); + assertKeysEqual(sk, decodedSk); + } + + public void testKeyAgreementPublicKeyEncoding() throws InvalidKeySpecException { + KeyPair clientKeyPair = EnrollmentCryptoOps.generateEnrollmentKeyAgreementKeyPair(isLegacy); + PublicKey pk = clientKeyPair.getPublic(); + byte[] encodedPk = KeyEncoding.encodeKeyAgreementPublicKey(pk); + PublicKey decodedPk = KeyEncoding.parseKeyAgreementPublicKey(encodedPk); + assertKeysEqual(pk, decodedPk); + } + + public void testKeyAgreementPrivateKeyEncoding() throws InvalidKeySpecException { + KeyPair clientKeyPair = EnrollmentCryptoOps.generateEnrollmentKeyAgreementKeyPair(isLegacy); + PrivateKey sk = clientKeyPair.getPrivate(); + byte[] encodedSk = KeyEncoding.encodeKeyAgreementPrivateKey(sk); + PrivateKey decodedSk = KeyEncoding.parseKeyAgreementPrivateKey(encodedSk, isLegacy); + assertKeysEqual(sk, decodedSk); + } + + public void testEncodingsWithForcedLegacy() throws InvalidKeySpecException { + if (PublicKeyProtoUtil.isLegacyCryptoRequired()) { + // We already test with legacy in this case + return; + } + KeyEncoding.setSimulateLegacyCrypto(true); + isLegacy = true; + setUserKeyPair(); + testUserPublicKeyEncoding(); + testUserPrivateKeyEncoding(); + testKeyAgreementPublicKeyEncoding(); + testKeyAgreementPrivateKeyEncoding(); + } + + public void testSigningPublicKeyEncoding() throws InvalidKeySpecException { + KeyPair keyPair = PublicKeyProtoUtil.generateEcP256KeyPair(); + PublicKey pk = keyPair.getPublic(); + byte[] encodedPk = KeyEncoding.encodeSigningPublicKey(pk); + PublicKey decodedPk = KeyEncoding.parseSigningPublicKey(encodedPk); + assertKeysEqual(pk, decodedPk); + } + + public void testSigningPrivateKeyEncoding() throws InvalidKeySpecException { + KeyPair keyPair = PublicKeyProtoUtil.generateEcP256KeyPair(); + PrivateKey sk = keyPair.getPrivate(); + byte[] encodedSk = KeyEncoding.encodeSigningPrivateKey(sk); + PrivateKey decodedSk = KeyEncoding.parseSigningPrivateKey(encodedSk); + assertKeysEqual(sk, decodedSk); + } + + public void testDeviceSyncPublicKeyEncoding() throws InvalidKeySpecException { + KeyPair keyPair = PublicKeyProtoUtil.generateEcP256KeyPair(); + PublicKey pk = keyPair.getPublic(); + byte[] encodedPk = KeyEncoding.encodeDeviceSyncGroupPublicKey(pk); + PublicKey decodedPk = KeyEncoding.parseDeviceSyncGroupPublicKey(encodedPk); + assertKeysEqual(pk, decodedPk); + } + + void assertKeysEqual(Key a, Key b) { + if ((a instanceof ECPublicKey) + || (a instanceof ECPrivateKey) + || (a instanceof RSAPublicKey) + || (a instanceof RSAPrivateKey)) { + assertNotNull(a.getEncoded()); + assertTrue(Arrays.equals(a.getEncoded(), b.getEncoded())); + } + if (a instanceof DHPublicKey) { + DHPublicKey ya = (DHPublicKey) a; + DHPublicKey yb = (DHPublicKey) b; + assertEquals(ya.getY(), yb.getY()); + assertEquals(ya.getParams().getG(), yb.getParams().getG()); + assertEquals(ya.getParams().getP(), yb.getParams().getP()); + } + if (a instanceof DHPrivateKey) { + DHPrivateKey xa = (DHPrivateKey) a; + DHPrivateKey xb = (DHPrivateKey) b; + assertEquals(xa.getX(), xb.getX()); + assertEquals(xa.getParams().getG(), xb.getParams().getG()); + assertEquals(xa.getParams().getP(), xb.getParams().getP()); + } + } + + /** + * Registers the SunEC security provider if no EC security providers are currently registered. + */ + // TODO(shabsi): Remove this method when b/7891565 is fixed + static void installSunEcSecurityProviderIfNecessary() { + if (Security.getProviders("KeyPairGenerator.EC") == null) { + try { + Class<?> providerClass = Class.forName("sun.security.ec.SunEC"); + Security.addProvider((Provider) providerClass.newInstance()); + } catch (Exception e) { + // SunEC is not available, nothing we can do + } + } + } +} |