From f7ecb0dfad2cc15d42eacefb13e8675dd664dd38 Mon Sep 17 00:00:00 2001 From: Emilia Kasper Date: Fri, 14 Oct 2016 15:58:23 +0200 Subject: Initial GitHub export --- .../security/wycheproof/testcases/RsaKeyTest.java | 139 +++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 java/com/google/security/wycheproof/testcases/RsaKeyTest.java (limited to 'java/com/google/security/wycheproof/testcases/RsaKeyTest.java') diff --git a/java/com/google/security/wycheproof/testcases/RsaKeyTest.java b/java/com/google/security/wycheproof/testcases/RsaKeyTest.java new file mode 100644 index 0000000..26480b6 --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/RsaKeyTest.java @@ -0,0 +1,139 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * 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.security.wycheproof; + +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.X509EncodedKeySpec; +import junit.framework.TestCase; + +/** + * Tests RSA keys. Signatures and encryption are tested in different tests. + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +// TODO(bleichen): +// - Add checks for bad random numbers +// - expect keys with e=1 to be rejected +// - expect keys with e=0 to be rejected +// - document stuff +// - Maybe also check encodings of private keys. +// - Test multi prime RSA +// - Tests for alternative representations: +// many libraries sort the primes as: p > q (but not all) +// some libraries compute d mod lambda(n) +// paramaters p,q,... are not really required +// - checks for bad random number generation +public class RsaKeyTest extends TestCase { + + public static final String ENCODED_PUBLIC_KEY = + "30819f300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001"; + + private void checkPrivateCrtKey(RSAPrivateCrtKey key, int expectedKeySize) throws Exception { + BigInteger p = key.getPrimeP(); + BigInteger q = key.getPrimeQ(); + BigInteger n = key.getModulus(); + BigInteger e = key.getPublicExponent(); + BigInteger d = key.getPrivateExponent(); + BigInteger dp = key.getPrimeExponentP(); + BigInteger dq = key.getPrimeExponentQ(); + BigInteger crtCoeff = key.getCrtCoefficient(); + + // Simple test that (n,d,e) is a valid RSA key. + assertEquals(n, p.multiply(q)); + assertEquals(expectedKeySize, n.bitLength()); + int certainty = 80; + assertTrue(p.isProbablePrime(certainty)); + assertTrue(q.isProbablePrime(certainty)); + // Very simple checks for weak random number generators. + RandomUtil.checkPrime(p); + RandomUtil.checkPrime(q); + assertTrue(d.bitLength() > expectedKeySize / 2); + // TODO(bleichen): Keys that are very imbalanced can be broken with elliptic curve factoring. + // Add other checks. E.g. for the size of dp and dq + assertTrue(p.bitLength() > 256); + assertTrue(q.bitLength() > 256); + BigInteger p1 = p.subtract(BigInteger.ONE); + BigInteger q1 = q.subtract(BigInteger.ONE); + BigInteger phi = p1.multiply(q1); + BigInteger order = phi.divide(p1.gcd(q1)); // maximal order of elements + assertEquals(BigInteger.ONE, d.multiply(e).mod(order)); + assertEquals(d.mod(p1), dp.mod(p1)); + assertEquals(d.mod(q1), dq.mod(q1)); + assertEquals(q.multiply(crtCoeff).mod(p), BigInteger.ONE); + } + + private void checkPublicKey(RSAPublicKey pub, RSAPrivateKey priv) { + assertEquals(pub.getModulus(), priv.getModulus()); + BigInteger e = pub.getPublicExponent(); + // Checks that e > 1. [CVE-1999-1444] + assertEquals(e.compareTo(BigInteger.ONE), 1); + } + + private void checkKeyPair(KeyPair keypair, int keySizeInBits) throws Exception { + RSAPublicKey pub = (RSAPublicKey) keypair.getPublic(); + RSAPrivateKey priv = (RSAPrivateKey) keypair.getPrivate(); + if (priv instanceof RSAPrivateCrtKey) { + checkPrivateCrtKey((RSAPrivateCrtKey) priv, keySizeInBits); + } else { + // Using a CRT key leads to 6-7 times better performance than not using the CRT. + // Such a perfomance loss makes a library almost useless. Thus we consider this + // a bug. + fail("Expecting an RSAPrivateCrtKey instead of " + priv.getClass().getName()); + } + checkPublicKey(pub, priv); + } + + public void testKeyGenerationSize(int keySizeInBits) throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(keySizeInBits); + KeyPair keypair = keyGen.genKeyPair(); + checkKeyPair(keypair, keySizeInBits); + } + + public void testKeyGeneration() throws Exception { + testKeyGenerationSize(1024); + testKeyGenerationSize(2048); + } + + /** + * Checks whether decoding and again encoding an RSA public key results + * in the same encoding. + * This is a regression test. Failing this test implies that the encoding has changed. + * Such a failure does not need to be a bug, since several encoding for the same key are + * possible. + */ + public void testEncodeDecodePublic() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + byte[] encoded = TestUtil.hexToBytes(ENCODED_PUBLIC_KEY); + X509EncodedKeySpec spec = new X509EncodedKeySpec(encoded); + RSAPublicKey pub = (RSAPublicKey) kf.generatePublic(spec); + assertEquals("The test assumes that the public key is in X.509 format", + "X.509", pub.getFormat()); + assertEquals(ENCODED_PUBLIC_KEY, TestUtil.bytesToHex(pub.getEncoded())); + } +} -- cgit v1.2.3