aboutsummaryrefslogtreecommitdiff
path: root/java/com/google/security/wycheproof/testcases/DhiesTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/google/security/wycheproof/testcases/DhiesTest.java')
-rw-r--r--java/com/google/security/wycheproof/testcases/DhiesTest.java172
1 files changed, 172 insertions, 0 deletions
diff --git a/java/com/google/security/wycheproof/testcases/DhiesTest.java b/java/com/google/security/wycheproof/testcases/DhiesTest.java
new file mode 100644
index 0000000..2a4815c
--- /dev/null
+++ b/java/com/google/security/wycheproof/testcases/DhiesTest.java
@@ -0,0 +1,172 @@
+/**
+ * @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 com.google.security.wycheproof.WycheproofRunner.ProviderType;
+import com.google.security.wycheproof.WycheproofRunner.SlowTest;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Arrays;
+import javax.crypto.Cipher;
+import javax.crypto.spec.DHParameterSpec;
+import junit.framework.TestCase;
+
+/**
+ * Testing DHIES.
+ *
+ * @author bleichen@google.com (Daniel Bleichenbacher)
+ */
+// TODO(bleichen):
+// - maybe again CipherInputStream, CipherOutputStream,
+// - byteBuffer.
+// - Exception handling
+// - Is DHIES using the key derivation function for the key stream?
+// - BouncyCastle knows an algorithm IES. Is this the same as DHIES?
+// - Bouncy fixed a padding oracle bug in version 1.56 (CVE-2016-1000345)
+// So far we have no test for this bug mainly because this cannot be tested
+// through the JCA interface. BC does not register and algorithm such as
+// Cipher.DHIESWITHAES-CBC.
+// - So far only BouncyCastles is tesed because this is the only provider
+// we use that implements DHIES.
+public class DhiesTest extends TestCase {
+
+ // TODO(bleichen): This is the same as DhTest.java
+ // We could move this into some TestUtil.
+ public DHParameterSpec ike2048() {
+ final BigInteger p =
+ new BigInteger(
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
+ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF",
+ 16);
+ final BigInteger g = new BigInteger("2");
+ return new DHParameterSpec(p, g);
+ }
+
+ /**
+ * WARNING: This test uses weak crypto (i.e. DHIESWithAES), if supported. Checks that key
+ * agreement using DHIES works in the sense that it can decrypt what it encrypts. Unfortunately it
+ * seems that there is no secure mode using AES.
+ */
+ @SuppressWarnings("InsecureCryptoUsage")
+ public void testDhiesBasic() throws Exception {
+ DHParameterSpec params = ike2048();
+ KeyPairGenerator kf = KeyPairGenerator.getInstance("DH");
+ kf.initialize(params);
+ KeyPair keyPair = kf.generateKeyPair();
+ PrivateKey priv = keyPair.getPrivate();
+ PublicKey pub = keyPair.getPublic();
+ byte[] message = "Hello".getBytes("UTF-8");
+ Cipher dhies;
+ try {
+ dhies = Cipher.getInstance("DHIESwithAES");
+ } catch (NoSuchAlgorithmException ex) {
+ // The algorithm isn't supported - even better!
+ return;
+ }
+ dhies.init(Cipher.ENCRYPT_MODE, pub);
+ byte[] ciphertext = dhies.doFinal(message);
+ System.out.println("testDhiesBasic:" + TestUtil.bytesToHex(ciphertext));
+ dhies.init(Cipher.DECRYPT_MODE, priv);
+ byte[] decrypted = dhies.doFinal(ciphertext);
+ assertEquals(TestUtil.bytesToHex(message), TestUtil.bytesToHex(decrypted));
+ }
+
+ /**
+ * WARNING: This test uses weak crypto (i.e. DHIESWithAES). DHIES should be secure against chosen
+ * ciphertexts. Checks that a modification of the ciphertext is dectected.
+ */
+ @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE})
+ @SuppressWarnings("InsecureCryptoUsage")
+ public void testDhiesCorrupt() throws Exception {
+ KeyPairGenerator kf = KeyPairGenerator.getInstance("DH");
+ kf.initialize(ike2048());
+ KeyPair keyPair = kf.generateKeyPair();
+ PrivateKey priv = keyPair.getPrivate();
+ PublicKey pub = keyPair.getPublic();
+ byte[] message = new byte[32];
+ Cipher dhies;
+ try {
+ dhies = Cipher.getInstance("DHIESwithAES");
+ } catch (NoSuchAlgorithmException ex) {
+ // The algorithm isn't supported - even better!
+ return;
+ }
+ dhies.init(Cipher.ENCRYPT_MODE, pub);
+ byte[] ciphertext = dhies.doFinal(message);
+ for (int i = 0; i < ciphertext.length; i++) {
+ byte[] corrupt = Arrays.copyOf(ciphertext, ciphertext.length);
+ corrupt[i] ^= (byte) 1;
+ try {
+ dhies.init(Cipher.DECRYPT_MODE, priv);
+ dhies.doFinal(corrupt);
+ fail("Corrupt ciphertext accepted:" + i);
+ } catch (GeneralSecurityException ex) {
+ // This is expected
+ }
+ }
+ }
+
+ /**
+ * Tries to detect if an algorithm is using ECB. Unfortunately, many JCE algorithms use ECB if no
+ * encryption mode is specified.
+ */
+ @SuppressWarnings("InsecureCryptoUsage")
+ public void testNotEcb(String algorithm) throws Exception {
+ Cipher dhies;
+ try {
+ dhies = Cipher.getInstance(algorithm);
+ } catch (NoSuchAlgorithmException ex) {
+ // This test is called with short algorithm names such as just "DHIES".
+ // Requiring full names is typically a good practice. Hence it is OK
+ // to not assigning default algorithms.
+ System.out.println("No implementation for:" + algorithm);
+ return;
+ }
+ KeyPairGenerator kf = KeyPairGenerator.getInstance("DH");
+ kf.initialize(ike2048());
+ KeyPair keyPair = kf.generateKeyPair();
+ PublicKey pub = keyPair.getPublic();
+ byte[] message = new byte[512];
+ dhies.init(Cipher.ENCRYPT_MODE, pub);
+ byte[] ciphertext = dhies.doFinal(message);
+ for (int i = 0; i + 32 <= ciphertext.length; i++) {
+ String block1 = TestUtil.bytesToHex(Arrays.copyOfRange(ciphertext, i, i + 16));
+ String block2 = TestUtil.bytesToHex(Arrays.copyOfRange(ciphertext, i + 16, i + 32));
+ assertTrue(
+ "Ciphertext repeats at " + i + ":" + TestUtil.bytesToHex(ciphertext),
+ !block1.equals(block2));
+ }
+ }
+
+ public void testSemanticSecurityDhies() throws Exception {
+ testNotEcb("DHIES");
+ }
+}